Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heap buffer overflow #77

Closed
rlohning opened this issue Jan 11, 2022 · 2 comments
Closed

Heap buffer overflow #77

rlohning opened this issue Jan 11, 2022 · 2 comments

Comments

@rlohning
Copy link

Hi,

I'm a developer in the Qt project which uses pcre2. I think I found an issue. Do demonstrate this, I'll use your oss-fuzz image with a changed fuzz target which mimics how Qt uses your library. I did not change anything in pcre2 itself. Should any of my steps be incorrect, please let me know.

  1. Check out my branch of oss-fuzz.
    This will clone your latest sources to the oss-fuzz image with changes I did to the fuzz target in my fork of your repo.
  2. Build your fuzzer in oss-fuzz:
    python infra/helper.py build_image pcre2
    python infra/helper.py build_fuzzers --engine libfuzzer --sanitizer address --architecture x86_64 pcre2
  3. Run this with the input file I will send to you via mail.
    python infra/helper.py reproduce pcre2 pcre2_fuzzer <input_file>
    You will see output like:

Running: /testcase
=================================================================
==18==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6030000001a1 at pc 0x00000058a03f bp 0x7ffd1c26fab0 sp 0x7ffd1c26faa8
READ of size 1 at 0x6030000001a1 thread T0
SCARINESS: 12 (1-byte-read-heap-buffer-overflow)
#0 0x58a03e in get_ucp /src/pcre2/src/pcre2_compile.c
#1 0x56f0a6 in parse_regex /src/pcre2/src/pcre2_compile.c:3152:14
#2 0x56452e in pcre2_compile_8 /src/pcre2/src/pcre2_compile.c:10147:13
#3 0x55e3df in LLVMFuzzerTestOneInput /src/pcre2/src/pcre2_fuzzsupport.c:68:23
#4 0x455283 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) cxa_noexception.cpp
#5 0x440ec2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
#6 0x44671c in fuzzer::FuzzerDriver(int*, char***, int ()(unsigned char const, unsigned long)) cxa_noexception.cpp
#7 0x46f522 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#8 0x7fce9188c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#9 0x41f67d in _start (/out/pcre2_fuzzer+0x41f67d)

DEDUP_TOKEN: get_ucp--parse_regex--pcre2_compile_8
0x6030000001a1 is located 0 bytes to the right of 17-byte region [0x603000000190,0x6030000001a1)
allocated by thread T0 here:
#0 0x52510d in __interceptor_malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3
#1 0x436e97 in operator new(unsigned long) cxa_noexception.cpp
#2 0x440ec2 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)) cxa_noexception.cpp
#4 0x46f522 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#5 0x7fce9188c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

DEDUP_TOKEN: __interceptor_malloc--operator new(unsigned long)--fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long)
SUMMARY: AddressSanitizer: heap-buffer-overflow /src/pcre2/src/pcre2_compile.c in get_ucp
Shadow bytes around the buggy address:
0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff8000: fa fa 00 00 00 fa fa fa 00 00 00 00 fa fa 00 00
0x0c067fff8010: 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
0x0c067fff8020: fd fd fd fa fa fa 00 00 00 00 fa fa 00 00 01 fa
=>0x0c067fff8030: fa fa 00 00[01]fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8080: 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
==18==ABORTING`

I'd appreciate if you could have a look into this. If I call your code incorrectly, please tell me so I can correct this in Qt.

@PhilipHazel
Copy link
Collaborator

This turned out to be a bug in some new code (not yet in any release) triggered by a pattern ending with an incomplete \p{... whose last character was underscore, hyphen, or space -- the ignorable characters. Now fixed.

@rlohning
Copy link
Author

I can confirm that the issue is fixed. Thank you for the quick reaction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants