Good evening,

I found a heap-buffer overflow in infocmp's safe_name().

`infocmp -x -E` can overflow a heap buffer when dumping a terminfo entry with a 
long extended capability name. The bug is in `progs/infocmp.c:safe_name()`: the 
function keeps a static pointer to a heap buffer, allocates it only on the 
first call, sizes it from that first call's arguments, and reuses it for later 
calls even when later names require more space.

In a build without `--enable-string-hacks`, `_nc_SPRINTF` maps to `sprintf`, so 
the later call can write past the original allocation. An AddressSanitizer 
build confirms a heap-buffer-overflow through `sprintf`, with the stack going 
through `safe_name()`, `dump_initializers()`, and `main()`.

I’m attaching a suggested fix, and the AddressSanitizer report.  A POC is 
available on request.

Full disclosure: I am building an open source bug and vulnerability scanner, 
N184, and used it to locate memory-safety issues in ncurses. You can find it 
here: https://github.com/MillaFleurs/N184

Thank you,

Dan


=================================================================
==48448==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x603000001c71 at pc 0x00010353af7c bp 0x00016d46d9d0 sp 0x00016d46d170
WRITE of size 336 at 0x603000001c71 thread T0
    #0 0x00010353af78 in memcpy+0x260 
(libclang_rt.asan_osx_dynamic.dylib:arm64e+0x8ef78)
    #1 0x00019f723c1c in __sfvwrite+0x14c (libsystem_c.dylib:arm64e+0x4c1c)
    #2 0x00019f723664 in __vfprintf+0x2bfc (libsystem_c.dylib:arm64e+0x4664)
    #3 0x00019f72b800 in vsprintf_l+0xc8 (libsystem_c.dylib:arm64e+0xc800)
    #4 0x0001034cb428 in vsprintf+0x6c 
(libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1f428)
    #5 0x0001034cbae8 in sprintf+0x38 
(libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1fae8)
    #6 0x0001029a1150 in safe_name infocmp.c:1324
    #7 0x000102994910 in dump_initializers infocmp.c:1450
    #8 0x000102992228 in main infocmp.c:2022
    #9 0x00019f4c9d50 in start+0x1c0c (dyld:arm64e+0x8d50)

0x603000001c71 is located 0 bytes after 17-byte region 
[0x603000001c60,0x603000001c71)
allocated by thread T0 here:
    #0 0x0001034ed164 in malloc+0x78 
(libclang_rt.asan_osx_dynamic.dylib:arm64e+0x41164)
    #1 0x0001029a0f30 in safe_name infocmp.c:1308
    #2 0x0001029940a4 in dump_initializers infocmp.c:1425
    #3 0x000102992228 in main infocmp.c:2022
    #4 0x00019f4c9d50 in start+0x1c0c (dyld:arm64e+0x8d50)

SUMMARY: AddressSanitizer: heap-buffer-overflow 
(libsystem_c.dylib:arm64e+0x4c1c) in __sfvwrite+0x14c
Shadow bytes around the buggy address:
  0x603000001980: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x603000001a00: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
  0x603000001a80: 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00
  0x603000001b00: fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa 00 00
  0x603000001b80: 00 00 fa fa 00 00 00 00 fa fa 00 00 00 00 fa fa
=>0x603000001c00: 00 00 00 fa fa fa 00 00 00 02 fa fa 00 00[01]fa
  0x603000001c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000001d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000001d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000001e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000001e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==48448==ABORTING


Attachment: patch.diff
Description: Binary data

Reply via email to