lua-users home
lua-l archive

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

Next assertion hit!

-- begin testcase #1 --
xpcall( function()  for _=_,_ do end  end,
        function()  debug.getinfo(1,"n")  end )
-- end testcase #1 --

What happens?  (As far as I understand it...)

The for loop's OP_FORPREP complains that the for limit must be a number
and luaG_runerror's out.  ldebug.c's getfuncname assumes that not all
opcodes can result in a call, but xpcall puts the error handling
function on top and violates that assumption.  Lo: assert(0)!

Going through all opcodes not explicitly handled and looking at the
code, OP_FORPREP is the only one that explicitly calls luaG_runerror.
All other interesting candidates don't, but can (re)allocate or could
reach a deeper luaG_runerror.


Checking for other `luaG_runerror`s...

OP_VARARG can reach a stack overflow while resizing and will
then hit the same assertion:

-- begin testcase #2 --
local handler = function( )  debug.getinfo(1,"n")  end
function chks( n, ... )
  xpcall( chks, handler, n+1, n, ... )
chks( 0 )
-- end testcase #2 --

NOTE: reduce stack limit or it will take a loong time... I used 1000,
which stacks ~80 calls.  With other values, you may also need to add a
few local variables to chks for stack feng shui, so it overflows in
OP_VARARG and not elsewhere.

OP_NEWTABLE (ok) cannot reach the luaG_runerror in setnodevector because
there cannot be too many elements (the scanner table used for the
constants has more entries and overflows earlier, so a test chunk
doesn't even compile.)

I can't find 'luaG_runerror's accessible from OP_SETLIST and OP_CLOSURE.
 (There's a branch in luaM_reallocv that leads to luaM_toobig which
luaG_runerror's, but I didn't bother to explore that branch - it's
probably not possible to make a large enough initializer.)

However, there's two alternate sources of errors:

(1) out of memory conditions result in luaD_throw - I can't wrap my head
around that yet, so I can't say for sure whether that can/should call
the error handler set by xpcall.

(2) __gc metamethods that throw an error.  As described in a separate
mail, I can't build a test case that runs the error handler.  But I
suspect this is / should be possible.

So it's probably a good idea to also handle OP_NEWTABLE, OP_SETLIST, and
OP_CLOSURE (in addition to OP_FORPREP and OP_VARARG).

(Alternatively or in addition to that: contain __gc errors? - I'll write
a separate mail on that.)

-- Marco