Skip to content

Panic: Allocation size too big in enc.rs #266

@Yomihay-qut

Description

@Yomihay-qut

Description

Hello, I discovered a panic in pdf-rs while fuzzing.

The parser panics with "allocation-size-too-big" when processing a specific input. This panic is caused by unchecked casting of negative i32 values to usize, resulting in an integer overflow and an invalid massive allocation size.(Looks like converting i32 to usize really isn't a good idea......)

Crash Location

  • pdf/src/enc.rs:306
  • Message: AddressSanitizer: allocation-size-too-big

Fuzz Target

Here are the fuzz target and PoC that I used.

#![no_main]
use libfuzzer_sys::fuzz_target;
use pdf::enc::*;
use std::convert::TryInto;

fn get_i32(data: &[u8], offset: &mut usize) -> i32 {
    if *offset + 4 > data.len() {
        return 0;
    }
    let val = i32::from_le_bytes(data[*offset..*offset+4].try_into().unwrap());
    *offset += 4;
    val
}

fuzz_target!(|data: &[u8]| {
    if data.len() < 1 { return; }
    let mut offset = 0;
    
    // Use the first byte to determine the filter type
    // We want to test:
    // 0: ASCIIHexDecode
    // 1: ASCII85Decode
    // 2: LZWDecode
    // 3: FlateDecode
    // 4: RunLengthDecode
    // 5: DCTDecode 
    let filter_type = data[offset] % 6; 
    offset += 1;

    let filter = match filter_type {
        0 => StreamFilter::ASCIIHexDecode,
        1 => StreamFilter::ASCII85Decode,
        2 | 3 => {
            // LZW or Flate
            // Needed params: predictor, n_components, bits_per_component, columns, early_change
            let predictor = get_i32(data, &mut offset);
            let n_components = get_i32(data, &mut offset);
            let bits_per_component = get_i32(data, &mut offset);
            let columns = get_i32(data, &mut offset);
            let early_change = get_i32(data, &mut offset);
            
            let params = LZWFlateParams {
                predictor,
                n_components,
                bits_per_component,
                columns,
                early_change
            };
            
            if filter_type == 2 {
                StreamFilter::LZWDecode(params)
            } else {
                StreamFilter::FlateDecode(params)
            }
        },
        4 => StreamFilter::RunLengthDecode,
        5 => {
             // DCT
             let color_transform = Some(get_i32(data, &mut offset));
             StreamFilter::DCTDecode(DCTDecodeParams { color_transform })
        },
        _ => return
    };

    if offset > data.len() { return; }
    let payload = &data[offset..];
    
    // Execute decode
    let _ = decode(payload, &filter);
});

POC.zip

Stack Trace

==82489==ERROR: AddressSanitizer: requested allocation size 0x19efa9763262bcd0 (0x19efa9763262ccd0 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
    #0 0x562d1f0d9169 in calloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:74:3
    #1 0x562d1f160b87 in alloc::alloc::alloc_zeroed /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/alloc.rs:178:9
    #2 0x562d1f160b87 in <alloc::alloc::Global>::alloc_impl /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/alloc.rs:190:43
    #3 0x562d1f160b87 in <alloc::alloc::Global as core::alloc::Allocator>::allocate_zeroed /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/alloc.rs:257:14
    #4 0x562d1f160b87 in <alloc::raw_vec::RawVecInner>::try_allocate_in /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/raw_vec/mod.rs:470:40
    #5 0x562d1f160b87 in <alloc::raw_vec::RawVecInner>::with_capacity_zeroed_in /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/raw_vec/mod.rs:443:15
    #6 0x562d1f160b87 in <alloc::raw_vec::RawVec<u8>>::with_capacity_zeroed_in /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/raw_vec/mod.rs:208:20
    #7 0x562d1f160b87 in <u8 as alloc::vec::spec_from_elem::SpecFromElem>::from_elem::<alloc::alloc::Global> /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/vec/spec_from_elem.rs:51:31
    #8 0x562d1f160b87 in alloc::vec::from_elem::<u8> /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/alloc/src/vec/mod.rs:3510:5
    #9 0x562d1f160b87 in pdf::enc::flate_decode /home/sun/pdf/pdf/src/enc.rs:306:24
    #10 0x562d1f1632c8 in pdf::enc::decode /home/sun/pdf/pdf/src/enc.rs:468:50
    #11 0x562d1f10b4eb in decode::_::__libfuzzer_sys_run /home/sun/pdf/pdf/fuzz/fuzz_targets/decode.rs:69:13
    #12 0x562d1f10d66a in rust_fuzzer_test_input /home/sun/.cargo/registry/src/rsproxy.cn-e3de039b2554c837/libfuzzer-sys-0.4.10/src/lib.rs:276:60
    #13 0x562d1f1f38e4 in libfuzzer_sys::test_input_wrap::{closure#0} /home/sun/.cargo/registry/src/rsproxy.cn-e3de039b2554c837/libfuzzer-sys-0.4.10/src/lib.rs:62:9
    #14 0x562d1f1f38e4 in std::panicking::catch_unwind::do_call::<libfuzzer_sys::test_input_wrap::{closure#0}, i32> /rustc/1aa9bab4ecbce4859eaad53000f78158ebe2be2c/library/std/src/panicking.rs:581:40
    #15 0x562d1f1f4488 in __rust_try libfuzzer_sys.27fa543dd454df52-cgu.0

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