sile / libflate

A Rust implementation of DEFLATE algorithm and related formats (ZLIB, GZIP)
https://docs.rs/libflate
MIT License
178 stars 35 forks source link

Encoder panic on specific input data... #52

Closed tonyastolfi closed 4 years ago

tonyastolfi commented 4 years ago

Greetings, and thanks for all your hard work on this very useful library!

When I run this code, I see:

Test data size is 16052 bytes
compressed 16031 bytes into 2707
thread 'main' panicked at 'symbol:15, table:12', /rustc/49cae55760da0a43428eba73abcb659bb70cf2e4/src/libstd/macros.rs:16:9
stack backtrace:
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::default_hook
   5: std::panicking::rust_panic_with_hook
   6: rust_begin_unwind
   7: std::panicking::begin_panic_fmt
   8: <libflate::deflate::symbol::DynamicHuffmanCodec as libflate::deflate::symbol::HuffmanCodec>::save::{{closure}}
   9: core::iter::traits::iterator::Iterator::position::check::{{closure}}
  10: core::iter::traits::double_ended::DoubleEndedIterator::try_rfold
  11: <core::iter::adapters::Rev<I> as core::iter::traits::iterator::Iterator>::try_fold
  12: core::iter::traits::iterator::Iterator::position
  13: <libflate::deflate::symbol::DynamicHuffmanCodec as libflate::deflate::symbol::HuffmanCodec>::save
  14: libflate::deflate::encode::CompressBuf<H,E>::flush
  15: libflate::deflate::encode::BlockBuf<E>::flush
  16: libflate::deflate::encode::Block<E>::finish
  17: libflate::deflate::encode::Encoder<W,E>::finish
  18: bug_repro_case::main
  19: std::rt::lang_start::{{closure}}
  20: std::rt::lang_start_internal
  21: std::rt::lang_start
  22: main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

I have reproduced this on macOSX 10.15 and Ubuntu Linux. My compiler is rustc 1.44.1 (c7087fe00 2020-06-17)

Here's the logic from the linked repo (with the test data removed for brevity):

use std::io::Write;

use libflate::deflate::Encoder;

fn main() -> std::io::Result<()> {
    let mut data: Vec<u8> = get_test_data();

    eprintln!("Test data size is {} bytes", data.len());

    let limit1 = 16_031usize;
    let limit2 = limit1 + 1;

    // Attempt 1 (should succeed)
    //
    let mut encoder = Encoder::new(Vec::new());
    encoder.write_all(&data[0..limit1])?;
    let compressed: Vec<u8> = encoder.finish().into_result()?;

    eprintln!("compressed {} bytes into {}", limit1, compressed.len());

    // Attempt 2 (will fail)
    //
    let mut encoder = Encoder::new(Vec::new());
    encoder.write_all(&data[0..limit2])?;
    let compressed: Vec<u8> = encoder.finish().into_result()?;

    eprintln!("compressed {} bytes into {}", limit2, compressed.len());

    Ok(())
}

fn get_test_data() -> Vec<u8> {
...
}

Thanks again for taking a look!

sile commented 4 years ago

Resolved by #53