Lexer heap buffer overflow
rol1510 opened this issue · 4 comments
rol1510 commented
Found this heap-buffer-overflow while working on the fuzzer ci.
Steps to reproduce:
- Build the quick-lint-js fuzzers with
CC=clang CXX=clang++ CFLAGS="-fsanitize=address,undefined -stdlib=libstdc++" CXXFLAGS=-fsanitize=address,undefined cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
- create the empty directory "corpus"
- Download this file crash.txt and place it in the corpus directory.
- run
./build-fuzz/fuzz/quick-lint-js-fuzz-lex corpus/
- You should see the following ASAN message:
==1644==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x621000002507 at pc 0x55be9eea0c1f bp 0x7fffbc794530 sp 0x7fffbc794528
READ of size 16 at 0x621000002507 thread T0
#0 0x55be9eea0c1e in quick_lint_js::Keyword_Lexer::key_strings_equal(char8_t const*, char8_t const*, unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b3c1e) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#1 0x55be9eea03ee in quick_lint_js::Lexer::identifier_token_type(std::basic_string_view<char8_t, std::char_traits<char8_t> >) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b33ee) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#2 0x55be9ee5aad7 in quick_lint_js::Lexer::try_parse_current_token() (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x16dad7) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#3 0x55be9ee57fde in quick_lint_js::Lexer::parse_current_token() (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x16afde) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#4 0x55be9ee26d47 in LLVMFuzzerTestOneInput (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x139d47) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#5 0x55be9ed59b53 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6cb53) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#6 0x55be9ed59279 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6c279) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#7 0x55be9ed5ac08 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile> >&) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6dc08) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#8 0x55be9ed5b0f2 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile> >&) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6e0f2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#9 0x55be9ed49cf2 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x5ccf2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#10 0x55be9ed729f2 in main (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x859f2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#11 0x7ff3dd9781c9 (/lib/x86_64-linux-gnu/libc.so.6+0x271c9) (BuildId: 51657f818beb1ae70372216a99b7412b8a100a20)
#12 0x7ff3dd978284 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27284) (BuildId: 51657f818beb1ae70372216a99b7412b8a100a20)
#13 0x55be9ed3e900 in _start (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x51900) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
0x621000002507 is located 7 bytes to the right of 4096-byte region [0x621000001500,0x621000002500)
allocated by thread T0 here:
#0 0x55be9ee2450d in operator new(unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x13750d) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#1 0x55be9eea3f6d in quick_lint_js::Flexible_Array<char, quick_lint_js::Linked_Bump_Allocator::Chunk_Header>* quick_lint_js::Flexible_Array<char, quick_lint_js::Linked_Bump_Allocator::Chunk_Header>::allocate_and_construct_header<quick_lint_js::Flexible_Array<char, quick_lint_js::Linked_Bump_Allocator::Chunk_Header>*&>(quick_lint_js::Memory_Resource*, unsigned long, quick_lint_js::Flexible_Array<char, quick_lint_js::Linked_Bump_Allocator::Chunk_Header>*&) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b6f6d) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#2 0x55be9eea3d5b in quick_lint_js::Linked_Bump_Allocator::append_chunk(unsigned long, unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b6d5b) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#3 0x55be9eea3a27 in quick_lint_js::Linked_Bump_Allocator::allocate_bytes(unsigned long, unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b6a27) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#4 0x55be9ee6e8b9 in quick_lint_js::Lexer::parse_identifier_slow(char8_t const*, char8_t const*, quick_lint_js::Lexer::Identifier_Kind) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1818b9) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#5 0x55be9ee622fc in quick_lint_js::Lexer::parse_identifier(char8_t const*, quick_lint_js::Lexer::Identifier_Kind) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1752fc) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#6 0x55be9ee66126 in quick_lint_js::Lexer::reparse_as_regexp() (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x179126) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#7 0x55be9ee629b8 in quick_lint_js::Lexer::test_for_regexp(char8_t const*) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1759b8) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#8 0x55be9ee5c76c in quick_lint_js::Lexer::try_parse_current_token() (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x16f76c) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#9 0x55be9ee57fca in quick_lint_js::Lexer::parse_current_token() (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x16afca) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#10 0x55be9ee26d47 in LLVMFuzzerTestOneInput (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x139d47) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#11 0x55be9ed59b53 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6cb53) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#12 0x55be9ed59279 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6c279) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#13 0x55be9ed5ac08 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile> >&) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6dc08) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#14 0x55be9ed5b0f2 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile> >&) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x6e0f2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#15 0x55be9ed49cf2 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x5ccf2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#16 0x55be9ed729f2 in main (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x859f2) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4)
#17 0x7ff3dd9781c9 (/lib/x86_64-linux-gnu/libc.so.6+0x271c9) (BuildId: 51657f818beb1ae70372216a99b7412b8a100a20)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/mnt/g/repos/quick-lint-js/build-fuzz/fuzz/quick-lint-js-fuzz-lex+0x1b3c1e) (BuildId: 2608e54ff4ea687b215dde8163c80509c663dcf4) in quick_lint_js::Keyword_Lexer::key_strings_equal(char8_t const*, char8_t const*, unsigned long)
Shadow bytes around the buggy address:
0x0c427fff8450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fff8460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fff8470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fff8480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c427fff8490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c427fff84a0:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fff84b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fff84c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fff84d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fff84e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c427fff84f0: 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
==1644==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x11,0x47,0x2a,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x47,0x2a,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x47,0x2a,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x2f,0x5c,0x75,0x5c,0x75,0x2a,0x2a,0x2f,0x38,0x3c,0x0,0x0,0x0,0x75,0x2a,0x2f,0x5c,0x75,0x0,0x0,0x2f,0x5c,0x75,0x5c,0x75,0x0,0x0,0x0,0x0,0x0,0x0,0x2a,0x2a,0x2f,0x36,0x2f,0x5c,0x75,0x5c,0x75,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x47,0x2a,0x2a,0x2f,0x5c,0x75,0x5c,0x2a,0x2f,0x5c,0x75,0x5c,0x75,0x2a,0x2a,0x2f,0x38,0x3c,0x0,0x0,0x0,0x75,0x2a,0x2f,0x5c,0x75,0x0,0x0,0x75,0x2a,0x2f,0x5c,0x75,0x0,0x0,0x2f,0x5c,0x75,0x5c,0x75,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x75,0x2a,0x2a,0x2f,0x38,0x71,0x2a,0x2f,0x34,0x71,
\021G**/\\u\\*G**/\\u\\*/\\u\\*/\\u\\*G**/\\u\\*/\\u\\u**/8<\000\000\000u*/\\u\000\000/\\u\\u\000\000\000\000\000\000**/6/\\u\\u\377\377\377\377\377\377\377\377\377\377\377*/\\u\\*G**/\\u\\*/\\u\\u**/8<\000\000\000u*/\\u\000\000u*/\\u\000\000/\\u\\uUUUUUUUUUUUu**/8q*/4q
artifact_prefix='./'; Test unit written to ./crash-fd5dfa97fcd291bce68ca883e5c43217ec3a0508
Base64: EUcqKi9cdVwqRyoqL1x1XCovXHVcKi9cdVwqRyoqL1x1XCovXHVcdSoqLzg8AAAAdSovXHUAAC9cdVx1AAAAAAAAKiovNi9cdVx1//////////////8qL1x1XCpHKiovXHVcKi9cdVx1KiovODwAAAB1Ki9cdQAAdSovXHUAAC9cdVx1VVVVVVVVVVVVVVV1KiovOHEqLzRx
rol1510 commented
./quick-lint-js crash.txt
works. Only the fuzzer is affected.
strager commented
Thanks for reporting! There is a real bug which affects the main program as well.
strager commented
Fix released in version 3.2.0.