diff --git a/rmp/src/decode/est.rs b/rmp/src/decode/est.rs index 8782105e..83b1f68e 100644 --- a/rmp/src/decode/est.rs +++ b/rmp/src/decode/est.rs @@ -161,10 +161,10 @@ impl MessageLen { Marker::Array16 | Marker::Array32 | Marker::Map16 | - Marker::Map32 => self.read_marker_with_len(data, MarkerLen { marker, buf: [0; 4], has: 0 }), + Marker::Map32 | Marker::Ext8 | Marker::Ext16 | - Marker::Ext32 => todo!(), + Marker::Ext32 => self.read_marker_with_len(data, MarkerLen { marker, buf: [0; 4], has: 0 }), Marker::F32 => self.skip_data(data, 4), Marker::F64 => self.skip_data(data, 8), Marker::U8 => self.skip_data(data, 1), @@ -175,11 +175,12 @@ impl MessageLen { Marker::I16 => self.skip_data(data, 2), Marker::I32 => self.skip_data(data, 4), Marker::I64 => self.skip_data(data, 8), - Marker::FixExt1 | - Marker::FixExt2 | - Marker::FixExt4 | - Marker::FixExt8 | - Marker::FixExt16 => todo!(), + // type byte + data + Marker::FixExt1 => self.skip_data(data, 1 + 1), + Marker::FixExt2 => self.skip_data(data, 1 + 2), + Marker::FixExt4 => self.skip_data(data, 1 + 4), + Marker::FixExt8 => self.skip_data(data, 1 + 8), + Marker::FixExt16 => self.skip_data(data, 1 + 16), Marker::FixNeg(_) => Some(()), } } @@ -215,9 +216,10 @@ impl MessageLen { Marker::Str8 | Marker::Str16 | Marker::Str32 => self.skip_data(data, len), + // type byte + data; `len < max_len <= u32::MAX`, so `+ 1` can't overflow Marker::Ext8 | Marker::Ext16 | - Marker::Ext32 => todo!(), + Marker::Ext32 => self.skip_data(data, len + 1), Marker::Array16 | Marker::Array32 => self.read_sequence(data, len), Marker::Map16 | diff --git a/rmp/tests/repro_message_len_ext.rs b/rmp/tests/repro_message_len_ext.rs new file mode 100644 index 00000000..5da25eef --- /dev/null +++ b/rmp/tests/repro_message_len_ext.rs @@ -0,0 +1,46 @@ +use rmp::decode::{LenError, MessageLen}; + +// fixext1: marker, type, 1 data byte +#[test] +fn repro_len_of_fixext1() { + assert_eq!(MessageLen::len_of(&[0xd4, 0x01, 0x2a, 0xff]).unwrap(), 3); +} + +// [ext8 len=1 type=1 data] +#[test] +fn repro_len_of_ext8_in_array() { + assert_eq!(MessageLen::len_of(&[0x91, 0xc7, 0x01, 0x01, 0x2a, 0xff]).unwrap(), 5); +} + +#[test] +fn repro_len_of_ext16_truncated() { + // ext16 len=4: needs 1 + 2 + 1 + 4 = 8 bytes + match MessageLen::len_of(&[0xc8, 0x00, 0x04, 0x01, 0x00]) { + Err(LenError::Truncated(n)) => assert!(n.get() <= 8), + other => panic!("{other:?}"), + } +} + +#[test] +fn repro_len_of_matches_encoder() { + let mut buf = Vec::new(); + rmp::encode::write_array_len(&mut buf, 3).unwrap(); + rmp::encode::write_ext_meta(&mut buf, 3, 5).unwrap(); + buf.extend_from_slice(&[1, 2, 3]); + rmp::encode::write_ext_meta(&mut buf, 300, -1).unwrap(); + buf.extend_from_slice(&[0; 300]); + rmp::encode::write_ext_meta(&mut buf, 16, 7).unwrap(); + buf.extend_from_slice(&[9; 16]); + let total = buf.len(); + buf.push(0xc0); + assert_eq!(MessageLen::len_of(&buf).unwrap(), total); + let mut inc = MessageLen::new(); + let mut res = Err(LenError::ParseError); + for b in buf.chunks(1) { + res = inc.incremental_len(b); + if res.is_ok() { + break; + } + } + assert_eq!(res.unwrap(), total); +}