diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-02 11:24:10 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-02 11:24:10 +0200 |
| commit | 66499a912cbf7ca0205b68a17b430070ef94bc49 (patch) | |
| tree | 7b7f3d4873e44311063063436fbdca65b194f73a /src | |
| parent | 84889233bfec4ad11ee1160fe63acbbbba7275e7 (diff) | |
| download | lanes-66499a912cbf7ca0205b68a17b430070ef94bc49.tar.gz lanes-66499a912cbf7ca0205b68a17b430070ef94bc49.tar.bz2 lanes-66499a912cbf7ca0205b68a17b430070ef94bc49.zip | |
InterCopyContext always raises errors in a non-Keeper state
Diffstat (limited to 'src')
| -rw-r--r-- | src/deep.cpp | 16 | ||||
| -rw-r--r-- | src/tools.cpp | 31 | ||||
| -rw-r--r-- | src/tools.h | 4 |
3 files changed, 26 insertions, 25 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index a824f72..735a14c 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
| @@ -381,7 +381,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
| 381 | STACK_CHECK_START_REL(L1, 0); | 381 | STACK_CHECK_START_REL(L1, 0); |
| 382 | STACK_CHECK_START_REL(L2, 0); | 382 | STACK_CHECK_START_REL(L2, 0); |
| 383 | 383 | ||
| 384 | // extract all uservalues of the source | 384 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
| 385 | int nuv = 0; | 385 | int nuv = 0; |
| 386 | while (lua_getiuservalue(L1, L1_i, nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil | 386 | while (lua_getiuservalue(L1, L1_i, nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil |
| 387 | ++nuv; | 387 | ++nuv; |
| @@ -391,7 +391,10 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
| 391 | STACK_CHECK(L1, nuv); | 391 | STACK_CHECK(L1, nuv); |
| 392 | 392 | ||
| 393 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 393 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
| 394 | char const* errmsg{ DeepFactory::PushDeepProxy(L2, u, nuv, mode) }; // L2: u | 394 | char const* errmsg{ DeepFactory::PushDeepProxy(L2, u, nuv, mode) }; // L1: ... u [uv]* L2: u |
| 395 | if (errmsg != nullptr) { | ||
| 396 | raise_luaL_error(getErrL(), errmsg); | ||
| 397 | } | ||
| 395 | 398 | ||
| 396 | // transfer all uservalues of the source in the destination | 399 | // transfer all uservalues of the source in the destination |
| 397 | { | 400 | { |
| @@ -399,8 +402,8 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
| 399 | int const clone_i{ lua_gettop(L2) }; | 402 | int const clone_i{ lua_gettop(L2) }; |
| 400 | while (nuv) { | 403 | while (nuv) { |
| 401 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 404 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
| 402 | if (!c.inter_copy_one()) { // L2: u uv | 405 | if (!c.inter_copy_one()) { // L1: ... u [uv]* L2: u uv |
| 403 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 406 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
| 404 | } | 407 | } |
| 405 | lua_pop(L1, 1); // L1: ... u [uv]* | 408 | lua_pop(L1, 1); // L1: ... u [uv]* |
| 406 | // this pops the value from the stack | 409 | // this pops the value from the stack |
| @@ -412,10 +415,5 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
| 412 | STACK_CHECK(L2, 1); | 415 | STACK_CHECK(L2, 1); |
| 413 | STACK_CHECK(L1, 0); | 416 | STACK_CHECK(L1, 0); |
| 414 | 417 | ||
| 415 | if (errmsg != nullptr) { | ||
| 416 | // raise the error in the proper state (not the keeper) | ||
| 417 | lua_State* const errL{ (mode == LookupMode::FromKeeper) ? L2 : L1 }; | ||
| 418 | raise_luaL_error(errL, errmsg); | ||
| 419 | } | ||
| 420 | return true; | 418 | return true; |
| 421 | } \ No newline at end of file | 419 | } \ No newline at end of file |
diff --git a/src/tools.cpp b/src/tools.cpp index 0495561..a55ee75 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -616,7 +616,7 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | |||
| 616 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error | 616 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
| 617 | switch (mode) { | 617 | switch (mode) { |
| 618 | default: // shouldn't happen, in theory... | 618 | default: // shouldn't happen, in theory... |
| 619 | raise_luaL_error(L1, "internal error: unknown lookup mode"); | 619 | raise_luaL_error(getErrL(), "internal error: unknown lookup mode"); |
| 620 | break; | 620 | break; |
| 621 | 621 | ||
| 622 | case LookupMode::ToKeeper: | 622 | case LookupMode::ToKeeper: |
| @@ -646,9 +646,8 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; | |||
| 646 | lua_getglobal(L2, "decoda_name"); // L1: ... t ... L2: {} t decoda_name | 646 | lua_getglobal(L2, "decoda_name"); // L1: ... t ... L2: {} t decoda_name |
| 647 | to = lua_tostring(L2, -1); | 647 | to = lua_tostring(L2, -1); |
| 648 | lua_pop(L2, 1); // L1: ... t ... L2: {} t | 648 | lua_pop(L2, 1); // L1: ... t ... L2: {} t |
| 649 | // when mode_ == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | ||
| 650 | raise_luaL_error( | 649 | raise_luaL_error( |
| 651 | (mode == LookupMode::FromKeeper) ? L2 : L1, | 650 | getErrL(), |
| 652 | "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database.", | 651 | "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database.", |
| 653 | from ? from : "main", | 652 | from ? from : "main", |
| 654 | fqn, | 653 | fqn, |
| @@ -889,7 +888,7 @@ void InterCopyContext::lookup_native_func() const | |||
| 889 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error | 888 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
| 890 | switch (mode) { | 889 | switch (mode) { |
| 891 | default: // shouldn't happen, in theory... | 890 | default: // shouldn't happen, in theory... |
| 892 | raise_luaL_error(L1, "internal error: unknown lookup mode"); | 891 | raise_luaL_error(getErrL(), "internal error: unknown lookup mode"); |
| 893 | break; | 892 | break; |
| 894 | 893 | ||
| 895 | case LookupMode::ToKeeper: | 894 | case LookupMode::ToKeeper: |
| @@ -916,7 +915,7 @@ void InterCopyContext::lookup_native_func() const | |||
| 916 | lua_pop(L2, 1); // L2: {} f | 915 | lua_pop(L2, 1); // L2: {} f |
| 917 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 916 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
| 918 | raise_luaL_error( | 917 | raise_luaL_error( |
| 919 | (mode == LookupMode::FromKeeper) ? L2 : L1 | 918 | getErrL() |
| 920 | , "%s%s: function '%s' not found in %s destination transfer database." | 919 | , "%s%s: function '%s' not found in %s destination transfer database." |
| 921 | , lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN " | 920 | , lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN " |
| 922 | , from ? from : "main" | 921 | , from ? from : "main" |
| @@ -1010,7 +1009,7 @@ void InterCopyContext::copy_func() const | |||
| 1010 | luaL_Buffer B; | 1009 | luaL_Buffer B; |
| 1011 | B.L = nullptr; | 1010 | B.L = nullptr; |
| 1012 | if (lua504_dump(L1, buf_writer, &B, 0) != 0) { | 1011 | if (lua504_dump(L1, buf_writer, &B, 0) != 0) { |
| 1013 | raise_luaL_error(L1, "internal error: function dump failed."); | 1012 | raise_luaL_error(getErrL(), "internal error: function dump failed."); |
| 1014 | } | 1013 | } |
| 1015 | 1014 | ||
| 1016 | // pushes dumped string on 'L1' | 1015 | // pushes dumped string on 'L1' |
| @@ -1054,7 +1053,7 @@ void InterCopyContext::copy_func() const | |||
| 1054 | // "Otherwise, it pushes an error message" | 1053 | // "Otherwise, it pushes an error message" |
| 1055 | // | 1054 | // |
| 1056 | STACK_GROW(L1, 1); | 1055 | STACK_GROW(L1, 1); |
| 1057 | raise_luaL_error(L1, "%s: %s", fname, lua_tostring(L2, -1)); | 1056 | raise_luaL_error(getErrL(), "%s: %s", fname, lua_tostring(L2, -1)); |
| 1058 | } | 1057 | } |
| 1059 | // remove the dumped string | 1058 | // remove the dumped string |
| 1060 | lua_pop(L1, 1); // ... | 1059 | lua_pop(L1, 1); // ... |
| @@ -1094,7 +1093,7 @@ void InterCopyContext::copy_func() const | |||
| 1094 | DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); | 1093 | DEBUGSPEW_CODE(fprintf(stderr, "copying value\n")); |
| 1095 | c.L1_i = SourceIndex{ lua_gettop(L1) }; | 1094 | c.L1_i = SourceIndex{ lua_gettop(L1) }; |
| 1096 | if (!c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> | 1095 | if (!c.inter_copy_one()) { // L2: ... {cache} ... function <upvalues> |
| 1097 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1096 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
| 1098 | } | 1097 | } |
| 1099 | } | 1098 | } |
| 1100 | lua_pop(L1, 1); // L1: ... _G | 1099 | lua_pop(L1, 1); // L1: ... _G |
| @@ -1196,7 +1195,7 @@ void InterCopyContext::copy_cached_func() const | |||
| 1196 | lua_pop(L2, 1); // L2: _R[kMtIdRegKey] | 1195 | lua_pop(L2, 1); // L2: _R[kMtIdRegKey] |
| 1197 | InterCopyContext const c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name }; | 1196 | InterCopyContext const c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name }; |
| 1198 | if (!c.inter_copy_one()) { // L2: _R[kMtIdRegKey] mt? | 1197 | if (!c.inter_copy_one()) { // L2: _R[kMtIdRegKey] mt? |
| 1199 | raise_luaL_error(L1, "Error copying a metatable"); | 1198 | raise_luaL_error(getErrL(), "Error copying a metatable"); |
| 1200 | } | 1199 | } |
| 1201 | 1200 | ||
| 1202 | STACK_CHECK(L2, 2); // L2: _R[kMtIdRegKey] mt | 1201 | STACK_CHECK(L2, 2); // L2: _R[kMtIdRegKey] mt |
| @@ -1275,7 +1274,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1275 | LUA_ASSERT(L1, lua_istable(L2, -3)); | 1274 | LUA_ASSERT(L1, lua_istable(L2, -3)); |
| 1276 | lua_rawset(L2, -3); // add to table (pops key & val) | 1275 | lua_rawset(L2, -3); // add to table (pops key & val) |
| 1277 | } else { | 1276 | } else { |
| 1278 | raise_luaL_error(L1, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, val_i)); | 1277 | raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, val_i)); |
| 1279 | } | 1278 | } |
| 1280 | } | 1279 | } |
| 1281 | 1280 | ||
| @@ -1342,7 +1341,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1342 | } | 1341 | } |
| 1343 | STACK_CHECK(L2, 1); | 1342 | STACK_CHECK(L2, 1); |
| 1344 | } else { | 1343 | } else { |
| 1345 | raise_luaL_error(L1, "Error copying a metatable"); | 1344 | raise_luaL_error(getErrL(), "Error copying a metatable"); |
| 1346 | } | 1345 | } |
| 1347 | // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel | 1346 | // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel |
| 1348 | lua_pushlightuserdata(L2, source); // L2: ... u source | 1347 | lua_pushlightuserdata(L2, source); // L2: ... u source |
| @@ -1356,7 +1355,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1356 | while (uvi > 0) { | 1355 | while (uvi > 0) { |
| 1357 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 1356 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
| 1358 | if (!c.inter_copy_one()) { // L2: ... u uv | 1357 | if (!c.inter_copy_one()) { // L2: ... u uv |
| 1359 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1358 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
| 1360 | } | 1359 | } |
| 1361 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* | 1360 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]* |
| 1362 | // this pops the value from the stack | 1361 | // this pops the value from the stack |
| @@ -1419,7 +1418,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1419 | void* const lud{ lua_touserdata(L1, L1_i) }; | 1418 | void* const lud{ lua_touserdata(L1, L1_i) }; |
| 1420 | lua_pushlightuserdata(L2, lud); | 1419 | lua_pushlightuserdata(L2, lud); |
| 1421 | } else { // raise an error | 1420 | } else { // raise an error |
| 1422 | raise_luaL_error(L1, "can't copy non-deep full userdata across lanes"); | 1421 | raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes"); |
| 1423 | } | 1422 | } |
| 1424 | 1423 | ||
| 1425 | STACK_CHECK(L2, 1); | 1424 | STACK_CHECK(L2, 1); |
| @@ -1489,7 +1488,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1489 | while (uvi > 0) { | 1488 | while (uvi > 0) { |
| 1490 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; | 1489 | c.L1_i = SourceIndex{ lua_absindex(L1, -1) }; |
| 1491 | if (!c.inter_copy_one()) { // L2: ... mt u uv | 1490 | if (!c.inter_copy_one()) { // L2: ... mt u uv |
| 1492 | raise_luaL_error(L1, "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 1491 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
| 1493 | } | 1492 | } |
| 1494 | lua_pop(L1, 1); // L1: ... u [uv]* | 1493 | lua_pop(L1, 1); // L1: ... u [uv]* |
| 1495 | // this pops the value from the stack | 1494 | // this pops the value from the stack |
| @@ -1827,7 +1826,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1827 | STACK_CHECK(L1, 1); | 1826 | STACK_CHECK(L1, 1); |
| 1828 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1827 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 1829 | if (mode == LookupMode::LaneBody) { | 1828 | if (mode == LookupMode::LaneBody) { |
| 1830 | raise_lua_error(L1); | 1829 | raise_lua_error(getErrL()); |
| 1831 | } | 1830 | } |
| 1832 | return InterCopyResult::Error; | 1831 | return InterCopyResult::Error; |
| 1833 | } | 1832 | } |
| @@ -1864,7 +1863,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 1864 | lua_pushfstring(L1, "failed to copy package entry %s", entry); | 1863 | lua_pushfstring(L1, "failed to copy package entry %s", entry); |
| 1865 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 1864 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 1866 | if (mode == LookupMode::LaneBody) { | 1865 | if (mode == LookupMode::LaneBody) { |
| 1867 | raise_lua_error(L1); | 1866 | raise_lua_error(getErrL()); |
| 1868 | } | 1867 | } |
| 1869 | lua_pop(L1, 1); | 1868 | lua_pop(L1, 1); |
| 1870 | break; | 1869 | break; |
diff --git a/src/tools.h b/src/tools.h index f5fdabc..9d4ed4c 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -42,6 +42,10 @@ class InterCopyContext | |||
| 42 | char const* name; // that one can change when we reuse the context | 42 | char const* name; // that one can change when we reuse the context |
| 43 | 43 | ||
| 44 | private: | 44 | private: |
| 45 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | ||
| 46 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error | ||
| 47 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } | ||
| 48 | |||
| 45 | // for use in copy_cached_func | 49 | // for use in copy_cached_func |
| 46 | void copy_func() const; | 50 | void copy_func() const; |
| 47 | void lookup_native_func() const; | 51 | void lookup_native_func() const; |
