Skip to content

Commit

Permalink
Merge Fix pointer value corruption (mr-631)
Browse files Browse the repository at this point in the history
  • Loading branch information
neptunium-cfx committed Dec 16, 2024
2 parents 894f9ac + 5a9fd5b commit 645f7c8
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ inline constexpr bool always_false_v = false;

enum class MetaField : uint8_t
{
PointerValueInteger,
PointerValueFloat,
PointerValueVector,
ReturnResultAnyway,
ResultAsInteger,
ResultAsLong,
Expand Down Expand Up @@ -328,11 +331,13 @@ CSCRC_INLINE void ScriptNativeContext::ProcessResult(Visitor&& visitor, const vo
}

case MetaField::ResultAsFloat:
case MetaField::PointerValueFloat:
{
return visitor(*static_cast<const float*>(value));
}

case MetaField::ResultAsVector:
case MetaField::PointerValueVector:
{
return visitor(*static_cast<const ScrVector*>(value));
}
Expand All @@ -343,6 +348,7 @@ CSCRC_INLINE void ScriptNativeContext::ProcessResult(Visitor&& visitor, const vo
}

case MetaField::ResultAsInteger:
case MetaField::PointerValueInteger:
{
return visitor(*static_cast<const int32_t*>(value));
}
Expand Down
14 changes: 11 additions & 3 deletions code/components/citizen-scripting-core/src/ScriptInvoker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ void ScriptNativeContext::PushReturnValue(MetaField field, const uintptr_t* valu
ScriptError("too many return value arguments");
}

int slots = (field == MetaField::ResultAsVector) ? 3 : 1;
int slots = (field == MetaField::PointerValueVector) ? 3 : 1;
size_t size = slots * sizeof(uintptr_t);

// COMPAT: Some code uses PointerValue arguments to act as struct output fields, so we need them to be stored contiguously in memory.
Expand Down Expand Up @@ -295,6 +295,14 @@ void ScriptNativeContext::PushMetaPointer(uint8_t* ptr)
// switch on the metafield
switch (metaField)
{
case MetaField::PointerValueInteger:
case MetaField::PointerValueFloat:
case MetaField::PointerValueVector:
{
PushReturnValue(metaField, nullptr);
break;
}

case MetaField::ReturnResultAnyway:
// We are going to return the result anyway if they've given us the type.
if (rettypes[0] == MetaField::Max)
Expand All @@ -317,7 +325,7 @@ void ScriptNativeContext::PushMetaPointer(uint8_t* ptr)
{
PointerField* field = reinterpret_cast<PointerField*>(ptr);

if (field->type == MetaField::ResultAsInteger || field->type == MetaField::ResultAsFloat || field->type == MetaField::ResultAsVector)
if (field->type == MetaField::PointerValueInteger || field->type == MetaField::PointerValueFloat || field->type == MetaField::PointerValueVector)
{
PushReturnValue(field->type, field->value);
}
Expand Down Expand Up @@ -670,7 +678,7 @@ void* ScriptNativeContext::GetMetaField(MetaField field)

void* ScriptNativeContext::GetPointerField(MetaField type, uintptr_t value)
{
assert(type == MetaField::ResultAsInteger || type == MetaField::ResultAsFloat || type == MetaField::ResultAsVector);
assert(type == MetaField::PointerValueInteger || type == MetaField::PointerValueFloat || type == MetaField::PointerValueVector);

PointerField* entry = &s_pointerFields[s_pointerFieldIndex];
s_pointerFieldIndex = (s_pointerFieldIndex + 1) % std::size(s_pointerFields);
Expand Down
43 changes: 20 additions & 23 deletions code/components/citizen-scripting-lua/src/LuaScriptRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,29 +744,26 @@ static int Lua_ResultAsObject(lua_State* L)
return Lua_GetMetaField<MetaField::ResultAsObject>(L);
}

template<MetaField field, bool init>
template<MetaField field>
static int Lua_GetPointerField(lua_State* L)
{
uintptr_t value = 0;

if (init)
{
const int type = lua_type(L, 1);
const int type = lua_type(L, 1);

// to prevent accidental passing of arguments like _r, we check if this is a userdata
if (type == LUA_TNIL || type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA)
{
value = 0;
}
else if constexpr (field == MetaField::ResultAsInteger)
{
value = (uint64_t)luaL_checkinteger(L, 1);
}
else if constexpr (field == MetaField::ResultAsFloat)
{
float fvalue = static_cast<float>(luaL_checknumber(L, 1));
value = *reinterpret_cast<uint32_t*>(&value);
}
// to prevent accidental passing of arguments like _r, we check if this is a userdata
if (type == LUA_TNIL || type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA)
{
value = 0;
}
else if constexpr (field == MetaField::PointerValueInteger)
{
value = (uint64_t)luaL_checkinteger(L, 1);
}
else if constexpr (field == MetaField::PointerValueFloat)
{
float fvalue = static_cast<float>(luaL_checknumber(L, 1));
value = *reinterpret_cast<uint32_t*>(&value);
}

lua_pushlightuserdata(L, ScriptNativeContext::GetPointerField(field, value));
Expand Down Expand Up @@ -1185,11 +1182,11 @@ static const struct luaL_Reg g_citizenLib[] = {
{ "SubmitBoundaryEnd", Lua_SubmitBoundaryEnd },
{ "SetStackTraceRoutine", Lua_SetStackTraceRoutine },
// metafields
{ "PointerValueIntInitialized", Lua_GetPointerField<MetaField::ResultAsInteger, true> },
{ "PointerValueFloatInitialized", Lua_GetPointerField<MetaField::ResultAsFloat, true> },
{ "PointerValueInt", Lua_GetPointerField<MetaField::ResultAsInteger, false> },
{ "PointerValueFloat", Lua_GetPointerField<MetaField::ResultAsFloat, false> },
{ "PointerValueVector", Lua_GetPointerField<MetaField::ResultAsVector, false> },
{ "PointerValueIntInitialized", Lua_GetPointerField<MetaField::PointerValueInteger> },
{ "PointerValueFloatInitialized", Lua_GetPointerField<MetaField::PointerValueFloat> },
{ "PointerValueInt", Lua_GetMetaField<MetaField::PointerValueInteger> },
{ "PointerValueFloat", Lua_GetMetaField<MetaField::PointerValueFloat> },
{ "PointerValueVector", Lua_GetMetaField<MetaField::PointerValueVector> },
{ "ReturnResultAnyway", Lua_GetMetaField<MetaField::ReturnResultAnyway> },
{ "ResultAsInteger", Lua_GetMetaField<MetaField::ResultAsInteger> },
{ "ResultAsLong", Lua_GetMetaField<MetaField::ResultAsLong> },
Expand Down
35 changes: 16 additions & 19 deletions code/components/citizen-scripting-v8/src/V8ScriptRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1352,28 +1352,25 @@ static void V8_GetMetaField(const v8::FunctionCallbackInfo<v8::Value>& args)
args.GetReturnValue().Set(External::New(GetV8Isolate(), ScriptNativeContext::GetMetaField(field)));
}

template<MetaField field, bool init>
template<MetaField field>
static void V8_GetPointerField(const v8::FunctionCallbackInfo<v8::Value>& args)
{
V8ScriptRuntime* runtime = GetScriptRuntimeFromArgs(args);

uintptr_t value = 0;

if (init)
{
auto arg = args[0];
auto arg = args[0];

if constexpr (field == MetaField::ResultAsInteger)
{
value = (uint64_t)arg->IntegerValue(runtime->GetContext()).ToChecked();
}
else if constexpr (field == MetaField::ResultAsFloat)
{
float fvalue = static_cast<float>(arg->NumberValue(runtime->GetContext()).ToChecked());
value = *reinterpret_cast<uint32_t*>(&value);
}
if constexpr (field == MetaField::PointerValueInteger)
{
value = (uint64_t)arg->IntegerValue(runtime->GetContext()).ToChecked();
}

else if constexpr (field == MetaField::PointerValueFloat)
{
float fvalue = static_cast<float>(arg->NumberValue(runtime->GetContext()).ToChecked());
value = *reinterpret_cast<uint32_t*>(&value);
}

args.GetReturnValue().Set(External::New(GetV8Isolate(), ScriptNativeContext::GetPointerField(field, value)));
}

Expand Down Expand Up @@ -1553,11 +1550,11 @@ static std::pair<std::string, FunctionCallback> g_citizenFunctions[] =
{ "submitBoundaryEnd", V8_SubmitBoundaryEnd },
{ "setStackTraceFunction", V8_SetStackTraceRoutine },
// metafields
{ "pointerValueIntInitialized", V8_GetPointerField<MetaField::ResultAsInteger, true> },
{ "pointerValueFloatInitialized", V8_GetPointerField<MetaField::ResultAsFloat, true> },
{ "pointerValueInt", V8_GetPointerField<MetaField::ResultAsInteger, false> },
{ "pointerValueFloat", V8_GetPointerField<MetaField::ResultAsFloat, false> },
{ "pointerValueVector", V8_GetPointerField<MetaField::ResultAsVector, false> },
{ "pointerValueIntInitialized", V8_GetPointerField<MetaField::PointerValueInteger> },
{ "pointerValueFloatInitialized", V8_GetPointerField<MetaField::PointerValueFloat> },
{ "pointerValueInt", V8_GetMetaField<MetaField::PointerValueInteger> },
{ "pointerValueFloat", V8_GetMetaField<MetaField::PointerValueFloat> },
{ "pointerValueVector", V8_GetMetaField<MetaField::PointerValueVector> },
{ "returnResultAnyway", V8_GetMetaField<MetaField::ReturnResultAnyway> },
{ "resultAsInteger", V8_GetMetaField<MetaField::ResultAsInteger> },
{ "resultAsLong", V8_GetMetaField<MetaField::ResultAsLong> },
Expand Down

0 comments on commit 645f7c8

Please sign in to comment.