Skip to content

Commit 14bf153

Browse files
authored
Merge pull request #231 from 404Setup/fix-decompress-bmi2-hang-6582532249254586770
Fix infinite loop and pointer update bug in decompress_bmi2
2 parents 33b039d + f510a6b commit 14bf153

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

src/decompress/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ impl Decompressor {
467467
DecompressResult::Success
468468
}
469469

470-
fn decompress_huffman_block(
470+
pub(crate) fn decompress_huffman_block(
471471
&mut self,
472472
input: &[u8],
473473
in_idx: &mut usize,

src/decompress/x86.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ pub unsafe fn decompress_bmi2(
267267
}
268268

269269
loop {
270+
let mut eob_found = false;
270271
unsafe {
271272
let in_ptr_start = input.as_ptr();
272273
let in_ptr_end = in_ptr_start.add(in_len);
@@ -292,6 +293,7 @@ pub unsafe fn decompress_bmi2(
292293
if entry & HUFFDEC_END_OF_BLOCK != 0 {
293294
bitbuf >>= entry as u8;
294295
bitsleft -= entry & 0xFF;
296+
eob_found = true;
295297
break;
296298
}
297299
if entry & HUFFDEC_SUBTABLE_POINTER != 0 {
@@ -323,6 +325,9 @@ pub unsafe fn decompress_bmi2(
323325

324326
let saved_bitbuf = bitbuf;
325327
let total_bits = entry & 0xFF;
328+
if bitsleft < total_bits {
329+
break;
330+
}
326331
bitbuf >>= total_bits;
327332
bitsleft -= total_bits;
328333

@@ -1733,10 +1738,30 @@ pub unsafe fn decompress_bmi2(
17331738
copied += 1;
17341739
}
17351740
}
1736-
out_idx += length;
1741+
out_next = out_next.add(length);
17371742
}
17381743
}
1744+
in_idx = in_next.offset_from(in_ptr_start) as usize;
1745+
out_idx = out_next.offset_from(out_ptr_start) as usize;
1746+
}
1747+
1748+
if eob_found {
1749+
break;
1750+
}
1751+
1752+
d.bitbuf = bitbuf;
1753+
d.bitsleft = bitsleft;
1754+
d.state = crate::decompress::DecompressorState::BlockBody;
1755+
1756+
let res = d.decompress_huffman_block(input, &mut in_idx, output, &mut out_idx);
1757+
1758+
bitbuf = d.bitbuf;
1759+
bitsleft = d.bitsleft;
1760+
1761+
if res != DecompressResult::Success {
1762+
return (res, in_idx, out_idx);
17391763
}
1764+
break;
17401765
}
17411766
}
17421767
_ => return (DecompressResult::BadData, 0, 0),

0 commit comments

Comments
 (0)