diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-06 10:23:30 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-06 10:23:30 +0200 |
| commit | 75a7e10527f1588efa00677ee1f8f77591af0921 (patch) | |
| tree | 460fd68f12ebea1a4afecd4d0e450b9aae1c5692 /src | |
| parent | a50367194b486e0abbe05aaee34b961e202635ba (diff) | |
| download | lanes-75a7e10527f1588efa00677ee1f8f77591af0921.tar.gz lanes-75a7e10527f1588efa00677ee1f8f77591af0921.tar.bz2 lanes-75a7e10527f1588efa00677ee1f8f77591af0921.zip | |
Fix transfer of nil uservalues triggering a Lua API check because of conversion to nil sentinels in keeper states
Diffstat (limited to 'src')
| -rw-r--r-- | src/compat.cpp | 35 | ||||
| -rw-r--r-- | src/compat.h | 8 |
2 files changed, 24 insertions, 19 deletions
diff --git a/src/compat.cpp b/src/compat.cpp index 5923d29..3b026b4 100644 --- a/src/compat.cpp +++ b/src/compat.cpp | |||
| @@ -70,7 +70,7 @@ void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, in | |||
| 70 | // ################################################################################################# | 70 | // ################################################################################################# |
| 71 | // ################################################################################################# | 71 | // ################################################################################################# |
| 72 | 72 | ||
| 73 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, int nuvalue_) | 73 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, [[maybe_unused]] int nuvalue_) |
| 74 | { | 74 | { |
| 75 | LUA_ASSERT(L_, nuvalue_ <= 1); | 75 | LUA_ASSERT(L_, nuvalue_ <= 1); |
| 76 | return lua_newuserdata(L_, sz_); | 76 | return lua_newuserdata(L_, sz_); |
| @@ -81,26 +81,35 @@ void* lua_newuserdatauv(lua_State* L_, size_t sz_, int nuvalue_) | |||
| 81 | // push on stack uservalue #n of full userdata at idx | 81 | // push on stack uservalue #n of full userdata at idx |
| 82 | int lua_getiuservalue(lua_State* L_, int idx_, int n_) | 82 | int lua_getiuservalue(lua_State* L_, int idx_, int n_) |
| 83 | { | 83 | { |
| 84 | STACK_CHECK_START_REL(L_, 0); | ||
| 84 | // full userdata can have only 1 uservalue before 5.4 | 85 | // full userdata can have only 1 uservalue before 5.4 |
| 85 | if (n_ > 1) { | 86 | if (n_ > 1) { |
| 86 | lua_pushnil(L_); | 87 | lua_pushnil(L_); |
| 87 | return LUA_TNONE; | 88 | return LUA_TNONE; |
| 88 | } | 89 | } |
| 89 | lua_getuservalue(L_, idx_); | ||
| 90 | 90 | ||
| 91 | #if LUA_VERSION_NUM == 501 | 91 | #if LUA_VERSION_NUM == 501 |
| 92 | /* default environment is not a nil (see lua_getfenv) */ | 92 | lua_getfenv(L_, idx_); // L_: ... {}|nil |
| 93 | lua_getglobal(L_, LUA_LOADLIBNAME); | 93 | STACK_CHECK(L_, 1); |
| 94 | // default environment is not a nil (see lua_getfenv) | ||
| 95 | lua_getglobal(L_, LUA_LOADLIBNAME); // L_: ... {}|nil package | ||
| 94 | if (lua_rawequal(L_, -2, -1) || lua_rawequal(L_, -2, LUA_GLOBALSINDEX)) { | 96 | if (lua_rawequal(L_, -2, -1) || lua_rawequal(L_, -2, LUA_GLOBALSINDEX)) { |
| 95 | lua_pop(L_, 2); | 97 | lua_pop(L_, 2); // L_: ... |
| 96 | lua_pushnil(L_); | 98 | lua_pushnil(L_); // L_: ... nil |
| 97 | 99 | STACK_CHECK(L_, 1); | |
| 98 | return LUA_TNONE; | 100 | return LUA_TNONE; |
| 99 | } | 101 | } |
| 100 | lua_pop(L_, 1); /* remove package */ | 102 | else { |
| 101 | #endif | 103 | lua_pop(L_, 1); // L_: ... nil |
| 102 | 104 | } | |
| 103 | return lua_type(L_, -1); | 105 | #else // LUA_VERSION_NUM > 501 |
| 106 | lua_getuservalue(L_, idx_); // L_: {}|nil | ||
| 107 | #endif// LUA_VERSION_NUM > 501 | ||
| 108 | STACK_CHECK(L_, 1); | ||
| 109 | int const _uvType{ lua_type(L_, -1) }; | ||
| 110 | // under Lua 5.2, there is a single uservalue that is either nil or a table. | ||
| 111 | // If nil, don't transfer it, as it can cause issues when copying to a Keeper state because of nil sentinel conversion | ||
| 112 | return (LUA_VERSION_NUM == 502 && _uvType == LUA_TNIL) ? LUA_TNONE : _uvType; | ||
| 104 | } | 113 | } |
| 105 | 114 | ||
| 106 | // ################################################################################################# | 115 | // ################################################################################################# |
| @@ -118,7 +127,11 @@ int lua_setiuservalue(lua_State* L_, int idx_, int n_) | |||
| 118 | return 0; | 127 | return 0; |
| 119 | } | 128 | } |
| 120 | 129 | ||
| 130 | #if LUA_VERSION_NUM == 501 | ||
| 131 | lua_setfenv(L_, idx_); | ||
| 132 | #else // LUA_VERSION_NUM == 501 | ||
| 121 | lua_setuservalue(L_, idx_); | 133 | lua_setuservalue(L_, idx_); |
| 134 | #endif // LUA_VERSION_NUM == 501 | ||
| 122 | return 1; // I guess anything non-0 is ok | 135 | return 1; // I guess anything non-0 is ok |
| 123 | } | 136 | } |
| 124 | 137 | ||
diff --git a/src/compat.h b/src/compat.h index 6307d86..1789a8b 100644 --- a/src/compat.h +++ b/src/compat.h | |||
| @@ -67,14 +67,6 @@ inline void lua_pushglobaltable(lua_State* L_) | |||
| 67 | lua_pushvalue(L_, LUA_GLOBALSINDEX); | 67 | lua_pushvalue(L_, LUA_GLOBALSINDEX); |
| 68 | } | 68 | } |
| 69 | #endif // LUAJIT_VERSION_NUM | 69 | #endif // LUAJIT_VERSION_NUM |
| 70 | inline int lua_setuservalue(lua_State* L_, int idx_) | ||
| 71 | { | ||
| 72 | return lua_setfenv(L_, idx_); | ||
| 73 | } | ||
| 74 | inline void lua_getuservalue(lua_State* L_, int idx_) | ||
| 75 | { | ||
| 76 | lua_getfenv(L_, idx_); | ||
| 77 | } | ||
| 78 | inline size_t lua_rawlen(lua_State* L_, int idx_) | 70 | inline size_t lua_rawlen(lua_State* L_, int idx_) |
| 79 | { | 71 | { |
| 80 | return lua_objlen(L_, idx_); | 72 | return lua_objlen(L_, idx_); |
