Skip to content

Bug in how ULuaState::FromFProperty() handles map properties #70

@hanoixan

Description

@hanoixan

Using: Windows 11, Unreal Engine 5.2, Visual Studio 2022, LuaMachine 20240424

In LuaState.cpp:2196, in the handler for FMapProperty properties, it iterates over all map pairs with this code:

			uint8* ArrayKeyPtr = Helper.GetKeyPtr(MapIndex);
			uint8* ArrayValuePtr = Helper.GetValuePtr(MapIndex);
			bool bArrayItemSuccess = false;
			NewLuaTable.SetField(
				FromProperty(ArrayKeyPtr, MapProperty->KeyProp, bArrayItemSuccess, 0).ToString(),
				FromProperty(ArrayValuePtr, MapProperty->ValueProp, bArrayItemSuccess, 0));

After investigating a crash, I determined that the map item pair's FProperty::Offset_Internal is being computed by both GetValuePtr() and the MapProperty->ValueProp being used in the second FromProperty() call. Because the ArrayValuePtr from the first offset is being used to compute the second FromProperty, it overshoots the value offset and causes a crash.

The best workaround I can see is the following:

			uint8* ArrayPairPtr = Helper.GetPairPtr(MapIndex);
			bool bArrayItemSuccess = false;
			NewLuaTable.SetField(
				FromProperty(ArrayPairPtr, MapProperty->KeyProp, bArrayItemSuccess, 0).ToString(),
				FromProperty(ArrayPairPtr, MapProperty->ValueProp, bArrayItemSuccess, 0));

This uses the pair's ptr as the base of the offset math, which works because the key offset is 0. It's not possible for me to create a fork and PR at this time, so I'm just inlining the simple code change here for your consideration.

To reproduce this, simply run something like this:

// declare

USTRUCT(BlueprintType)
struct WAVESCENEOBJECTS_API FMyLuaFunctionContext
{
	GENERATED_BODY()

	UPROPERTY()
	TMap<FString, FLuaValue> Config;
};

// and then try to turn a populated instance of this into an FLuaValue:

FLuaValue TestMapSerialization(ULuaState& LuaState, FString& Key, FLuaValue& Value)
{
	FMyLuaFunctionContext Context;
	Context.Config.Add(Key, Value);

	FLuaValue ReturnValue = LuaState.StructToLuaValue(Context); // Crash
	return ReturnValue;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions