alexcrichton / xz2-rs

Bindings to liblzma in Rust (xz streams in Rust)
Apache License 2.0
81 stars 52 forks source link

Err(Program) where Ok(MemNeeded) expected #115

Open Bennett-Petzold opened 1 year ago

Bennett-Petzold commented 1 year ago

When calling xz2::stream::Stream.process, an undersized output buffer will sometimes return Err(Program) [specifically returning error code 11 from the C call] instead of Ok(MemNeeded). This behavior is not mirrored in the bound C xz code.

The code below (compiled on rustc 1.71.0, platform using Linux kernel 6.4.3-arch1-1) shows this behavior. The compressed size is exactly 60 bytes.

use std::io::Read;

use xz2::{
    read::XzEncoder,
    stream::{Action, Check, Error, Status, Stream},
};

fn decompress(arr: &mut [u8]) -> Result<Status, Error> {
    let mut encoder = Stream::new_easy_encoder(6, Check::Crc64)?;
    let string = "One".as_bytes();

    loop {
        let res = encoder.process(string, arr, Action::Finish);
        if res != Ok(Status::Ok) {
            return res;
        }
    }
}

fn main() 
{
    for x in 0..64 {
        let mut arr = vec![0; x];
        println!("{x}: {:?}", decompress(&mut arr));
    }
}

Size zero returns Ok(MemNeeded) and every size between 1-59 returns Err(Program). By contrast, I've attached a modified version of 01_compress_easy.c from xz/doc/examples at tag 2327a46. It returns LZMA_BUF_ERROR for sizes 0-59 as expected.

The C code compiled on the same platform with GCC 13.1.1. Recreate my results with mv break_xz_utils.txt break_xz_utils.c && gcc break_xz_utils.c -llzma && ./a.out on a UNIX platform with gcc.

C code: break_xz_utils.txt C output: c_output.txt Rust output: rust_output.txt