lua-users home
lua-l archive

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


It was thus said that the Great Dirk Laurie once stated:
> 2017-11-03 7:50 GMT+02:00 Dirk Laurie <dirk.laurie@gmail.com>:
> > 2017-11-02 17:42 GMT+02:00 Viacheslav Usov <via.usov@gmail.com>:
> >>
> >> Here is my test of your code:
> >>
> >> lua_State *L = luaL_newstate();
> >>
> >> luaL_openlibs(L);
> >> luaopen_buffer(L);
> >> lua_setglobal(L, "b");
> >> luaL_dostring(L,
> >> "local x = b.new()"
> >> "b.append(x, string.rep('x', 100000))"
> >> "b.append(x, string.rep('x', 100000))"
> >> "print(b.flush(x))"
> >> );
> >>
> >> When I run the above, it crashes within the second call to luaL_addvalue(),
> >> due to a heap corruption. If I remove the second b.append... line, then it
> >> crashes within luaL_pushresult(), for the same reason.
> >
> > I will be more impressed if you can crash my code by using it as a
> > module of C routines to be called from Lua.
> 
> OK, I can spare you the effort. If I run your code line by line in the
> interpreter (without 'local'), it is fine. If I put it inside do ...
> end,
> it crashes spectacularly. You are right.
> 
> The reason it is in the API must be that it is needed to code the
> standard library, which prides itself on being totally written in the
> API.

I got the following when I compiled your code and ran it:

[spc]lucy:/tmp/foo>lua-53 
Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
> b = require "buffer"
> x = b.new()
> b.append(x, string.rep('x', 100000))
> b.append(x, string.rep('x', 100000))
*** glibc detected *** double free or corruption (!prev): 0x098a1ed0 ***
Aborted (core dumped)
[spc]lucy:/tmp/foo>

  When I modified the code thusly:

static int buffer_new (lua_State *L) {
  luaL_Buffer **buf = lua_newuserdata(L,sizeof(luaL_Buffer *));
  *buf = malloc(sizeof(luaL_Buffer));
  luaL_buffinit(L,*buf);
  luaL_setmetatable(L,"Buffer");
  return 1;
}

static int buffer_flush (lua_State *L) {
  luaL_Buffer **buf = luaL_checkudata(L,1,"Buffer");
  luaL_pushresult(*buf);
  free(*buf);
  *buf = NULL;
  return 1;
}

static int buffer_append (lua_State *L) {
  luaL_addvalue(*(luaL_Buffer **)luaL_checkudata(L,1,"Buffer"));
  return 0;
}

I got (after the first call to b.append()):
xxxxx
*** glibc detected *** malloc(): memory corruption: 0x08e98da8 ***
Aborted (core dumped)

Meanwhile, this works:

	#include <lua.h>
	#include <lualib.h>
	#include <lauxlib.h>
	
	static int bar(lua_State *L)
	{
	  lua_pushinteger(L,5 * lua_tointeger(L,1) + 2);
	  return 1;
	}
	
	static int baz(lua_State *L)
	{
	  luaL_Buffer  buf;  
	  char        *p;
	  int          l;
	  int          x;
	
	  luaL_buffinit(L,&buf);
	  luaL_addstring(&buf,"result: ");
	  lua_getglobal(L,"foo");
	  lua_call(L,0,1);
	  x = lua_tointeger(L,-1);
	  p = luaL_prepbuffsize(&buf,10000);
	  l = snprintf(p,10000,"%d",x * 2);
	  luaL_addsize(&buf,l);
	  luaL_pushresult(&buf);
	  return 1;
	}
	
	int main(void)
	{
	  lua_State *L = luaL_newstate();
	  luaL_openlibs(L);
	  lua_pushcfunction(L,bar);
	  lua_setglobal(L,"bar");  
	  luaL_loadstring(L,"function foo() return bar(3) * 4 + 5 end");
	  lua_call(L,0,0);
	  lua_getglobal(L,"print");
	  lua_pushcfunction(L,baz);
	  lua_call(L,0,1);
	  lua_call(L,1,0);
	  lua_close(L);
	  return 0;
	}

  -spc (Which is how I think the luaL_Buffer API is supposed to be used ... )