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.06k stars 492 forks source link

Strange compile error related to length of string sent to sol::table.get<T> #1535

Open FranchescaMullin opened 9 months ago

FranchescaMullin commented 9 months ago

Hi, thanks for making a great library. I am a bit puzzled by a strange compile error I am getting right now. Not sure if I am doing something silly or if this is really a bug?

Here are some details:

configis of type const sol::table& config and is passed to the example code as a parameter in a method

This compiles fine: sol::optional<std::string> currency = config.get<sol::optional<std::string>>("currencyyyyyy"); But this line gives a compile error: sol::optional<std::string> currency = config.get<sol::optional<std::string>>("currency");

I played around, and basically the field name passed to .get must be > 9 chars or it will not compile. Example error:

In file included from /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack.hpp:35,
                 from /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/sol.hpp:52,
                 from redacted,
                 from redacted
In member function 'void sol::stack::field_getter<T, global, raw, <template-parameter-1-4> >::get(lua_State*, Key&&, int) [with Key = const char (&)[11]; T = char [11]; bool global = false; bool raw = false; <template-parameter-1-4> = void]',
    inlined from 'void sol::stack::get_field(lua_State*, Key&&, int) [with bool global = false; bool raw = false; Key = const char (&)[11]]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack_core.hpp:1210:62,
    inlined from 'sol::stack::probe sol::stack::probe_field_getter<T, P, global, raw, <template-parameter-1-5> >::get(lua_State*, Key&&, int) [with Key = const char (&)[11]; T = char [11]; P = std::basic_string<char>; bool b = false; bool raw = false; <template-parameter-1-5> = void]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack_probe.hpp:41:21,
    inlined from 'sol::stack::probe sol::stack::probe_field_getter<T, P, global, raw, <template-parameter-1-5> >::get(lua_State*, Key&&, int) [with Key = const char (&)[9]; T = char [9]; P = std::basic_string<char>; bool b = false; bool raw = false; <template-parameter-1-5> = void]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack_probe.hpp:35:9,
    inlined from 'sol::stack::probe sol::stack::probe_get_field(lua_State*, Key&&, int) [with bool global = false; bool raw = false; C = std::basic_string<char>; Key = const char (&)[9]]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack_core.hpp:1230:78,
    inlined from 'decltype(auto) sol::basic_table_core<<anonymous>, <template-parameter-1-2> >::traverse_get_deep_optional(int&, int, Key&&, Keys&& ...) const [with bool global = false; bool raw = false; sol::detail::insert_mode mode = sol::detail::none; T = sol::optional<std::basic_string<char> >; Key = const char (&)[9]; Keys = {}; bool top_level = false; ref_t = sol::basic_reference<false>]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/table_core.hpp:217:62,
    inlined from 'decltype(auto) sol::basic_table_core<<anonymous>, <template-parameter-1-2> >::traverse_get_single(int, Keys&& ...) const [with bool raw = false; Ret = sol::optional<std::basic_string<char> >; Keys = {const char (&)[9]}; bool top_level = false; ref_t = sol::basic_reference<false>]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/table_core.hpp:123:134,
    inlined from 'decltype(auto) sol::basic_table_core<<anonymous>, <template-parameter-1-2> >::traverse_get_single_maybe_tuple(int, Key&&) const [with bool raw = false; Ret = sol::optional<std::basic_string<char> >; Key = const char (&)[9]; bool top_level = false; ref_t = sol::basic_reference<false>]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/table_core.hpp:113:77,
    inlined from 'decltype(auto) sol::basic_table_core<<anonymous>, <template-parameter-1-2> >::tuple_get(int, Keys&& ...) const [with bool raw = false; Ret = {sol::optional<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >}; Keys = {const char (&)[9]}; bool top_level = false; ref_t = sol::basic_reference<false>]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/table_core.hpp:93:97,
    inlined from 'decltype(auto) sol::basic_table_core<<anonymous>, <template-parameter-1-2> >::get(Keys&& ...) const [with Ret = {sol::optional<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >}; Keys = {const char (&)[9]}; bool top_level = false; ref_t = sol::basic_reference<false>]' at /home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/table_core.hpp:422:76,
    inlined from 'std::optional<std::basic_string<char> > redacted::redactedMethodName(const std::string&, const sol::table&)' at /home/redacted.cpp:235:92:
/home/redacted/.conan/data/sol2/3.3.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/sol/stack_field.hpp:116:61: error: array subscript 'const char [11][0]' is partly outside array bounds of 'const char [9]' [-Werror=array-bounds]
  116 |                                                 lua_getfield(L, tableindex, &key[0]);
      |                                                 ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[2]: *** [service/CMakeFiles/service_library.dir/build.make:188: service/CMakeFiles/redacted.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:900: redacted/CMakeFiles/redacted_library.dir/all] Error 2
make: *** [Makefile:146: all] Error 2

Include Compiler/IDE (Visual Studio, XCode...), Build and Deployment System, Language (C++, Objective-C++), and any special defines you have set:

[settings]
arch=x86_64
arch_build=x86_64
build_type=RelWithDebInfo
compiler=gcc
compiler.version=12
compiler.libcxx=libstdc++
os=Linux
os_build=Linux

[options]

[build_requires]

[env]
mattwigway commented 6 months ago

I think this may be caused by a GCC bug. It looks like the GCC static analyzer is seeing that somewhere the function gets called with a null-terminated string of a certain length (30 in my case, I guess 10 with the null terminator in yours), and reads the whole thing, and assumes it will always read that many bytes. @FranchescaMullin is there somewhere else in your program where you have a nine-character argument to .get?

FranchescaMullin commented 6 months ago

You are definitely on to something!

My first call to get is the following (10 characters long): sol::optional<std::string> pricerType = config.get<sol::optional<std::string>>("pricerType");

As an experiment to test your theory, I tried to compile it with the field name lengthened to 17 chars: sol::optional<std::string> pricerType = config.get<sol::optional<std::string>>("pricerTypezzzzzzz"); and I get the following error: /redacted/include/sol/stack_field.hpp:116:61: error: array subscript ‘const char [18][0]’ is partly outside array bounds of ‘const char [17]’ [-Werror=array-bounds] 116 | lua_getfield(L, tableindex, &key[0]); The line of code generating the error is as follows (16 chars long): config.get<sol::optional<std::string>>("frontMonthSymbol");

If I drop the number of chars in the first call to get to 16 chars, the whole thing compiles fine.