vstakhov / libucl

Universal configuration library parser
BSD 2-Clause "Simplified" License
1.63k stars 139 forks source link

Heap-buffer-overflow in ucl_skip_comments function of ucl_parser.c:182:11 #265

Open HotSpurzzZ opened 1 year ago

HotSpurzzZ commented 1 year ago

When I use tests/fuzzers/ucl_add_string_fuzzer.c for fuzz testing, I found Heap-buffer-overflow in ucl_skip_comments function of ucl_parser.c:182:11

Verification steps

CC = clang
CFLAGS = -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link
LIB_FUZZING_ENGINE="-fsanitize=fuzzer"

cd libucl 
./autogen.sh && ./configure
make

$CC $CFLAGS $LIB_FUZZING_ENGINE tests/fuzzers/ucl_add_string_fuzzer.c \
    -DHAVE_CONFIG_H -I./src -I./include src/.libs/libucl.a -I./ \
    -o $OUT/ucl_add_string_fuzzer
./ucl_add_string_fuzzer $poc

POC file

https://github.com/HotSpurzzZ/testcases/blob/main/libucl/libucl_Heap_buffer_overflow_ucl_skip_comments

AddressSanitizer output

==24470==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6070000000d1 at pc 0x00000057296a bp 0x7ffe68c8a060 sp 0x7ffe68c8a058
  | READ of size 1 at 0x6070000000d1 thread T0
  | #0 0x572969 in ucl_skip_comments /src/libucl/src/ucl_parser.c:182:11
  | #1 0x562b3b in ucl_parse_key /src/libucl/src/ucl_parser.c:1466:9
  | #2 0x562b3b in ucl_state_machine /src/libucl/src/ucl_parser.c:2475:9
  | #3 0x560e4e in ucl_parser_add_chunk_full /src/libucl/src/ucl_parser.c:2995:12
  | #4 0x570621 in ucl_parser_add_chunk_priority /src/libucl/src/ucl_parser.c:3030:9
  | #5 0x570621 in ucl_parser_add_string_priority /src/libucl/src/ucl_parser.c:3093:9
  | #6 0x570621 in ucl_parser_add_string /src/libucl/src/ucl_parser.c:3105:9
  | #7 0x55a8de in LLVMFuzzerTestOneInput /src/libucl/tests/fuzzers/ucl_add_string_fuzzer.c:17:2
  | #8 0x455243 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
  | #9 0x440ed2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
  | #10 0x44671c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
  | #11 0x46f312 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
  | #12 0x7f9ae934f082 in __libc_start_main
  | #13 0x41f6fd in _start
  |  
  | 0x6070000000d1 is located 0 bytes to the right of 65-byte region [0x607000000090,0x6070000000d1)
  | allocated by thread T0 here:
  | #0 0x523b2d in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3
  | #1 0x436ed7 in operator new(unsigned long) cxa_noexception.cpp:0
  | #2 0x440ed2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
  | #3 0x44671c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9
  | #4 0x46f312 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
  | #5 0x7f9ae934f082 in __libc_start_main
  |  
  | SUMMARY: AddressSanitizer: heap-buffer-overflow (/clusterfuzz/bot1700-7565d8759b-549f9/clusterfuzz/bot/builds/libfuzzer_asan_linux_libucl/custom/ucl_add_string_fuzzer+0x572969)
  | Shadow bytes around the buggy address:
  | 0x0c0e7fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  | 0x0c0e7fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  | 0x0c0e7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  | 0x0c0e7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  | 0x0c0e7fff8000: fa fa fa fa 00 00 00 00 00 00 00 00 01 fa fa fa
  | =>0x0c0e7fff8010: fa fa 00 00 00 00 00 00 00 00[01]fa fa fa fa fa
  | 0x0c0e7fff8020: 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa
  | 0x0c0e7fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  | 0x0c0e7fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  | 0x0c0e7fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  | 0x0c0e7fff8060: 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
  | ==24470==ABORTING