Skip to content

Commit

Permalink
fix bug in inflate_fast when refilling
Browse files Browse the repository at this point in the history
the logic assumed a certain number of bits would be available; this was false in general.
  • Loading branch information
folkertdev committed Oct 7, 2024
1 parent 5630952 commit 54c1d70
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 21 deletions.
15 changes: 14 additions & 1 deletion zlib-rs/src/inflate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,20 @@ fn inflate_fast_help(state: &mut State, _start: usize) -> ReturnCode {
}

'outer: loop {
let mut here = bit_reader.refill_and(|hold| lcode[(hold & lmask) as usize]);
let mut here = {
let bits = bit_reader.bits_in_buffer();
let hold = bit_reader.hold();

bit_reader.refill();

// in most cases, the read can be interleaved with the logic
// based on benchmarks this matters in practice. wild.
if bits as usize >= state.len_table.bits {
lcode[(hold & lmask) as usize]
} else {
lcode[(bit_reader.hold() & lmask) as usize]
}
};

if here.op == 0 {
writer.push(here.val as u8);
Expand Down
20 changes: 0 additions & 20 deletions zlib-rs/src/inflate/bitreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,6 @@ impl<'a> BitReader<'a> {
self.bits_used |= 56;
}

#[inline(always)]
pub fn refill_and<T>(&mut self, f: impl Fn(u64) -> T) -> T {
debug_assert!(self.bytes_remaining() >= 8);

// the trick of this function is that the read can happen concurrently
// with the arithmetic below. That makes the read effectively free.
let read = unsafe { core::ptr::read_unaligned(self.ptr.cast::<u64>()) }.to_le();
let next_bit_buffer = self.bit_buffer | read << self.bits_used;

let increment = (63 - self.bits_used) >> 3;
self.ptr = self.ptr.wrapping_add(increment as usize);
self.bits_used |= 56;

let result = f(self.bit_buffer);

self.bit_buffer = next_bit_buffer;

result
}

#[inline(always)]
pub fn bits(&mut self, n: usize) -> u64 {
// debug_assert!( n <= self.bits_used, "{n} bits requested, but only {} avaliable", self.bits_used);
Expand Down

0 comments on commit 54c1d70

Please sign in to comment.