"heap-use-after-free" issue in luaV_finishget

96 views
Skip to first unread message

Sergey Bronnikov

unread,
Mar 27, 2024, 7:00:19 AM3/27/24
to lua-l
Hello, everyone,

there is a "heap-use-after-free" issue on the latest version.

How to reproduce:

- clone Git repository with Lua source code:
  git clone https://github.com/lua/lua
- apply the patch below: patch -p1 < makefile.patch

```
--- a/makefile
+++ b/makefile
@@ -72,11 +72,11 @@ LOCAL = $(TESTS) $(CWARNS)
 # enable Linux goodies
 MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_USE_READLINE
 MYLDFLAGS= $(LOCAL) -Wl,-E
-MYLIBS= -ldl -lreadline
+MYLIBS= -ldl -lreadline $(LDFLAGS)
 
 
-CC= gcc
-CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
+CC?= gcc
+CFLAGS+= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
 AR= ar rc
 RANLIB= ranlib
 RM= rm -f
```

- build Lua with enabled AddressSanitizer:
  CC=clang CFLAGS="-ggdb -O0 -fsanitize=address" LDFLAGS=-fsanitize=address make
- create a file with Lua code:

```
cat << EOF > repro.lua
local a
local b
local b
local b
local b
local __index = function(c, d)
        if type(c) then
        end
end
local e
local b
local h
local b
local b
local b
local b
local b
debug.setmetatable("string", { __index = __index })
local f
local i
g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g = "Name"
g(g:g())
EOF
```
- execute the Lua snippet by command `./lua repro.lua`
  and AddressSanitizer will report a heap-use-after-free in `luaV_finishget`:

=================================================================
==159947==ERROR: AddressSanitizer: heap-use-after-free on address 0x51a000000208 at pc 0x596b266ea5bf bp 0x7ffcaab43fe0 sp 0x7ffcaab43fd8
READ of size 1 at 0x51a000000208 thread T0
    #0 0x596b266ea5be in luaV_finishget (/home/sergeyb/sources/cache/lua/lua+0x1715be) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #1 0x596b266ef503 in luaV_execute (/home/sergeyb/sources/cache/lua/lua+0x176503) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #2 0x596b266b2809 in luaD_callnoyield (/home/sergeyb/sources/cache/lua/lua+0x139809) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #3 0x596b266ae6e0 in luaD_rawrunprotected (/home/sergeyb/sources/cache/lua/lua+0x1356e0) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #4 0x596b266b3b06 in luaD_pcall (/home/sergeyb/sources/cache/lua/lua+0x13ab06) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #5 0x596b266a4218 in lua_pcallk (/home/sergeyb/sources/cache/lua/lua+0x12b218) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #6 0x596b26699249 in docall lua.c
    #7 0x596b2669863b in pmain lua.c
    #8 0x596b266b207a in luaD_precall (/home/sergeyb/sources/cache/lua/lua+0x13907a) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #9 0x596b266b27d9 in luaD_callnoyield (/home/sergeyb/sources/cache/lua/lua+0x1397d9) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #10 0x596b266ae6e0 in luaD_rawrunprotected (/home/sergeyb/sources/cache/lua/lua+0x1356e0) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #11 0x596b266b3b06 in luaD_pcall (/home/sergeyb/sources/cache/lua/lua+0x13ab06) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #12 0x596b266a4218 in lua_pcallk (/home/sergeyb/sources/cache/lua/lua+0x12b218) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #13 0x596b26697ba6 in main (/home/sergeyb/sources/cache/lua/lua+0x11eba6) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #14 0x787cf0e29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #15 0x787cf0e29e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #16 0x596b265b9614 in _start (/home/sergeyb/sources/cache/lua/lua+0x40614) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)

0x51a000000208 is located 392 bytes inside of 1360-byte region [0x51a000000080,0x51a0000005d0)
freed by thread T0 here:
    #0 0x596b266583fc in realloc (/home/sergeyb/sources/cache/lua/lua+0xdf3fc) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #1 0x596b266c3205 in luaM_realloc_ (/home/sergeyb/sources/cache/lua/lua+0x14a205) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)

previously allocated by thread T0 here:
    #0 0x596b266583fc in realloc (/home/sergeyb/sources/cache/lua/lua+0xdf3fc) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)
    #1 0x596b266c3205 in luaM_realloc_ (/home/sergeyb/sources/cache/lua/lua+0x14a205) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd)

SUMMARY: AddressSanitizer: heap-use-after-free (/home/sergeyb/sources/cache/lua/lua+0x1715be) (BuildId: 6348343d72d6c76f60f3adaaf07ccc041e70a3bd) in luaV_finishget
Shadow bytes around the buggy address:
  0x519fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x51a000000000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x51a000000080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x51a000000200: fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000380: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000400: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x51a000000480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==159947==ABORTING

It seems the commit 0593256707ce ("'luaH_get' functions return tag of the result") [1]
introduced a problem. Because the problem is gone when it is reverted:

$ ./lua repro.lua
./lua: repro.lua:22: attempt to call a nil value (method 'g')
stack traceback:
        repro.lua:22: in main chunk
        [C]: in ?


Sergey

Roberto Ierusalimschy

unread,
Mar 27, 2024, 12:24:26 PM3/27/24
to lu...@googlegroups.com
> there is a "heap-use-after-free" issue on the latest version.
>
> [...]

Many thanks for the report. Bug confirmed (with valgrind).

-- Roberto
Reply all
Reply to author
Forward
0 new messages