Skip to content

Commit

Permalink
fix(inflate): Reject input with too many litlen codes as per spec/zlib
Browse files Browse the repository at this point in the history
fixes #130
  • Loading branch information
oyvindln committed Dec 22, 2022
1 parent 0b8f10f commit f4ee585
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
25 changes: 21 additions & 4 deletions miniz_oxide/src/inflate/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ impl Default for DecompressorOxide {
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[non_exhaustive]
enum State {
Start = 0,
ReadZlibCmf,
Expand Down Expand Up @@ -292,6 +293,7 @@ enum State {
// Failure states.
BlockTypeUnexpected,
BadCodeSizeSum,
BadDistOrLiteralTableLength,
BadTotalSymbols,
BadZlibHeader,
DistanceOutOfBounds,
Expand All @@ -307,6 +309,7 @@ impl State {
match self {
BlockTypeUnexpected => true,
BadCodeSizeSum => true,
BadDistOrLiteralTableLength => true,
BadTotalSymbols => true,
BadZlibHeader => true,
DistanceOutOfBounds => true,
Expand Down Expand Up @@ -1279,7 +1282,18 @@ pub fn decompress(
} else {
memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0);
l.counter = 0;
Action::Jump(ReadHufflenTableCodeSize)
// Check that the litlen and distance are within spec.
// litlen table should be <=286 acc to the RFC and
// additionally zlib rejects dist table sizes larger than 30.
// NOTE this the final sizes after adding back predefined values, not
// raw value in the data.
// See miniz_oxide issue #130 and https://github.com/madler/zlib/issues/82.
if r.table_sizes[LITLEN_TABLE] <= 286 && r.table_sizes[DIST_TABLE] <= 30 {
Action::Jump(ReadHufflenTableCodeSize)
}
else {
Action::Jump(BadDistOrLiteralTableLength)
}
}
}),

Expand Down Expand Up @@ -1634,7 +1648,8 @@ pub fn decompress(
DoneForever => break TINFLStatus::Done,

// Anything else indicates failure.
// BadZlibHeader | BadRawLength | BlockTypeUnexpected | DistanceOutOfBounds |
// BadZlibHeader | BadRawLength | BadDistOrLiteralTableLength | BlockTypeUnexpected |
// DistanceOutOfBounds |
// BadTotalSymbols | BadCodeSizeDistPrevLookup | BadCodeSizeSum | InvalidLitlen |
// InvalidDist | InvalidCodeLen
_ => break TINFLStatus::Failed,
Expand Down Expand Up @@ -1836,18 +1851,20 @@ mod test {
// Bad check bits.
cr(&[0x78, 0x98], F, State::BadZlibHeader, true);


// Too many code lengths. (From inflate library issues)
cr(
b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcdM",
F,
State::BadTotalSymbols,
State::BadDistOrLiteralTableLength,
false,
);

// Bad CLEN (also from inflate library issues)
cr(
b"\xdd\xff\xff*M\x94ffffffffff",
F,
State::BadTotalSymbols,
State::BadDistOrLiteralTableLength,
false,
);

Expand Down
12 changes: 12 additions & 0 deletions miniz_oxide/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ fn issue_119_inflate_with_exact_limit() {
);
}

#[test]
fn issue_130_reject_invalid_table_sizes() {
let input = get_test_file_data("tests/test_data/issue_130_table_size.bin");


let result = decompress_to_vec_zlib(input.as_slice());
println!("{:?}", result);
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.status, TINFLStatus::Failed);
}

/*
#[test]
fn large_file() {
Expand Down

0 comments on commit f4ee585

Please sign in to comment.