Skip to content

Commit 7a6556a

Browse files
fix: resolve potential infinite loop and panic in Huffman table generation
This commit addresses a test hang observed in `tests/offset_tests.rs` (specifically `test_offset_12_pattern`) by hardening the Huffman table generation logic in `src/decompress/mod.rs`. Changes: - **Fix `bsr32` Underflow:** Added a check for `diff == 0` before calling `bsr32` in the canonical codeword generation loop. When the table is fully utilized for a given bit length, `codeword ^ mask` can be 0, causing `bsr32` (implemented as `31 - leading_zeros`) to underflow/panic in debug builds or produce undefined shifts. The logic now correctly resets `codeword` to 0 in this edge case (wrapping around). - **Add Loop Guards:** Introduced explicit iteration limits to the nested loops in `build_decode_table`. If the loops exceed safe bounds (indicating an infinite loop due to invalid Huffman data or logic errors), the function now returns `false` (error) instead of hanging indefinitely. This prevents the process from getting stuck. This ensures robust handling of edge-case Huffman trees and prevents both crashes and hangs during table construction. Co-authored-by: 404Setup <[email protected]>
1 parent d1ccdb2 commit 7a6556a

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

src/decompress/mod.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,9 +1776,19 @@ fn build_decode_table(
17761776
return true;
17771777
}
17781778
let mut cur_table_end: usize = 1 << len;
1779+
let mut outer_iters = 0;
17791780
while len <= table_bits {
1781+
outer_iters += 1;
1782+
if outer_iters > 100 {
1783+
return false;
1784+
}
17801785
let mut count = len_counts[len];
1786+
let mut inner_iters = 0;
17811787
while count > 0 {
1788+
inner_iters += 1;
1789+
if inner_iters > 100000 {
1790+
return false;
1791+
}
17821792
decode_table[codeword as usize] =
17831793
make_decode_table_entry(decode_results, sorted_syms[sym_ptr] as usize, len as u32);
17841794
sym_ptr += 1;
@@ -1792,9 +1802,14 @@ fn build_decode_table(
17921802
}
17931803
return true;
17941804
}
1795-
let bit = 1 << bsr32(codeword ^ ((cur_table_end as u32) - 1));
1796-
codeword &= bit - 1;
1797-
codeword |= bit;
1805+
let diff = codeword ^ ((cur_table_end as u32) - 1);
1806+
if diff == 0 {
1807+
codeword = 0;
1808+
} else {
1809+
let bit = 1 << bsr32(diff);
1810+
codeword &= bit - 1;
1811+
codeword |= bit;
1812+
}
17981813
count -= 1;
17991814
}
18001815
loop {

0 commit comments

Comments
 (0)