Skip to content

Commit b157fea

Browse files
authored
Add Crc checksum validation for gzip::header::Parser
Ensure the header is valid Signed-off-by: Jiahao XU <[email protected]>
1 parent 5574102 commit b157fea

File tree

1 file changed

+49
-26
lines changed

1 file changed

+49
-26
lines changed

crates/compression-codecs/src/gzip/header.rs

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use compression_core::util::PartialBuffer;
2+
use flate2::Crc;
23
use std::io;
34

45
#[derive(Debug, Default)]
@@ -36,6 +37,7 @@ impl Default for State {
3637
pub(super) struct Parser {
3738
state: State,
3839
header: Header,
40+
crc: Crc,
3941
}
4042

4143
impl Header {
@@ -63,16 +65,33 @@ impl Header {
6365

6466
impl Parser {
6567
pub(super) fn input(&mut self, input: &mut PartialBuffer<&[u8]>) -> io::Result<Option<Header>> {
68+
let consume_input = |n| {
69+
self.crc.update(&input.unwritten()[..n]);
70+
input.advance(n);
71+
};
72+
73+
let consume_cstr = || {
74+
if let Some(len) = memchr::memchr(0, input.unwritten()) {
75+
consume_input(len + 1);
76+
Some(())
77+
} else {
78+
consume_input(input.unwritten().len());
79+
None
80+
}
81+
};
82+
6683
loop {
6784
match &mut self.state {
6885
State::Fixed(data) => {
6986
data.copy_unwritten_from(input);
7087

7188
if data.unwritten().is_empty() {
72-
self.header = Header::parse(&data.take().into_inner())?;
89+
let data = data.get_mut();
90+
self.crc.update(data);
91+
self.header = Header::parse(data)?;
7392
self.state = State::ExtraLen(<_>::default());
7493
} else {
75-
return Ok(None);
94+
break Ok(None)
7695
}
7796
}
7897

@@ -85,22 +104,24 @@ impl Parser {
85104
data.copy_unwritten_from(input);
86105

87106
if data.unwritten().is_empty() {
88-
let len = u16::from_le_bytes(data.take().into_inner());
107+
let data = data.get_mut();
108+
self.crc.update(data);
109+
let len = u16::from_le_bytes(data);
89110
self.state = State::Extra(len.into());
90111
} else {
91-
return Ok(None);
112+
break Ok(None)
92113
}
93114
}
94115

95116
State::Extra(bytes_to_consume) => {
96117
let n = input.unwritten().len().min(*bytes_to_consume);
97118
*bytes_to_consume -= n;
98-
input.advance(n);
119+
consume_input(n);
99120

100121
if *bytes_to_consume == 0 {
101122
self.state = State::Filename;
102123
} else {
103-
return Ok(None);
124+
break Ok(None)
104125
}
105126
}
106127

@@ -110,13 +131,8 @@ impl Parser {
110131
continue;
111132
}
112133

113-
if let Some(len) = memchr::memchr(0, input.unwritten()) {
114-
input.advance(len + 1);
115-
self.state = State::Comment;
116-
} else {
117-
input.advance(input.unwritten().len());
118-
return Ok(None);
119-
}
134+
consume_cstr()?;
135+
self.state = State::Comment;
120136
}
121137

122138
State::Comment => {
@@ -125,35 +141,42 @@ impl Parser {
125141
continue;
126142
}
127143

128-
if let Some(len) = memchr::memchr(0, input.unwritten()) {
129-
input.advance(len + 1);
130-
self.state = State::Crc(<_>::default());
131-
} else {
132-
input.advance(input.unwritten().len());
133-
return Ok(None);
134-
}
144+
consume_cstr()?;
145+
self.state = State::Crc(<_>::default());
135146
}
136147

137148
State::Crc(data) => {
149+
let header = std::mem::take(&mut self.header);
150+
138151
if !self.header.flags.crc {
139152
self.state = State::Done;
140-
return Ok(Some(std::mem::take(&mut self.header)));
153+
break Ok(Some(header))
141154
}
142155

143156
data.copy_unwritten_from(input);
144157

145-
if data.unwritten().is_empty() {
158+
break if data.unwritten().is_empty() {
146159
self.state = State::Done;
147-
return Ok(Some(std::mem::take(&mut self.header)));
160+
let checksum = self.crc.sum().to_le_bytes();
161+
let data = data.get_mut();
162+
163+
if data == checksum[..2] {
164+
Ok(Some(header))
165+
} else {
166+
Err(io::Error::new(
167+
io::ErrorKind::InvalidData,
168+
"CRC computed for header does not match",
169+
))
170+
}
148171
} else {
149-
return Ok(None);
172+
Ok(None)
150173
}
151174
}
152175

153176
State::Done => {
154-
return Err(io::Error::other("parser used after done"));
177+
break Err(io::Error::other("parser used after done"))
155178
}
156-
};
179+
}
157180
}
158181
}
159182
}

0 commit comments

Comments
 (0)