I try to use the benchmark pcre2-10.00 in fuzzer-test-suite to find the use-after-free bug.
When running libfuzzer for a while, it found a use-after-free bug. But when I run the POC file again. AddressSanitizer reports buffer-overflow rather than use-after-free.
So I guess it's actually a buffer-overflow because of Address Sanitizer's false positives(Red zone size is too small, the buffer overflow to the freed field). Their backtrace seems the same, but same POC leads to different ASAN report.
=================================================================
==192986==ERROR: AddressSanitizer: heap-use-after-free on address 0x61400069b0c6 at pc 0x0000005df924 bp 0x7ffe0f6aa710 sp 0x7ffe0f6aa708
READ of size 1 at 0x61400069b0c6 thread T0
#0 0x5df923 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1426:16
#1 0x5d5082 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:5304:11
#2 0x5c8923 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1110:7
#3 0x59e1dd in pcre2_match_8 /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:6876:8
#4 0x5f2c8f in regexec /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2posix.c:291:6
#5 0x551771 in LLVMFuzzerTestOneInput /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/../target.cc:17:5
#6 0x42fbb5 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:515
#7 0x435021 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:440
#8 0x435021 in fuzzer::Fuzzer::MutateAndTestOne() /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:649
#9 0x437e8f in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:775
#10 0x429243 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:754
#11 0x41d5f2 in main /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#12 0x7f9ae9ae282f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
#13 0x41d668 in _start (/home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/pcre2-10.00-fsanitize_fuzzer+0x41d668)
0x61400069b0c6 is located 134 bytes inside of 446-byte region [0x61400069b040,0x61400069b1fe)
freed by thread T0 here:
#0 0x54dcb8 in operator delete[](void*) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_new_delete.cc:152
#1 0x435021 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:440
#2 0x435021 in fuzzer::Fuzzer::MutateAndTestOne() /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:649
#3 0x437e8f in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:775
#4 0x429243 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:754
#5 0x41d5f2 in main /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#6 0x7f9ae9ae282f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
previously allocated by thread T0 here:
#0 0x54cf60 in operator new[](unsigned long) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/asan/asan_new_delete.cc:95
#1 0x42faf7 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:506
#2 0x435021 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:440
#3 0x435021 in fuzzer::Fuzzer::MutateAndTestOne() /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:649
#4 0x437e8f in fuzzer::Fuzzer::Loop(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fuzzer::fuzzer_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:775
#5 0x429243 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:754
#6 0x41d5f2 in main /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#7 0x7f9ae9ae282f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
SUMMARY: AddressSanitizer: heap-use-after-free /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1426:16 in match
Shadow bytes around the buggy address:
0x0c28800cb5c0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c28800cb5d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb5e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb5f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb600: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
=>0x0c28800cb610: fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd fd fd
0x0c28800cb620: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb630: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb640: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c28800cb650: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c28800cb660: 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
==192986==ABORTING
=================================================================
==12987==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61e000007f5a at pc 0x0000005df924 bp 0x7ffcea0902b0 sp 0x7ffcea0902a8
READ of size 1 at 0x61e000007f5a thread T0
#0 0x5df923 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1426:16
#1 0x5d5082 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:5304:11
#2 0x5c8923 in match /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1110:7
#3 0x59e1dd in pcre2_match_8 /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:6876:8
#4 0x5f2c8f in regexec /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2posix.c:291:6
#5 0x551771 in LLVMFuzzerTestOneInput /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/../target.cc:17:5
#6 0x42fbb5 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:515
#7 0x41f3da in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:280
#8 0x4291e3 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:703
#9 0x41d5f2 in main /home/wencheng/Documents/llvm-6.0.1/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
#10 0x7fdc97fed82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
#11 0x41d668 in _start (/home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/pcre2-10.00-fsanitize_fuzzer+0x41d668)
Address 0x61e000007f5a is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/wencheng/FuzzingObject/fuzzer-test-suite/pcre2-10.00/build/BUILD/src/pcre2_match.c:1426:16 in match
Shadow bytes around the buggy address:
0x0c3c7fff8f90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff8fa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff8fb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff8fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff8fd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c3c7fff8fe0: fa fa fa fa fa fa fa fa fa fa fa[fa]fa fa fa fa
0x0c3c7fff8ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff9000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff9010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff9020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c3c7fff9030: 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
==12987==ABORTING
I also try to use AFL to test pcre2-10.00. Within 48 hours, AFL did not find use-after-free. But the README.md said that fuzzer can find use-after-free in less than a minute. If you are sure that this is not Address Sanitizer's false alarm, can you provide use-after-free POC files?
I am using this benchmark to do the experiment for finding the use-after-free bug. And I can't find this use-after-free using AFL and libfuzzer. I hope you can help improving this benchmark.
Thank you very much.