lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


>>>>> "Egor" == Egor Skriptunoff <egor.skriptunoff@gmail.com> writes:

 >> I wonder how many of them crash if you do
 >> 
 >> local function f(s) s:gsub(".", f) return "x" end f("foo")
 >> 
 >> and more to the point, how many of them will crash on that code if
 >> they switch to 5.4 without realizing the default stack depth grew
 >> 10x.

 Egor> Instead of testing it in embedded environments, I've tested this
 Egor> one-line Lua program on usual desktop computer.
 Egor> Here are the results.

 Egor> On *Linux*
 Egor> Lua built with gcc (32-bit and 64-bit executables):

 Egor> Catchable error is raised:
 Egor>    Lua 5.1(all)
 Egor>    Lua 5.2(all)
 Egor>    Lua 5.3(all)
 Egor>    Lua 5.4_work2(32-bit)

 Egor> Host application crashes:
 Egor>    Lua 5.4_work2(64-bit)

This suggests you're running with a stack size limit on the close order
of 16MB, perhaps? The default buffer size is based on sizeof(void*)
amongst other factors, so the 32-bit build is probably using about 12MB
of stack for that code and the 64-bit build around 20MB.

 Egor> On *Windows*
 Egor> Lua built with different compilers:
 Egor> VisualStudio2010 and MinGW (from MSYS2), both produce 32-bit and
 Egor> 64-bit executables:

 Egor> Catchable error is raised:
 Egor>    Lua 5.1(all)
 Egor>    Lua 5.2(all)
 Egor>    Lua 5.3(VS 32-bit, MinGW 32-bit, MinGW 64-bit)

 Egor> Host application crashes:
 Egor>    Lua 5.3(VS 64-bit)
 Egor>    Lua 5.4_work2(all)

I am no windows expert, but I believe the stack size limit of a windows
binary can be specified at link time. So I guess MinGW is using a
different default size (presumably 2MB or more) there, and that VS's
default stack size is on the order of 1MB to 1.5MB; Lua 5.3 uses
something like 1.8MB for that code on a 64-bit build, and something
around 1MB on a 32-bit build.

Incidentally, I tried making a list of functions with dangerous stack
usage. There appear to be three: string.gsub is the most obvious one,
since it explicitly invokes a function parameter while having a
luaL_Buffer on the stack, but there are at least two more that are more
subtle: table.concat and string.format can both invoke metamethods on
parameter values while having a luaL_Buffer on the stack.

I think this should work to demonstrate the problem for table.concat:

t = setmetatable({},
  {__index=function(t,i) local y = table.concat(t,'',1,1) end})
print(t[1])

Anyone think of any more functions that are vulnerable in this way?

-- 
Andrew.