Skip to content

Commit fa0f10c

Browse files
committed
lua: luaT_tolstring: keep Lua stack size unchanged
I found it counter-intuitive to change a Lua stack in a function that returns its result as the function return value. It complicates addressing of existing Lua stack elements using negative indices (relatively to the stack top). In fact, the amount of those temporary stack elements is the implementation detail. A couple of dubious examples: - Whether the function adds an extra element when the given value is already a string? - How much extra elements is added, when the __tostring metamethod returns several values? The original luaL_tostring() function from Lua 5.2 also left the temporary elements on the stack, but we're not obligated to keep bug-to-bug compatibility in a function of the luaT namespace.
1 parent bc6caac commit fa0f10c

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/lua/utils.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ luaT_cpcall(lua_State *L, lua_CFunction func, void *ud)
10401040
const char *
10411041
luaT_tolstring(lua_State *L, int idx, size_t *len)
10421042
{
1043+
int top = lua_gettop(L);
10431044
if (!luaL_callmeta(L, idx, "__tostring")) {
10441045
switch (lua_type(L, idx)) {
10451046
case LUA_TNUMBER:
@@ -1060,7 +1061,9 @@ luaT_tolstring(lua_State *L, int idx, size_t *len)
10601061
}
10611062
}
10621063

1063-
return lua_tolstring(L, -1, len);
1064+
const char *res = lua_tolstring(L, -1, len);
1065+
lua_settop(L, top);
1066+
return res;
10641067
}
10651068

10661069
/* Based on ffi_meta___call() from luajit/src/lib_ffi.c. */

test/app-tap/module_api.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,10 @@ static int table_tostring(lua_State *L) {
19861986
static int
19871987
test_tostring(lua_State *L)
19881988
{
1989+
size_t len = 0;
1990+
const char *res = NULL;
1991+
int top;
1992+
19891993
/* original table */
19901994
lua_createtable(L, 0, 0);
19911995
/* meta-table */
@@ -2012,6 +2016,21 @@ test_tostring(lua_State *L)
20122016
lua_pushnil(L);
20132017
assert(strcmp(luaT_tolstring(L, -1, NULL), "nil") == 0);
20142018

2019+
/*
2020+
* Verify a non-top string element.
2021+
*
2022+
* Check the length output value. Check that the Lua stack
2023+
* size remains unchanged.
2024+
*/
2025+
lua_pushliteral(L, "foo");
2026+
lua_pushnil(L);
2027+
top = lua_gettop(L);
2028+
res = luaT_tolstring(L, -2, &len);
2029+
assert(strcmp(res, "foo") == 0);
2030+
assert(len == 3);
2031+
assert(lua_gettop(L) - top == 0);
2032+
lua_pop(L, 2);
2033+
20152034
lua_pushboolean(L, true);
20162035
return 1;
20172036
}

0 commit comments

Comments
 (0)