summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-07-22 13:48:43 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-07-22 13:48:43 -0300
commit439e45a2f69549b674d6a6e2023e8debfa00a2b8 (patch)
tree416db940cc3e4826119fda14d47f579b60cfb99b
parent62fb93442753cbfb828335cd172e71471dffd536 (diff)
downloadlua-github-439e45a2f69549b674d6a6e2023e8debfa00a2b8.tar.gz
Bug: luaL_tolstring may get confused with negative index
When object has a '__name' metafield, 'luaL_tolstring' used the received index after pushing a string on the stack.
-rw-r--r--lauxlib.c1
-rw-r--r--ltests.c3
-rw-r--r--testes/errors.lua16
3 files changed, 20 insertions, 0 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 94835ef9..8ed1da11 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -881,6 +881,7 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
+ idx = lua_absindex(L,idx);
if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
if (!lua_isstring(L, -1))
luaL_error(L, "'__tostring' must return a string");
diff --git a/ltests.c b/ltests.c
index a50f7830..97834e38 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1743,6 +1743,9 @@ static struct X { int x; } x;
(void)s1; /* to avoid warnings */
lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
}
+ else if EQ("Ltolstring") {
+ luaL_tolstring(L1, getindex, NULL);
+ }
else if EQ("type") {
lua_pushstring(L1, luaL_typename(L1, getnum));
}
diff --git a/testes/errors.lua b/testes/errors.lua
index 825f37c2..a7dc479a 100644
--- a/testes/errors.lua
+++ b/testes/errors.lua
@@ -228,6 +228,22 @@ do -- named objects (field '__name')
checkmessage("return {} < XX", "table with My Type")
checkmessage("return XX < io.stdin", "My Type with FILE*")
_G.XX = nil
+
+ if T then -- extra tests for 'luaL_tolstring'
+ -- bug in 5.4.3; 'luaL_tolstring' with negative indices
+ local x = setmetatable({}, {__name="TABLE"})
+ assert(T.testC("Ltolstring -1; return 1", x) == tostring(x))
+
+ local a, b = T.testC("pushint 10; Ltolstring -2; return 2", x)
+ assert(a == 10 and b == tostring(x))
+
+ setmetatable(x, {__tostring=function (o)
+ assert(o == x)
+ return "ABC"
+ end})
+ a, b, c = T.testC("pushint 10; Ltolstring -2; return 3", x)
+ assert(a == x and b == 10 and c == "ABC")
+ end
end
-- global functions