[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: is this a bug in lua core 5.0b ?
- From: "Bilyk, Alex" <ABilyk@...>
- Date: Thu, 30 Jan 2003 09:56:35 -0800
Curiously enough, I am calling coroutine.create via a lua_call or lua_pcall and either end up with memory corruption that prevents further scripts execution with message "error in error handling" or a simple crash in GC. lua_[p]call itself executes with no problems taking 1 parameter and returning a new coroutine/lua_State* on the stack. But after this things go berserk.
In my test run pState == pMainState (see code below). Call to lua_pcall succeeds leaving a new lua_State* on the stack. Using lua_call instead of lua_pcall makes no difference. I don't override Lua's memory allocation facilities. Commenting out lua_pcall fixes the problem. I did add one more member variable (void* mpMyData) to lua_State structure that I placed before CommonHeader. So, this variable can technically be a problem, I suspect.
Here is the simplified code that I tested
///////////////////////////////////////////////////////////////////////
// Takes a LUA function as parameter 1
//
Sint32 nsGZLua5ThreadLib::Create(lua_State* pState)
{
lua_State* pMainState = G(pState)->mainthread;
Sint32 main_tos = lua_gettop(pMainState);
lua_xmove(pState, pMainState, 1); // move the function to pMainState stack
Sint32 lf_si = lua_gettop(pMainState);
// call old create
lua_pushnumber(pMainState, kThreadsOldCreateKey);
lua_rawget(pMainState, cIGZLua5Thread::kSIREGISTRY); // puts the precached coroutine.create on top
lua_pushvalue(pMainState, lf_si); // push the lua function on top
lua_pcall(pMainState, 1, 1); // call coroutine.create
lua_settop(pMainState, main_tos); // restore the stack for the main thread
return 0;
}
AB
-----Original Message-----
From: Benoit Germain [mailto:bgermain@ubisoft.fr]
Sent: Thursday, January 30, 2003 7:55 AM
To: Multiple recipients of list
Subject: is this a bug in lua core 5.0b ?
Hi,
I have replaced the system memory allocator with Doug Lea's malloc, version
2.7.2, found here: http://gee.cs.oswego.edu/pub/misc/malloc.c, and I get a
crash because of memory corruption.
Here is what I am doing at the time of the crash:
I pcall from C a function created by coroutine.wrap(). This function resumes
the coroutine, but an error is raised by luaG_ordererror(), which causes the
program to enter luaG_errormsg a first time:
luaG_errormsg(lua_State * L=0x011c1c50) Ligne 568
luaG_runerror(lua_State * L=0x011c1c50, const char * fmt=0x00b3af48, ...)
Ligne 577 + 0x9
luaG_ordererror(lua_State * L=0x011c1c50, const lua_TObject * p1=0x011c7f60,
const lua_TObject * p2=0x011c7f58) Ligne 543 + 0x16
luaV_lessthan(lua_State * L=0x011c1c50, const lua_TObject * l=0x011c7f60,
const lua_TObject * r=0x011c7f58) Ligne 233 + 0x11
luaV_execute(lua_State * L=0x011c1c50) Ligne 578 + 0xa9
resume(lua_State * L=0x011c1c50, void * ud=0x0012f3ec) Ligne 352 + 0x9
luaD_rawrunprotected(lua_State * L=0x011c1c50, void (lua_State *, void *)*
f=0x006aa4d0, void * ud=0x0012f3ec) Ligne 96 + 0xd
lua_resume(lua_State * L=0x011c1c50, int nargs=3) Ligne 368 + 0x12
auxresume(lua_State * L=0x011b03d0, lua_State * co=0x011c1c50, int narg=3)
Ligne 548 + 0xd
luaB_auxwrap(lua_State * L=0x011b03d0) Ligne 583 + 0x1a
luaD_precall(lua_State * L=0x011b03d0, lua_TObject * func=0x011c86e0) Ligne
273 + 0x12
luaD_call(lua_State * L=0x011b03d0, lua_TObject * func=0x011c86e0, int
nResults=0) Ligne 318 + 0xd
f_call(lua_State * L=0x011b03d0, void * ud=0x0012fc20) Ligne 666 + 0x16
luaD_rawrunprotected(lua_State * L=0x011b03d0, void (lua_State *, void *)*
f=0x0069d100, void * ud=0x0012fc20) Ligne 96 + 0xd
luaD_pcall(lua_State * L=0x011b03d0, void (lua_State *, void *)*
func=0x0069d100, void * u=0x0012fc20, int old_top=16, int ef=8) Ligne 421 +
0x11
lua_pcall(lua_State * L=0x011b03d0, int nargs=3, int nresults=0, int
errfunc=-5) Ligne 679 + 0x20
since there is no error handler, LUA_ERRRUN is simply thrown, which returns
control to lua_resume(). Then luaB_auxwrap() propagates the error, which
causes the program to enter luaG_errormsg a second time.
The contents of L at that point are as follows:
- L 0x011b03d0 lua_State *
+ next 0xcdcdcdcd GCObject *
tt 8 '?' unsigned char
marked 205 'Í' unsigned char
+ top 0x011c8c78 lua_TObject *
+ base 0x011c86e8 lua_TObject *
+ l_G 0x011b0430 global_State *
+ ci 0x011b064c CallInfo *
+ stack_last 0x011c8c40 lua_TObject *
+ stack 0x011c86d0 lua_TObject *
stacksize 180 int
+ end_ci 0x011b06d8 CallInfo *
+ base_ci 0x011b0638 CallInfo *
size_ci 8 unsigned short
nCcalls 1 unsigned short
hookmask 7 '?' unsigned char
allowhook 1 '?' unsigned char
hookinit 1 '?' unsigned char
basehookcount 0 int
hookcount -4217 int
hook 0x00667bd7 lua::lua_interface::LuaDebugger::theHook(struct
lua_State *,struct lua_Debug *) void (lua_State *, lua_Debug *)*
+ _gt {...} lua_TObject
+ openupval 0x00000000 GCObject *
+ gclist 0xcdcdcdcd GCObject *
+ errorJmp 0x0012f9a0 lua_longjmp *
errfunc 8 int
As you can see, we have:
L->stacksize == 180
and
L->top-L->stack 181 unsigned long
that is to say, the stack is full. Unfortunately, we can see that
luaG_errormsg pushes two objects on the stack, and resizes it only
afterward:
void luaG_errormsg (lua_State *L) {
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
setobjs2s(L->top, L->top - 1); /* move argument */
setobjs2s(L->top - 1, errfunc); /* push function */ <-- here is the
problem
incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */
}
luaD_throw(L, LUA_ERRRUN);
}
As a result, when the error function is pushed on the stack, it goes beyond
the limit of the current memory block where the stack resides, thus causing
the header of the adjacent block in RAM to be corrupted.
What do you think of this ?
Regards,
Benoit.