lua-users home
lua-l archive

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


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.