From 663a44a7fea7602b894160ec0608bca378c97d10 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Thu, 8 Jul 2021 14:55:04 +0200 Subject: fix function transfer with lua_dump for Lua 5.4 failing for functions big enough to necessitate a buffer reallocation --- src/lanes.h | 2 +- src/tools.c | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/lanes.h b/src/lanes.h index 1a38ba5..41a6b73 100644 --- a/src/lanes.h +++ b/src/lanes.h @@ -12,7 +12,7 @@ #define LANES_VERSION_MAJOR 3 #define LANES_VERSION_MINOR 15 -#define LANES_VERSION_PATCH 0 +#define LANES_VERSION_PATCH 1 #define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH)))) #define LANES_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR replaced by the result) + luaL_pushresult( &b); // ... {} ... "" STACK_END( L, 1); return lua_tolstring( L, -1, length); } @@ -631,14 +633,6 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) return id; } - -static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) { - (void)L; - luaL_addlstring((luaL_Buffer*) B, (const char *)b, n); - return 0; -} - - // function sentinel used to transfer native functions from/to keeper states static int func_lookup_sentinel( lua_State* L) { @@ -1138,14 +1132,32 @@ static char const* vt_names[] = }; #endif // USE_DEBUG_SPEW +// Lua 5.4.3 style of dumping (see lstrlib.c) +// we have to do it that way because we can't unbalance the stack between buffer operations +// namely, this means we can't push a function on top of the stack *after* we initialize the buffer! +// luckily, this also works with earlier Lua versions +static int buf_writer( lua_State* L, void const* b, size_t size, void* ud) +{ + luaL_Buffer* B = (luaL_Buffer*) ud; + if( !B->L) + { + luaL_buffinit( L, B); + } + luaL_addlstring( B, (char const*) b, size); + return 0; +} + static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) { int n, needToPush; - luaL_Buffer b; + luaL_Buffer B; + B.L = NULL; + ASSERT_L( L2_cache_i != 0); // ... {cache} ... p STACK_GROW( L, 2); STACK_CHECK( L, 0); + // 'lua_dump()' needs the function at top of stack // if already on top of the stack, no need to push again needToPush = (i != (uint_t)lua_gettop( L)); @@ -1154,18 +1166,18 @@ static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* lua_pushvalue( L, i); // ... f } - luaL_buffinit( L, &b); // // "value returned is the error code returned by the last call // to the writer" (and we only return 0) // not sure this could ever fail but for memory shortage reasons - if( lua504_dump( L, buf_writer, &b, 0) != 0) + // last parameter is Lua 5.4-specific (no stripping) + if( lua504_dump( L, buf_writer, &B, 0) != 0) { luaL_error( L, "internal error: function dump failed."); } // pushes dumped string on 'L' - luaL_pushresult( &b); // ... f b + luaL_pushresult( &B); // ... f b // if not pushed, no need to pop if( needToPush) -- cgit v1.2.3-55-g6feb