Hi,
I found an interesting crash on Lua interpreter.
(Ubuntu 20.04 LTS / glibc 2.3.1 / Lua 5.4.4 commit hash 0e5071b5fbcc244d9f8c4bae82e327ad59bccc3f)
Code below generates use after read crash with address-sanitizer applied.
---------------------------------------------------------------------------------------------------
1 co = coroutine.wrap(
2 function()
3 local pcall <close> = setmetatable(
4 {}, {__close = function() pcall(co) end}
5 )
6 pcall()
7 end
8 )
9 co()
Windows 10 (64 bits)
MSVC 2019 (64 bits)
latest lua git:
Lua 5.4.4 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> co = coroutine.wrap(
>> function()
>> local pcall <close> = setmetatable(
>> {}, {__close = function() pcall(co) end}
>> )
>> pcall()
>> end
>> )
> co()
stdin:1: stdin:6: attempt to call a table value (local 'pcall')
stack traceback:
[C]: in function 'co'
stdin:1: in main chunk
[C]: in ?
>
C:\dll\lua\git>lua crash2.lua
lua: \dll\xclipper\xbin\lsql\crash2.lua:9: \dll\xclipper\xbin\lsql\crash2.lua:6: attempt to call a table value (local 'pcall')
stack traceback:
[C]: in function 'co'
\dll\xclipper\xbin\lsql\crash2.lua:9: in main chunk
[C]: in ?
Similarly, code below generates use after write crash.
---------------------------------------------------------------------------------------------------
1 co = coroutine.wrap(
2 function()
3 local pcall <close> = setmetatable(
4 {}, {__close = function() return pcall(co) end}
5 )
6 pcall()
7 end
8 )
9 co()
Lua 5.4.4 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> co = coroutine.wrap(
>> function()
>> local pcall <close> = setmetatable(
>> {}, {__close = function() return pcall(co) end}
>> )
>> pcall()
>> end
>> )
> co()
stdin:1: stdin:6: attempt to call a table value (local 'pcall')
stack traceback:
[C]: in function 'co'
stdin:1: in main chunk
[C]: in ?
>
C:\dll\lua\git>lua crash3.lua
lua: \dll\xclipper\xbin\lsql\crash3.lua:9: \dll\xclipper\xbin\lsql\crash3.lua:6: attempt to call a table value (local 'pcall')
stack traceback:
[C]: in function 'co'
\dll\xclipper\xbin\lsql\crash3.lua:9: in main chunk
[C]: in ?
Am I missing something?
Anyway pcall() and pcall(1), should be illegal:
There is a bug with pcall().
lbaselib.c:
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
lua_pushboolean(L, 1); /* first result if no errors */
lua_insert(L, 1); /* put it in place */
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
return finishpcall(L, status, 0);
}
Should be:
static int luaB_pcall (lua_State *L) {
int status;
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_pushboolean(L, 1); /* first result if no errors */
lua_insert(L, 1); /* put it in place */
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
return finishpcall(L, status, 0);
}
regards,
Ranier Vilela