lua-users home
lua-l archive

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


Hi,

I am a contributor to the Alpine Linux distribution. We recently
encountered a double free which leads to a segmentation fault while
building lsyncd with lua 5.4.4 [1].

To me, it looks like the lineinfo memory is freed twice. Once via
combine() and once via close_state(). The valgrind output looks
as follows:

==29903== Invalid free() / delete / delete[] / realloc()
==29903==    at 0x48A4B0D: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29903==    by 0x11E5D2: l_alloc (lauxlib.c:1014)
==29903==    by 0x112F51: luaM_free_ (lmem.c:135)
==29903==    by 0x11111B: luaF_freeproto (lfunc.c:271)
==29903==    by 0x112ABB: deletelist (lgc.c:1494)
==29903==    by 0x112ABB: luaC_freeallobjects (lgc.c:1511)
==29903==    by 0x116D54: close_state (lstate.c:276)
==29903==    by 0x10B549: main (luac.c:210)
==29903==  Address 0x48ec220 is 0 bytes inside a block of size 10 free'd
==29903==    at 0x48A4B0D: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29903==    by 0x11E5D2: l_alloc (lauxlib.c:1014)
==29903==    by 0x112F51: luaM_free_ (lmem.c:135)
==29903==    by 0x10C60C: combine (luac.c:158)
==29903==    by 0x10C60C: pmain (luac.c:183)
==29903==    by 0x10FF38: precallC (ldo.c:506)
==29903==    by 0x11020C: luaD_precall (ldo.c:572)
==29903==    by 0x110340: ccall (ldo.c:607)
==29903==    by 0x10F7CA: luaD_rawrunprotected (ldo.c:144)
==29903==    by 0x110668: luaD_pcall (ldo.c:926)
==29903==    by 0x10DB2F: lua_pcallk (lapi.c:1067)
==29903==    by 0x10B528: main (luac.c:209)
==29903==  Block was alloc'd at
==29903==    at 0x48A6FC9: realloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==29903==    by 0x112F7E: luaM_realloc_ (lmem.c:166)
==29903==    by 0x112FC5: luaM_saferealloc_ (lmem.c:180)
==29903==    by 0x113074: luaM_shrinkvector_ (lmem.c:116)
==29903==    by 0x114B02: close_func (lparser.c:764)
==29903==    by 0x116B1B: mainfunc (lparser.c:1937)
==29903==    by 0x116B1B: luaY_parser (lparser.c:1959)
==29903==    by 0x10F718: f_parser (ldo.c:971)
==29903==    by 0x10F7CA: luaD_rawrunprotected (ldo.c:144)
==29903==    by 0x110668: luaD_pcall (ldo.c:926)
==29903==    by 0x11074B: luaD_protectedparser (ldo.c:988)
==29903==    by 0x10DC13: lua_load (lapi.c:1097)
==29903==    by 0x10C5B1: combine (luac.c:151)
==29903==    by 0x10C5B1: pmain (luac.c:183)

I am not familiar with the lua code base, but a simple fix would be to
have combine() assign NULL to f->lineinfo to ensure that it is not freed
again later on:

diff -upr lua-5.4.4.orig/src/luac.c lua-5.4.4/src/luac.c
--- lua5.4.4.orig/src/luac.c	2022-04-14 20:57:01.927447850 +0200
+++ lua-5.4.4/src/luac.c	2022-04-14 20:57:35.260900910 +0200
@@ -156,6 +156,7 @@ static const Proto* combine(lua_State* L
    if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
   }
   luaM_freearray(L,f->lineinfo,f->sizelineinfo);
+  f->lineinfo=NULL;
   f->sizelineinfo=0;
   return f;
  }

Would be nice if this could get this fixed properly upstream.

Greetings,
Sören

[1]: https://gitlab.alpinelinux.org/alpine/aports/-/issues/13694