haampie / libtree

ldd as a tree
MIT License
2.67k stars 60 forks source link

Segfault with another llvm library #56

Closed orbea closed 2 years ago

orbea commented 2 years ago

libtree: d51185d9fa83dd0525ef135bb3c40391f42cb932

$ ./libtree /usr/lib64/libLLVMScalarOpts.so
libLLVMScalarOpts.so.12 
├── libLLVMAggressiveInstCombine.so.12 [runpath]
│   ├── libLLVMTransformUtils.so.12 [runpath]
│   │   ├── libLLVMAnalysis.so.12 [runpath]
│   │   │   ├── libLLVMObject.so.12 [runpath]
│   │   │   │   ├── libLLVMBitReader.so.12 [runpath]
│   │   │   │   │   ├── libLLVMCore.so.12 [runpath]
=================================================================
==24611==ERROR: AddressSanitizer: heap-use-after-free on address 0x61d000000820 at pc 0x000000499aa7 bp 0x7ffdcb36b3a0 sp 0x7ffdcb36ab68
READ of size 10 at 0x61d000000820 thread T0
    #0 0x499aa6 in __asan_memcpy /tmp/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
    #1 0x4d2808 in string_table_store /tmp/libtree/libtree.c:317:5
    #2 0x4d4f87 in interpolate_variables /tmp/libtree/libtree.c:518:9
    #3 0x4cf9c5 in recurse /tmp/libtree/libtree.c:1136:13
    #4 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #5 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #6 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #7 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #8 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #9 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #10 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #11 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #12 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #13 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #14 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #15 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #16 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #17 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #18 0x4cc86c in print_tree /tmp/libtree/libtree.c:1463:22
    #19 0x4cc4b3 in main /tmp/libtree/libtree.c:1629:12
    #20 0x7f4b6977c01c in __libc_start_main (/lib64/libc.so.6+0x2401c)
    #21 0x41f369 in _start /tmp/glibc-2.33/csu/../sysdeps/x86_64/start.S:120

0x61d000000820 is located 1952 bytes inside of 2050-byte region [0x61d000000080,0x61d000000882)
freed by thread T0 here:
    #0 0x49aa19 in realloc /tmp/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:164:3
    #1 0x4d2cf1 in string_table_maybe_grow /tmp/libtree/libtree.c:307:17
    #2 0x4d279d in string_table_store /tmp/libtree/libtree.c:316:5
    #3 0x4d4f87 in interpolate_variables /tmp/libtree/libtree.c:518:9
    #4 0x4cf9c5 in recurse /tmp/libtree/libtree.c:1136:13
    #5 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #6 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #7 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #8 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #9 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #10 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #11 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #12 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #13 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #14 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #15 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #16 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #17 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #18 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #19 0x4cc86c in print_tree /tmp/libtree/libtree.c:1463:22
    #20 0x4cc4b3 in main /tmp/libtree/libtree.c:1629:12
    #21 0x7f4b6977c01c in __libc_start_main (/lib64/libc.so.6+0x2401c)

previously allocated by thread T0 here:
    #0 0x49aa19 in realloc /tmp/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:164:3
    #1 0x4d2cf1 in string_table_maybe_grow /tmp/libtree/libtree.c:307:17
    #2 0x4d4397 in string_table_copy_from_file /tmp/libtree/libtree.c:325:9
    #3 0x4cfc25 in recurse /tmp/libtree/libtree.c:1153:9
    #4 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #5 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #6 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #7 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #8 0x4d5dd0 in check_search_paths /tmp/libtree/libtree.c:427:17
    #9 0x4d151d in recurse /tmp/libtree/libtree.c:1253:9
    #10 0x4cc86c in print_tree /tmp/libtree/libtree.c:1463:22
    #11 0x4cc4b3 in main /tmp/libtree/libtree.c:1629:12
    #12 0x7f4b6977c01c in __libc_start_main (/lib64/libc.so.6+0x2401c)

SUMMARY: AddressSanitizer: heap-use-after-free /tmp/llvm-12.0.0.src/build/../projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy
Shadow bytes around the buggy address:
  0x0c3a7fff80b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fff80c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fff80d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fff80e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fff80f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c3a7fff8100: fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd
  0x0c3a7fff8110: fd fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fff8130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fff8140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c3a7fff8150: 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
  Shadow gap:              cc
==24611==ABORTING
haampie commented 2 years ago

Right, that's legitimate. Now I understand why Rust is a thing

haampie commented 2 years ago

Can you retry?

orbea commented 2 years ago

With commit 13465dca3426752d412b97524b166d1ed55d8068.

$ ./libtree /usr/lib64/libLLVMScalarOpts.so
=================================================================
==25431==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffded805c8 at pc 0x0000004d2bd6 bp 0x7fffded80510 sp 0x7fffded80508
READ of size 8 at 0x7fffded805c8 thread T0
    #0 0x4d2bd5 in string_table_maybe_grow /tmp/libtree/libtree.c:302:12
    #1 0x4d536d in interpolate_variables /tmp/libtree/libtree.c:519:9
    #2 0x4cf9c5 in recurse /tmp/libtree/libtree.c:1141:13
    #3 0x4cc86c in print_tree /tmp/libtree/libtree.c:1468:22
    #4 0x4cc4b3 in main /tmp/libtree/libtree.c:1634:12
    #5 0x7f9d392d401c in __libc_start_main (/lib64/libc.so.6+0x2401c)
    #6 0x41f369 in _start /tmp/glibc-2.33/csu/../sysdeps/x86_64/start.S:120

Address 0x7fffded805c8 is located in stack of thread T0 at offset 40 in frame
    #0 0x4d47af in interpolate_variables /tmp/libtree/libtree.c:442

  This frame has 1 object(s):
    [32, 40) 'st' (line 447) <== Memory access at offset 40 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/libtree/libtree.c:302:12 in string_table_maybe_grow
Shadow bytes around the buggy address:
  0x10007bda8060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda8070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda80a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007bda80b0: 00 00 00 00 f1 f1 f1 f1 00[f3]f3 f3 00 00 00 00
  0x10007bda80c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda80d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda80e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda80f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007bda8100: 00 00 00 00 f1 f1 f1 f1 00 00 f2 f2 00 00 f2 f2
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
  Shadow gap:              cc
==25431==ABORTING

Also a new compiler warning fwiw.

clang -g -O0 -fsanitize=address -Wall -std=c99 -D_FILE_OFFSET_BITS=64 -c libtree.c
libtree.c:519:33: warning: incompatible pointer types passing 'struct string_table_t **' to parameter of type 'struct string_table_t *'; remove & [-Wincompatible-pointer-types]
        string_table_maybe_grow(&st, n);
                                ^~~
libtree.c:300:60: note: passing argument to parameter 't' here
static void string_table_maybe_grow(struct string_table_t *t, size_t n) {
                                                           ^
1 warning generated.
haampie commented 2 years ago

4f16a1be6a591424a8b1b1658bb61a64495aee0d yes, sorry

orbea commented 2 years ago

Works with commit 4f16a1be6a591424a8b1b1658bb61a64495aee0d, thanks again!

$ ./libtree /usr/lib64/libLLVMScalarOpts.so
libLLVMScalarOpts.so.12 
├── libLLVMAggressiveInstCombine.so.12 [runpath]
│   ├── libLLVMTransformUtils.so.12 [runpath]
│   │   ├── libLLVMAnalysis.so.12 [runpath]
│   │   │   ├── libLLVMObject.so.12 [runpath]
│   │   │   │   ├── libLLVMBitReader.so.12 [runpath]
│   │   │   │   │   ├── libLLVMCore.so.12 [runpath]
│   │   │   │   │   │   ├── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   │   │   ├── libLLVMDemangle.so.12 [runpath]
│   │   │   │   │   │   │   ├── libz.so.1 [runpath]
│   │   │   │   │   │   │   ├── libtinfo.so.6 [runpath]
│   │   │   │   │   │   │   └── librt.so.1 [ld.so.conf]
│   │   │   │   │   │   ├── libLLVMRemarks.so.12 [runpath]
│   │   │   │   │   │   │   ├── libLLVMBitstreamReader.so.12 [runpath]
│   │   │   │   │   │   │   │   └── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   │   │   └── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   │   └── libLLVMBinaryFormat.so.12 [runpath]
│   │   │   │   │   │       └── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   ├── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   └── libLLVMBitstreamReader.so.12 [runpath]
│   │   │   │   ├── libLLVMSupport.so.12 [runpath]
│   │   │   │   ├── libLLVMBinaryFormat.so.12 [runpath]
│   │   │   │   ├── libLLVMMC.so.12 [runpath]
│   │   │   │   │   ├── libLLVMBinaryFormat.so.12 [runpath]
│   │   │   │   │   ├── libLLVMSupport.so.12 [runpath]
│   │   │   │   │   └── libLLVMDebugInfoCodeView.so.12 [runpath]
│   │   │   │   │       ├── libLLVMDebugInfoMSF.so.12 [runpath]
│   │   │   │   │       │   └── libLLVMSupport.so.12 [runpath]
│   │   │   │   │       └── libLLVMSupport.so.12 [runpath]
│   │   │   │   ├── libLLVMTextAPI.so.12 [runpath]
│   │   │   │   │   ├── libLLVMBinaryFormat.so.12 [runpath]
│   │   │   │   │   └── libLLVMSupport.so.12 [runpath]
│   │   │   │   ├── libLLVMMCParser.so.12 [runpath]
│   │   │   │   │   ├── libLLVMMC.so.12 [runpath]
│   │   │   │   │   └── libLLVMSupport.so.12 [runpath]
│   │   │   │   └── libLLVMCore.so.12 [runpath]
│   │   │   ├── libLLVMSupport.so.12 [runpath]
│   │   │   ├── libLLVMBinaryFormat.so.12 [runpath]
│   │   │   ├── libLLVMCore.so.12 [runpath]
│   │   │   └── libLLVMProfileData.so.12 [runpath]
│   │   │       ├── libLLVMCore.so.12 [runpath]
│   │   │       ├── libLLVMDemangle.so.12 [runpath]
│   │   │       └── libLLVMSupport.so.12 [runpath]
│   │   ├── libLLVMSupport.so.12 [runpath]
│   │   └── libLLVMCore.so.12 [runpath]
│   ├── libLLVMSupport.so.12 [runpath]
│   ├── libLLVMCore.so.12 [runpath]
│   └── libLLVMAnalysis.so.12 [runpath]
├── libLLVMSupport.so.12 [runpath]
├── libLLVMCore.so.12 [runpath]
├── libLLVMAnalysis.so.12 [runpath]
├── libLLVMTransformUtils.so.12 [runpath]
└── libLLVMInstCombine.so.12 [runpath]
    ├── libLLVMTransformUtils.so.12 [runpath]
    ├── libLLVMSupport.so.12 [runpath]
    ├── libLLVMCore.so.12 [runpath]
    └── libLLVMAnalysis.so.12 [runpath]
haampie commented 2 years ago

Thanks for your patience :D

orbea commented 2 years ago

No worries, I am just testing the tool because I was curious after the c99 rewrite. It does seem rather useful.