ThePhD / sol2

Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:
http://sol2.rtfd.io/
MIT License
4.12k stars 500 forks source link

Segmentation fault when accessing objects inside a table with wrong type #1432

Closed dns13 closed 1 year ago

dns13 commented 1 year ago

Below program is crashing after throwing the exception when accessing "test2" with the incorrect type. Incorrectly accessing "test" is throwing as expected and program runs after that. The expected behavior I suggest would be just throw an exception and not crash afterwards.

I've tested this with sol 3.3.0 and Lua 5.3.6 and with sol 3.2.1 with Lua 5.3.5 (this is what compiler explorer is providing). It was working with the same Lua version before updating to sol3 with v2.20.6.

#include <limits>
#include <iostream>
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

auto main() -> int {
    sol::state lua;
    lua["object"] = lua.create_table_with("test2", 10);
    lua["test"] = 10;

    try {
        std::cout << lua["test"].get<int>() << std::endl;
        std::cout << lua["test"].get<std::string>() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "exception caught for test: " << e.what() << std::endl;
    }

    try {
        std::cout << lua["object"]["test2"].get<int>() << std::endl;
        std::cout << lua["object"]["test2"].get<std::string>() << std::endl;
    } catch (const std::exception& e) {
        std::cout << "exception caught for test2: " << e.what() << std::endl;
    }

    return 0;
}

Output:

Program returned: 139
munmap_chunk(): invalid pointer
10
exception caught for test: lua: error: stack index -1, expected string, received number
exception caught for test2: lua: error: attempt to index a string value

You can test it by yourself in compiler explorer: https://godbolt.org/z/ojbzMGsdf (not current sol2 version, but it fails in 3.3.0 as well)

The segfault is happening inside ltable.c at the marked Line:

static Node *mainposition (const Table *t, const TValue *key) {
  switch (ttype(key)) {
    case LUA_TNUMINT:
      return hashint(t, ivalue(key));
    case LUA_TNUMFLT:
      return hashmod(t, l_hashfloat(fltvalue(key)));
    case LUA_TSHRSTR:
      return hashstr(t, tsvalue(key));
    case LUA_TLNGSTR:
      return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
    case LUA_TBOOLEAN:
      return hashboolean(t, bvalue(key));
    case LUA_TLIGHTUSERDATA:
      return hashpointer(t, pvalue(key));
    case LUA_TLCF:
      return hashpointer(t, fvalue(key));
    default:
      lua_assert(!ttisdeadkey(key));
      return hashpointer(t, gcvalue(key)); // <----
  }
}

My current workaround is to check against the type before converting, but I relied on the exceptions on version v2.20.6 and I'm worried that I'm introducing crashes somewhere I'm currently not aware of.

dns13 commented 1 year ago

The issue persists with Lua 5.4.4 and develop branch of sol2.

roman-orekhov commented 1 year ago

This is expected behavior according to docs

dns13 commented 1 year ago

You are right, thank you.