Skip to content

Commit e7c7ab9

Browse files
change prefix_int to use u64 instead of usize (#223)
RFC 9204 4.1.1: QPACK implementations MUST be able to decode integers up to and including 62 bits long.
1 parent a530808 commit e7c7ab9

File tree

6 files changed

+159
-53
lines changed

6 files changed

+159
-53
lines changed

h3/src/qpack/block.rs

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,30 @@ impl HeaderPrefix {
177177
pub fn decode<R: Buf>(buf: &mut R) -> Result<Self, ParseError> {
178178
let (_, encoded_insert_count) = prefix_int::decode(8, buf)?;
179179
let (sign_negative, delta_base) = prefix_int::decode(7, buf)?;
180+
181+
if encoded_insert_count > (usize::MAX as u64) {
182+
return Err(ParseError::Integer(
183+
crate::qpack::prefix_int::Error::Overflow,
184+
));
185+
}
186+
187+
if delta_base > (usize::MAX as u64) {
188+
return Err(ParseError::Integer(
189+
crate::qpack::prefix_int::Error::Overflow,
190+
));
191+
}
192+
180193
Ok(Self {
181-
encoded_insert_count,
182-
delta_base,
194+
encoded_insert_count: encoded_insert_count as usize,
195+
delta_base: delta_base as usize,
183196
sign_negative: sign_negative == 1,
184197
})
185198
}
186199

187200
pub fn encode<W: BufMut>(&self, buf: &mut W) {
188201
let sign_bit = if self.sign_negative { 1 } else { 0 };
189-
prefix_int::encode(8, 0, self.encoded_insert_count, buf);
190-
prefix_int::encode(7, sign_bit, self.delta_base, buf);
202+
prefix_int::encode(8, 0, self.encoded_insert_count as u64, buf);
203+
prefix_int::encode(7, sign_bit, self.delta_base as u64, buf);
191204
}
192205
}
193206

@@ -200,16 +213,32 @@ pub enum Indexed {
200213
impl Indexed {
201214
pub fn decode<R: Buf>(buf: &mut R) -> Result<Self, ParseError> {
202215
match prefix_int::decode(6, buf)? {
203-
(0b11, i) => Ok(Indexed::Static(i)),
204-
(0b10, i) => Ok(Indexed::Dynamic(i)),
216+
(0b11, i) => {
217+
if i > (usize::MAX as u64) {
218+
return Err(ParseError::Integer(
219+
crate::qpack::prefix_int::Error::Overflow,
220+
));
221+
}
222+
223+
Ok(Indexed::Static(i as usize))
224+
}
225+
(0b10, i) => {
226+
if i > (usize::MAX as u64) {
227+
return Err(ParseError::Integer(
228+
crate::qpack::prefix_int::Error::Overflow,
229+
));
230+
}
231+
232+
Ok(Indexed::Dynamic(i as usize))
233+
}
205234
(f, _) => Err(ParseError::InvalidPrefix(f)),
206235
}
207236
}
208237

209238
pub fn encode<W: BufMut>(&self, buf: &mut W) {
210239
match self {
211-
Indexed::Static(i) => prefix_int::encode(6, 0b11, *i, buf),
212-
Indexed::Dynamic(i) => prefix_int::encode(6, 0b10, *i, buf),
240+
Indexed::Static(i) => prefix_int::encode(6, 0b11, *i as u64, buf),
241+
Indexed::Dynamic(i) => prefix_int::encode(6, 0b10, *i as u64, buf),
213242
}
214243
}
215244
}
@@ -220,13 +249,21 @@ pub struct IndexedWithPostBase(pub usize);
220249
impl IndexedWithPostBase {
221250
pub fn decode<R: Buf>(buf: &mut R) -> Result<Self, ParseError> {
222251
match prefix_int::decode(4, buf)? {
223-
(0b0001, i) => Ok(IndexedWithPostBase(i)),
252+
(0b0001, i) => {
253+
if i > (usize::MAX as u64) {
254+
return Err(ParseError::Integer(
255+
crate::qpack::prefix_int::Error::Overflow,
256+
));
257+
}
258+
259+
Ok(IndexedWithPostBase(i as usize))
260+
}
224261
(f, _) => Err(ParseError::InvalidPrefix(f)),
225262
}
226263
}
227264

228265
pub fn encode<W: BufMut>(&self, buf: &mut W) {
229-
prefix_int::encode(4, 0b0001, self.0, buf)
266+
prefix_int::encode(4, 0b0001, self.0 as u64, buf)
230267
}
231268
}
232269

@@ -253,26 +290,42 @@ impl LiteralWithNameRef {
253290

254291
pub fn decode<R: Buf>(buf: &mut R) -> Result<Self, ParseError> {
255292
match prefix_int::decode(4, buf)? {
256-
(f, i) if f & 0b0101 == 0b0101 => Ok(LiteralWithNameRef::new_static(
257-
i,
258-
prefix_string::decode(8, buf)?,
259-
)),
260-
(f, i) if f & 0b0101 == 0b0100 => Ok(LiteralWithNameRef::new_dynamic(
261-
i,
262-
prefix_string::decode(8, buf)?,
263-
)),
293+
(f, i) if f & 0b0101 == 0b0101 => {
294+
if i > (usize::MAX as u64) {
295+
return Err(ParseError::Integer(
296+
crate::qpack::prefix_int::Error::Overflow,
297+
));
298+
}
299+
300+
Ok(LiteralWithNameRef::new_static(
301+
i as usize,
302+
prefix_string::decode(8, buf)?,
303+
))
304+
}
305+
(f, i) if f & 0b0101 == 0b0100 => {
306+
if i > (usize::MAX as u64) {
307+
return Err(ParseError::Integer(
308+
crate::qpack::prefix_int::Error::Overflow,
309+
));
310+
}
311+
312+
Ok(LiteralWithNameRef::new_dynamic(
313+
i as usize,
314+
prefix_string::decode(8, buf)?,
315+
))
316+
}
264317
(f, _) => Err(ParseError::InvalidPrefix(f)),
265318
}
266319
}
267320

268321
pub fn encode<W: BufMut>(&self, buf: &mut W) -> Result<(), prefix_string::Error> {
269322
match self {
270323
LiteralWithNameRef::Static { index, value } => {
271-
prefix_int::encode(4, 0b0101, *index, buf);
324+
prefix_int::encode(4, 0b0101, *index as u64, buf);
272325
prefix_string::encode(8, 0, value, buf)?;
273326
}
274327
LiteralWithNameRef::Dynamic { index, value } => {
275-
prefix_int::encode(4, 0b0100, *index, buf);
328+
prefix_int::encode(4, 0b0100, *index as u64, buf);
276329
prefix_string::encode(8, 0, value, buf)?;
277330
}
278331
}
@@ -296,16 +349,24 @@ impl LiteralWithPostBaseNameRef {
296349

297350
pub fn decode<R: Buf>(buf: &mut R) -> Result<Self, ParseError> {
298351
match prefix_int::decode(3, buf)? {
299-
(f, i) if f & 0b1111_0000 == 0 => Ok(LiteralWithPostBaseNameRef::new(
300-
i,
301-
prefix_string::decode(8, buf)?,
302-
)),
352+
(f, i) if f & 0b1111_0000 == 0 => {
353+
if i > (usize::MAX as u64) {
354+
return Err(ParseError::Integer(
355+
crate::qpack::prefix_int::Error::Overflow,
356+
));
357+
}
358+
359+
Ok(LiteralWithPostBaseNameRef::new(
360+
i as usize,
361+
prefix_string::decode(8, buf)?,
362+
))
363+
}
303364
(f, _) => Err(ParseError::InvalidPrefix(f)),
304365
}
305366
}
306367

307368
pub fn encode<W: BufMut>(&self, buf: &mut W) -> Result<(), prefix_string::Error> {
308-
prefix_int::encode(3, 0b0000, self.index, buf);
369+
prefix_int::encode(3, 0b0000, self.index as u64, buf);
309370
prefix_string::encode(8, 0, &self.value, buf)?;
310371
Ok(())
311372
}
@@ -347,6 +408,7 @@ impl Literal {
347408
#[cfg(test)]
348409
mod test {
349410
use super::*;
411+
use std::convert::TryInto;
350412
use std::io::Cursor;
351413

352414
const TABLE_SIZE: usize = 4096;
@@ -424,7 +486,7 @@ mod test {
424486
#[test]
425487
fn base_index_too_small() {
426488
let mut buf = vec![];
427-
let encoded_largest_ref = (2 % (2 * TABLE_SIZE / 32)) + 1;
489+
let encoded_largest_ref: u64 = ((2 % (2 * TABLE_SIZE / 32)) + 1).try_into().unwrap();
428490
prefix_int::encode(8, 0, encoded_largest_ref, &mut buf);
429491
prefix_int::encode(7, 1, 2, &mut buf); // base index negative = 0
430492

h3/src/qpack/decoder.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use bytes::{Buf, BufMut};
2-
use std::{fmt, io::Cursor};
2+
use std::{convert::TryInto, fmt, io::Cursor, num::TryFromIntError};
33

44
use tracing::trace;
55

@@ -36,6 +36,7 @@ pub enum Error {
3636
BadBaseIndex(isize),
3737
UnexpectedEnd,
3838
HeaderTooLong(u64),
39+
BufSize(TryFromIntError),
3940
}
4041

4142
impl std::error::Error for Error {}
@@ -53,6 +54,7 @@ impl std::fmt::Display for Error {
5354
Error::BadBaseIndex(i) => write!(f, "out of bounds base index: {}", i),
5455
Error::UnexpectedEnd => write!(f, "unexpected end"),
5556
Error::HeaderTooLong(_) => write!(f, "header too long"),
57+
Error::BufSize(_) => write!(f, "number in buffer wrong size"),
5658
}
5759
}
5860
}
@@ -126,7 +128,8 @@ impl Decoder {
126128
}
127129

128130
if self.table.total_inserted() != inserted_on_start {
129-
InsertCountIncrement(self.table.total_inserted() - inserted_on_start).encode(write);
131+
InsertCountIncrement((self.table.total_inserted() - inserted_on_start).try_into()?)
132+
.encode(write);
130133
}
131134

132135
Ok(self.table.total_inserted())
@@ -326,6 +329,12 @@ impl From<ParseError> for Error {
326329
}
327330
}
328331

332+
impl From<TryFromIntError> for Error {
333+
fn from(error: TryFromIntError) -> Self {
334+
Error::BufSize(error)
335+
}
336+
}
337+
329338
#[cfg(test)]
330339
mod tests {
331340
use super::*;

h3/src/qpack/encoder.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,8 @@ impl Action {
239239
let first = buf.chunk()[0];
240240
let instruction = match DecoderInstruction::decode(first) {
241241
DecoderInstruction::Unknown => return Err(Error::UnknownDecoderInstruction(first)),
242-
DecoderInstruction::InsertCountIncrement => {
243-
InsertCountIncrement::decode(&mut buf)?.map(|x| Action::ReceivedRefIncrement(x.0))
244-
}
242+
DecoderInstruction::InsertCountIncrement => InsertCountIncrement::decode(&mut buf)?
243+
.map(|x| Action::ReceivedRefIncrement(x.0 as usize)),
245244
DecoderInstruction::HeaderAck => {
246245
HeaderAck::decode(&mut buf)?.map(|x| Action::Untrack(x.0))
247246
}

h3/src/qpack/prefix_int.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl std::fmt::Display for Error {
1919
}
2020
}
2121

22-
pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<(u8, usize), Error> {
22+
pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<(u8, u64), Error> {
2323
assert!(size <= 8);
2424
let mut first = buf.get::<u8>()?;
2525

@@ -31,13 +31,13 @@ pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<(u8, usize), Error> {
3131

3232
// if first < 2usize.pow(size) - 1
3333
if first < mask {
34-
return Ok((flags, first as usize));
34+
return Ok((flags, first as u64));
3535
}
3636

37-
let mut value = mask as usize;
37+
let mut value = mask as u64;
3838
let mut power = 0usize;
3939
loop {
40-
let byte = buf.get::<u8>()? as usize;
40+
let byte = buf.get::<u8>()? as u64;
4141
value += (byte & 127) << power;
4242
power += 7;
4343

@@ -53,21 +53,21 @@ pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<(u8, usize), Error> {
5353
Ok((flags, value))
5454
}
5555

56-
pub fn encode<B: BufMut>(size: u8, flags: u8, value: usize, buf: &mut B) {
56+
pub fn encode<B: BufMut>(size: u8, flags: u8, value: u64, buf: &mut B) {
5757
assert!(size <= 8);
5858
// NOTE: following casts to u8 intend to trim the most significant bits, they are used as a
5959
// workaround for shiftoverflow errors when size == 8.
6060
let mask = !(0xFF << size) as u8;
6161
let flags = ((flags as usize) << size) as u8;
6262

6363
// if value < 2usize.pow(size) - 1
64-
if value < (mask as usize) {
64+
if value < (mask as u64) {
6565
buf.write(flags | value as u8);
6666
return;
6767
}
6868

6969
buf.write(mask | flags);
70-
let mut remaining = value - mask as usize;
70+
let mut remaining = value - mask as u64;
7171

7272
while remaining >= 128 {
7373
let rest = (remaining % 128) as u8;
@@ -93,7 +93,7 @@ impl From<coding::UnexpectedEnd> for Error {
9393
mod test {
9494
use std::io::Cursor;
9595

96-
fn check_codec(size: u8, flags: u8, value: usize, data: &[u8]) {
96+
fn check_codec(size: u8, flags: u8, value: u64, data: &[u8]) {
9797
let mut buf = Vec::new();
9898
super::encode(size, flags, value, &mut buf);
9999
assert_eq!(buf, data);
@@ -110,7 +110,7 @@ mod test {
110110
check_codec(
111111
5,
112112
0b010,
113-
usize::max_value(),
113+
u64::max_value(),
114114
&[95, 224, 255, 255, 255, 255, 255, 255, 255, 255, 1],
115115
);
116116
}
@@ -122,7 +122,7 @@ mod test {
122122
check_codec(
123123
8,
124124
0,
125-
usize::max_value(),
125+
u64::max_value(),
126126
&[255, 128, 254, 255, 255, 255, 255, 255, 255, 255, 1],
127127
);
128128
}

h3/src/qpack/prefix_string/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ mod bitwin;
22
mod decode;
33
mod encode;
44

5+
use std::convert::TryInto;
56
use std::fmt;
7+
use std::num::TryFromIntError;
68

79
use bytes::{Buf, BufMut};
810

@@ -22,6 +24,7 @@ pub enum Error {
2224
Integer(IntegerError),
2325
HuffmanDecoding(HuffmanDecodingError),
2426
HuffmanEncoding(HuffmanEncodingError),
27+
BufSize(TryFromIntError),
2528
}
2629

2730
impl std::fmt::Display for Error {
@@ -31,12 +34,14 @@ impl std::fmt::Display for Error {
3134
Error::Integer(e) => write!(f, "could not parse integer: {}", e),
3235
Error::HuffmanDecoding(e) => write!(f, "Huffman decode failed: {:?}", e),
3336
Error::HuffmanEncoding(e) => write!(f, "Huffman encode failed: {:?}", e),
37+
Error::BufSize(_) => write!(f, "number in buffer wrong size"),
3438
}
3539
}
3640
}
3741

3842
pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<Vec<u8>, Error> {
3943
let (flags, len) = prefix_int::decode(size - 1, buf)?;
44+
let len: usize = len.try_into()?;
4045
if buf.remaining() < len {
4146
return Err(Error::UnexpectedEnd);
4247
}
@@ -56,7 +61,7 @@ pub fn decode<B: Buf>(size: u8, buf: &mut B) -> Result<Vec<u8>, Error> {
5661

5762
pub fn encode<B: BufMut>(size: u8, flags: u8, value: &[u8], buf: &mut B) -> Result<(), Error> {
5863
let encoded = Vec::from(value).hpack_encode()?;
59-
prefix_int::encode(size - 1, flags << 1 | 1, encoded.len(), buf);
64+
prefix_int::encode(size - 1, flags << 1 | 1, encoded.len().try_into()?, buf);
6065
for byte in encoded {
6166
buf.write(byte);
6267
}
@@ -84,6 +89,12 @@ impl From<HuffmanDecodingError> for Error {
8489
}
8590
}
8691

92+
impl From<TryFromIntError> for Error {
93+
fn from(error: TryFromIntError) -> Self {
94+
Error::BufSize(error)
95+
}
96+
}
97+
8798
#[cfg(test)]
8899
mod tests {
89100
use super::*;

0 commit comments

Comments
 (0)