When calling a C function from Lua, the stack is guaranteed to have a minimum size of LUA_MINSTACK which is 20 for PUC-Rio Lua. If you want to push more values than this, you have to call lua_checkstack to make sure that the stack has enough room and needs to grow if it's too small.
Here is a (very contrived) small example where this can be reproduced:
#include <iostream>
#include <tuple>
#define SOL_CHECK_ARGUMENTS 1
#include <sol.hpp>
int main() {
sol::state L;
std::cout << "Good :)\n";
L["good"] = []() {
return std::make_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36);
};
L.script("good()");
std::cout << "Bad :(\n";
L["bad"] = []() {
return std::make_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37);
};
L.script("bad()");
}
On my machine with Lua 5.3 I get
$ clang++ -Wall -Wextra -Wpedantic -I Code/sol2/ -I /usr/include/lua5.3/ test.cpp -llua5.3
$ ./a.out
Good :)
Bad :(
munmap_chunk(): invalid pointer
Aborted
This is a security critical issue because Lua is usually used to run user provided code and overflowing the stack pointer can be exploited for out of bounds reads and writes. This has actually led to real world bugs (not using Sol2 though) in e.g. Redis (see https://github.com/antirez/redis/commit/52a00201).
This implies that every lua_push<whatever> needs to be prefixed by lua_checkstack (unless you know for sure that you will not exceed 20 items on the stack). Could you please provide a preprocessor option (maybe SOL_CHECK_STACK, similar to SOL_CHECK_ARGUMENTS) to toggle stack protection?
Sure, I'll add it to the list of things sol3 needs.
As a side note, I think this will only apply when doing function calls and returns through the sol::stack::call API, wherein I'll insert the necessary cleaning and culling right there. This makes my life easier since I don't think I have to sprinkle it throughout the entire API.
Ostensibly, I could also put it in stack::push. This would be hyper-paranoid, and check even your usage of the C API to make sure you're not blowing things up... I might need 2 defines. SOL_CHECK_CALL_STACK and SOL_CHECK_STACK, where the former is only the call stack and the latter checks every single push...
I have the version that checks every single push, but I don't know what to do.
Am I supposed to use luaL_checkstack to force the stack to grow? Or, should I be using lua_checkstack and then throwing an error if there is not enough space? Automatically growing seems like the wrong answer, so I'll probably do the latter...
lua_checkstack(L, n) automatically grows the stack to accommodate n elements and only returns false if it can't grow in which case you should raise an error.
Well, it says it never goes beyond a fixed maximum size so, I suppose I can live with that?

We're all set.
Most helpful comment
Sure, I'll add it to the list of things sol3 needs.