Skip to content

Malformed unreal4 crashdump file can cause OOM when being parsed #476

Closed
@5225225

Description

@5225225

I'm using the following fuzzer harness

#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    drop(symbolic::unreal::Unreal4Crash::parse_with_limit(data, 1024*1024));
});

And 1MB should be enough to never OOM. But the issue is that

fn gread_files(
bytes: &[u8],
count: usize,
offset: &mut usize,
) -> Result<Vec<Unreal4FileMeta>, Unreal4Error> {
let mut files = Vec::with_capacity(count);
for _ in 0..count {
let file_offset = *offset;
files.push(bytes.gread_with(offset, file_offset)?);
}
Ok(files)
}
here, line 116 is an unbounded allocation. count is read directly from the file, and not validated in any way. Therefore, a malicious file can cause the Vec to be allocated with an arbitrarily large count.

I suggest just capping the capacity here to something small. (Say, 64?). That would imply extra allocations if the file actually has more than that, but that's cheap enough, and most definitely better than an OOM. The capacity here is just a hint, anyways.

A sample program that shows off the vulnerability is

use flate2::write::ZlibEncoder;
use std::io::Write;

fn main() {
    let mut bytes = Vec::new();
    bytes.extend_from_slice(b"\x00\x00\x00\x00"); // Directory Name (AnsiString)
    bytes.extend_from_slice(b"\x00\x00\x00\x00"); // File Name (AnsiString)
    bytes.extend_from_slice(b"\x00\x00\x00\x00"); // Uncompressed Size (i32 LE)
    bytes.extend_from_slice(b"\xff\xff\xff\x40"); // File Count (i32 LE)

    // File Count is what we're targeting, but we need the bits at the front.
    
    let mut enc = ZlibEncoder::new(Vec::new(), flate2::Compression::default());
    enc.write_all(&bytes).unwrap();
    let compressed = enc.finish().unwrap();
    drop(dbg!(symbolic::unreal::Unreal4Crash::parse_with_limit(&compressed, 1024*1024)));
    // drop is just to ignore the unused Result warning
}

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