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

OOB panic in deflate_stored after deflateParams() #229

Open
inahga opened this issue Oct 15, 2024 · 0 comments
Open

OOB panic in deflate_stored after deflateParams() #229

inahga opened this issue Oct 15, 2024 · 0 comments

Comments

@inahga
Copy link
Contributor

inahga commented Oct 15, 2024

Fuzzing reveals a OOB panic in deflate_stored() on the main branch, when we change the deflate parameters midway through the stream.

This seems somewhat related to both #218 and #219,

#[test]
    fn inahga_4() {
        let mut source = [
            161, 161, 161, 161, 179, 179, 179, 179, 179, 179, 133, 133, 133, 133, 13, 13, 13, 13,
            13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179,
            179, 179, 179, 43, 179, 8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13,
            13, 13, 13, 13, 3, 13, 13, 95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189,
            189, 189, 0, 189, 189, 189, 189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189,
            189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189, 189,
            189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 189, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 189,
            189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255, 255, 255, 255, 189, 13, 13, 13,
            13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
            125, 125, 125, 125, 125, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
            39, 39, 39, 39, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
            125, 125, 125, 125, 125, 125, 255, 18, 125, 125, 125, 69, 125, 125, 125, 125, 255, 255,
            255, 255, 125, 125, 125, 125, 125, 63, 125, 125, 125, 125, 125, 125, 125, 125, 125,
            223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
            39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 13, 13, 13,
            13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179, 179, 179, 179, 43, 179,
            8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13, 13, 13, 13, 13, 3, 13, 13,
            95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 0, 189, 189, 189,
            189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
            189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255, 255, 255, 255,
            189, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
            13, 13, 13, 13, 13, 125, 125, 125, 125, 125, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
            39, 39, 39, 39, 39, 39, 39, 39, 39, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
            125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 255, 18, 125, 125, 125, 69, 125, 125,
            125, 125, 255, 255, 255, 255, 125, 125, 125, 125, 125, 63, 125, 125, 125, 125, 125,
            125, 125, 125, 125, 223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39, 39, 39, 39,
            39, 39, 39, 39, 39, 39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255,
            255, 255, 189, 189, 189, 189, 189, 189, 183, 183, 183, 183, 183, 189, 189, 189, 189,
            189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
            189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189,
            189, 189, 189, 189, 66, 189, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 158, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189, 189,
            189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 189, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 5, 5, 5, 5,
            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 39,
            39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
            39, 39, 39, 39, 39, 39, 255, 255, 255, 189, 189, 189, 189, 189, 255, 255, 255, 255,
            255, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
            141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 255, 255,
            255, 81, 126, 81, 81, 81, 81, 81, 81, 81, 85, 5, 5, 5, 5, 5, 5, 5, 5, 49, 5, 5, 5, 5,
            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 255, 255, 189, 189,
            189, 189, 189, 189, 19, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 95, 95, 95, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 95,
            255, 255, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 255, 255,
            245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 189, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 199, 199, 199,
            199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
            199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
            199, 199, 199, 199, 199, 199, 199, 199, 199, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 191, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 7, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 81, 255, 255, 255, 255, 255,
            255, 255, 255, 255, 36, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 40, 255, 255,
            255, 255, 255, 255, 81, 81, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255,
        ]
        .to_vec();

        let config = DeflateConfig {
            level: 0,
            method: Method::Deflated,
            window_bits: 8,
            mem_level: 3,
            strategy: Strategy::HuffmanOnly,
        };

        let mut stream = z_stream::default();
        let err = unsafe {
            deflateInit2_(
                &mut stream,
                config.level,
                config.method as i32,
                config.window_bits,
                config.mem_level,
                config.strategy as i32,
                zlibVersion(),
                size_of::<z_stream>() as c_int,
            )
        };
        assert_eq!(ReturnCode::from(err), ReturnCode::Ok);

        let buf_size = unsafe { deflateBound(&mut stream, source.len() as u64) };

        let mut dest = vec![0; buf_size as usize];
        let chunk = 305u32;
        let flush = DeflateFlush::NoFlush;

        stream.next_in = source.as_mut_ptr().cast();
        stream.avail_in = chunk; // First chunk.
        stream.next_out = dest.as_mut_ptr().cast();
        stream.avail_out = dest.len().try_into().unwrap();

        // Deflate first chunk.
        let err = unsafe { deflate(&mut stream, flush as i32) };
        assert_eq!(ReturnCode::from(err), ReturnCode::Ok);

        // Change the parameters.
        let new_level = 0;
        let new_strategy = Strategy::Default;
        let err = unsafe { deflateParams(&mut stream, new_level, new_strategy as _) };
        match ReturnCode::from(err) {
            ReturnCode::Ok => {}
            ReturnCode::BufError => {
                // Flushing the current pending data may run us out of buffer space.
                // Worst case double the buffer size.
                let add_space = Ord::min(chunk, buf_size as u32);
                dest.extend(core::iter::repeat_n(0, add_space.try_into().unwrap()));

                // If extend() reallocates, it may have moved in memory.
                stream.next_out = dest.as_mut_ptr();
                stream.avail_out += add_space;

                let err = unsafe { deflateParams(&mut stream, new_level, new_strategy as _) };
                assert_eq!(ReturnCode::from(err), ReturnCode::Ok);
            }
            err => panic!("fatal {:?}", err),
        }

        // Deflate the rest in chunks.
        let mut left: u32 = source.len() as u32 - chunk;
        while left > 0 {
            // Write the chunk.
            let avail = Ord::min(chunk, left).try_into().unwrap();
            stream.avail_in = avail;
            let err = unsafe { deflate(&mut stream, flush as i32) };
            match ReturnCode::from(err) {
                ReturnCode::Ok => {
                    left -= avail;
                }
                ReturnCode::BufError => {
                    // Worst case double the buffer size.
                    let add_space = Ord::min(chunk, buf_size as u32);
                    dest.extend(core::iter::repeat_n(0, add_space.try_into().unwrap()));

                    // If extend() reallocates, it may have moved in memory.
                    stream.next_out = dest.as_mut_ptr();
                    stream.avail_out += add_space;

                    left -= avail - stream.avail_in;
                }
                err => panic!("fatal {:?}", err),
            }
        }

        assert_eq!(left, 0);

        let _ = unsafe { deflateEnd(&mut stream) };
    }
running 1 test
test tests::inahga_4 ... FAILED

failures:

---- tests::inahga_4 stdout ----
thread 'tests::inahga_4' panicked at /home/inahga/Projects/zlib-rs/zlib-rs/src/deflate/algorithm/stored.rs:182:14:
range end index 1013 out of range for slice of length 915
stack backtrace:
   0: rust_begin_unwind
             at /rustc/7608018cbdac9e55d0d13529cf43adc33d53efcf/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/7608018cbdac9e55d0d13529cf43adc33d53efcf/library/core/src/panicking.rs:74:14
   2: core::slice::index::slice_end_index_len_fail_rt
             at /rustc/7608018cbdac9e55d0d13529cf43adc33d53efcf/library/core/src/slice/index.rs:64:5
   3: core::slice::index::slice_end_index_len_fail
             at /rustc/7608018cbdac9e55d0d13529cf43adc33d53efcf/library/core/src/slice/index.rs:58:5
   4: core::slice::index::range
             at /home/inahga/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:889:9
   5: core::slice::<impl [T]>::copy_within
             at /home/inahga/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:3723:56
   6: zlib_rs::deflate::algorithm::stored::deflate_stored
             at /home/inahga/Projects/zlib-rs/zlib-rs/src/deflate/algorithm/stored.rs:179:9
   7: zlib_rs::deflate::algorithm::run
             at /home/inahga/Projects/zlib-rs/zlib-rs/src/deflate/algorithm/mod.rs:32:41
   8: zlib_rs::deflate::deflate
             at /home/inahga/Projects/zlib-rs/zlib-rs/src/deflate.rs:2589:22
   9: LIBZ_RS_SYS_TEST_deflate
             at /home/inahga/Projects/zlib-rs/libz-rs-sys/src/lib.rs:894:26
  10: compress_gz::tests::inahga_4
             at ./fuzz_targets/compress_gz.rs:1049:32
  11: compress_gz::tests::inahga_4::{{closure}}
             at ./fuzz_targets/compress_gz.rs:891:18
  12: core::ops::function::FnOnce::call_once
             at /home/inahga/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
  13: core::ops::function::FnOnce::call_once
             at /rustc/7608018cbdac9e55d0d13529cf43adc33d53efcf/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

n.b. this changes the level and strategy midway through the deflate stream.

Minor bug, no memory corruption occurs and I'm doubtful anyone really uses deflateParams() in practice anyway.

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

1 participant