Skip to content

Out-of-memory crash on parsing metadata blocks #912

@rhysd

Description

@rhysd

With improvements at #910, the fuzzer caught an out-of-memory crash on a machine with 64GiB RAM. Here is the minimized input (100 bytes).

FuzzingInput {
    markdown: "\n[\u{b}\t\t%\n*\t/////////////K[](      ? \n ---\n-\n--\0\0\0\0\0\0\0\0\n---\n-\u{f}nnn2\n\n.\u{1a}#\u{1}///K[](      ? \n0\\\\-\\\\\\",
    tables: false,
    footnotes: false,
    strikethrough: false,
    tasklists: true,
    smart_punctuation: false,
    heading_attributes: false,
    metadata_block: true,
    math: false,
    gfm: false,
}

Either parsing task lists or metadata blocks or both Parsing metadata blocks have an issue that the parser consumes the memory in worst cases.

Here is the full output from libFuzzer including stacktrace:

parse(50466,0x7ff854ec2700) malloc: nano zone abandoned due to inability to reserve vm space.
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1809842429
INFO: Loaded 1 modules   (52344 inline 8-bit counters): 52344 [0x105eb8070, 0x105ec4ce8),
INFO: Loaded 1 PC tables (52344 PCs): 52344 [0x105ec4ce8,0x105f91468),
fuzz/target/x86_64-apple-darwin/release/parse: Running 1 inputs 1 time(s) each.
Running: crash.md
==50466== ERROR: libFuzzer: out-of-memory (malloc(3221225472))
   To change the out-of-memory limit use -rss_limit_mb=<N>

    #0 0x1066cf565 in __sanitizer_print_stack_trace+0x35 (librustc-nightly_rt.asan.dylib:x86_64h+0xea565)
    #1 0x105c9068a in fuzzer::PrintStackTrace()+0x2a (parse:x86_64+0x10023268a)
    #2 0x105c814b5 in fuzzer::Fuzzer::HandleMalloc(unsigned long)+0x55 (parse:x86_64+0x1002234b5)
    #3 0x105c813ab in fuzzer::MallocHook(void const volatile*, unsigned long)+0x2b (parse:x86_64+0x1002233ab)
    #4 0x1066d6ef5 in __sanitizer::RunMallocHooks(void*, unsigned long)+0x25 (librustc-nightly_rt.asan.dylib:x86_64h+0xf1ef5)
    #5 0x1065eaf7e in __asan::Allocator::Allocate(unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, __asan::AllocType, bool)+0x67e (librustc-nightly_rt.asan.dylib:x86_64h+0x5f7e)
    #6 0x1065eb3e7 in __asan::Allocator::Reallocate(void*, unsigned long, __sanitizer::BufferedStackTrace*)+0x67 (librustc-nightly_rt.asan.dylib:x86_64h+0x63e7)
    #7 0x1065eb2fa in __asan::asan_realloc(void*, unsigned long, __sanitizer::BufferedStackTrace*)+0x2a (librustc-nightly_rt.asan.dylib:x86_64h+0x62fa)
    #8 0x1066c3999 in realloc+0xe9 (librustc-nightly_rt.asan.dylib:x86_64h+0xde999)
    #9 0x105afc538 in alloc::alloc::Global::grow_impl::h2f1f8eb9fe77353a+0x98 (parse:x86_64+0x10009e538)
    #10 0x105afda5f in alloc::raw_vec::finish_grow::h7a790573e513548e+0x12f (parse:x86_64+0x10009fa5f)
    #11 0x105b01e04 in alloc::raw_vec::RawVec$LT$T$C$A$GT$::grow_one::h240ec2c5807235b5+0x154 (parse:x86_64+0x1000a3e04)
    #12 0x105ba07c3 in pulldown_cmark::tree::Tree$LT$T$GT$::append::h815c91f77b35e890+0x93 (parse:x86_64+0x1001427c3)
    #13 0x105b42a08 in pulldown_cmark::firstpass::FirstPass::parse_line::_$u7b$$u7b$closure$u7d$$u7d$::h945dd50e7b43a1f9+0x5888 (parse:x86_64+0x1000e4a08)
    #14 0x105b3c832 in pulldown_cmark::firstpass::FirstPass::parse_line::h8b4a23b03e0ea2a0+0x502 (parse:x86_64+0x1000de832)
    #15 0x105b394e3 in pulldown_cmark::firstpass::FirstPass::parse_paragraph::h60c06c32301ae506+0x673 (parse:x86_64+0x1000db4e3)
    #16 0x105b35e36 in pulldown_cmark::firstpass::FirstPass::parse_block::hfd1697761766dcf7+0x3c26 (parse:x86_64+0x1000d7e36)
    #17 0x105b31cf1 in pulldown_cmark::firstpass::run_first_pass::h7548edfcae956b18+0x4d1 (parse:x86_64+0x1000d3cf1)
    #18 0x105b69196 in pulldown_cmark::parse::Parser::new_ext::h9e4b4e9e542f064f+0x156 (parse:x86_64+0x10010b196)
    #19 0x105aa7088 in parse::_::__libfuzzer_sys_run::hfac49f94d2e5f9b2+0x2a8 (parse:x86_64+0x100049088)
    #20 0x105aa6612 in rust_fuzzer_test_input+0x592 (parse:x86_64+0x100048612)
    #21 0x105c7c538 in std::panicking::try::do_call::hb350625bcb22a9b3+0xe8 (parse:x86_64+0x10021e538)
    #22 0x105c812a3 in __rust_try+0x13 (parse:x86_64+0x1002232a3)
    #23 0x105c8087c in LLVMFuzzerTestOneInput+0x11c (parse:x86_64+0x10022287c)
    #24 0x105c83a1b in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)+0x12b (parse:x86_64+0x100225a1b)
    #25 0x105ca58f3 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long)+0xe3 (parse:x86_64+0x1002478f3)
    #26 0x105cab010 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long))+0x2490 (parse:x86_64+0x10024d010)
    #27 0x105cb8242 in main+0x22 (parse:x86_64+0x10025a242)
    #28 0x7ff81148b41e in start+0x76e (dyld:x86_64+0xfffffffffff6e41e)

SUMMARY: libFuzzer: out-of-memory
────────────────────────────────────────────────────────────────────────────────

Error: Fuzz target exited with exit status: 71

Stack backtrace:
   0: std::backtrace::Backtrace::create
   1: std::backtrace::Backtrace::capture
   2: anyhow::error::<impl anyhow::Error>::msg
   3: cargo_fuzz::project::FuzzProject::exec_fuzz
   4: <cargo_fuzz::options::run::Run as cargo_fuzz::RunCommand>::run_command
   5: cargo_fuzz::main
   6: std::sys_common::backtrace::__rust_begin_short_backtrace
   7: std::rt::lang_start::{{closure}}
   8: std::rt::lang_start_internal
   9: _main
  10: <unknown>

Repro

Download the following file.

crash.md

Then run:

cargo +nightly fuzz run parse crash.md

EDIT: I manually minimized the input further. See #912 (comment)

Environment

  • Rust: rustc 1.81.0-nightly (3cf924b93 2024-06-15)
  • pulldown-cmark: 9ea0e05
  • OS: macOS 13
  • Arch: x86_64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions