/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.22/src/msgs/codec.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use alloc::vec::Vec; |
2 | | use core::fmt::Debug; |
3 | | |
4 | | use crate::error::InvalidMessage; |
5 | | |
6 | | /// Wrapper over a slice of bytes that allows reading chunks from |
7 | | /// with the current position state held using a cursor. |
8 | | /// |
9 | | /// A new reader for a sub section of the buffer can be created |
10 | | /// using the `sub` function or a section of a certain length can |
11 | | /// be obtained using the `take` function |
12 | | pub struct Reader<'a> { |
13 | | /// The underlying buffer storing the readers content |
14 | | buffer: &'a [u8], |
15 | | /// Stores the current reading position for the buffer |
16 | | cursor: usize, |
17 | | } |
18 | | |
19 | | impl<'a> Reader<'a> { |
20 | | /// Creates a new Reader of the provided `bytes` slice with |
21 | | /// the initial cursor position of zero. |
22 | 0 | pub fn init(bytes: &'a [u8]) -> Self { |
23 | 0 | Reader { |
24 | 0 | buffer: bytes, |
25 | 0 | cursor: 0, |
26 | 0 | } |
27 | 0 | } |
28 | | |
29 | | /// Attempts to create a new Reader on a sub section of this |
30 | | /// readers bytes by taking a slice of the provided `length` |
31 | | /// will return None if there is not enough bytes |
32 | 0 | pub fn sub(&mut self, length: usize) -> Result<Self, InvalidMessage> { |
33 | 0 | match self.take(length) { |
34 | 0 | Some(bytes) => Ok(Reader::init(bytes)), |
35 | 0 | None => Err(InvalidMessage::MessageTooShort), |
36 | | } |
37 | 0 | } |
38 | | |
39 | | /// Borrows a slice of all the remaining bytes |
40 | | /// that appear after the cursor position. |
41 | | /// |
42 | | /// Moves the cursor to the end of the buffer length. |
43 | 0 | pub fn rest(&mut self) -> &'a [u8] { |
44 | 0 | let rest = &self.buffer[self.cursor..]; |
45 | 0 | self.cursor = self.buffer.len(); |
46 | 0 | rest |
47 | 0 | } |
48 | | |
49 | | /// Attempts to borrow a slice of bytes from the current |
50 | | /// cursor position of `length` if there is not enough |
51 | | /// bytes remaining after the cursor to take the length |
52 | | /// then None is returned instead. |
53 | 0 | pub fn take(&mut self, length: usize) -> Option<&'a [u8]> { |
54 | 0 | if self.left() < length { |
55 | 0 | return None; |
56 | 0 | } |
57 | 0 | let current = self.cursor; |
58 | 0 | self.cursor += length; |
59 | 0 | Some(&self.buffer[current..current + length]) |
60 | 0 | } |
61 | | |
62 | | /// Used to check whether the reader has any content left |
63 | | /// after the cursor (cursor has not reached end of buffer) |
64 | 0 | pub fn any_left(&self) -> bool { |
65 | 0 | self.cursor < self.buffer.len() |
66 | 0 | } |
67 | | |
68 | 0 | pub fn expect_empty(&self, name: &'static str) -> Result<(), InvalidMessage> { |
69 | 0 | match self.any_left() { |
70 | 0 | true => Err(InvalidMessage::TrailingData(name)), |
71 | 0 | false => Ok(()), |
72 | | } |
73 | 0 | } |
74 | | |
75 | | /// Returns the cursor position which is also the number |
76 | | /// of bytes that have been read from the buffer. |
77 | 0 | pub fn used(&self) -> usize { |
78 | 0 | self.cursor |
79 | 0 | } |
80 | | |
81 | | /// Returns the number of bytes that are still able to be |
82 | | /// read (The number of remaining takes) |
83 | 0 | pub fn left(&self) -> usize { |
84 | 0 | self.buffer.len() - self.cursor |
85 | 0 | } |
86 | | } |
87 | | |
88 | | /// Trait for implementing encoding and decoding functionality |
89 | | /// on something. |
90 | | pub trait Codec<'a>: Debug + Sized { |
91 | | /// Function for encoding itself by appending itself to |
92 | | /// the provided vec of bytes. |
93 | | fn encode(&self, bytes: &mut Vec<u8>); |
94 | | |
95 | | /// Function for decoding itself from the provided reader |
96 | | /// will return Some if the decoding was successful or |
97 | | /// None if it was not. |
98 | | fn read(_: &mut Reader<'a>) -> Result<Self, InvalidMessage>; |
99 | | |
100 | | /// Convenience function for encoding the implementation |
101 | | /// into a vec and returning it |
102 | 0 | fn get_encoding(&self) -> Vec<u8> { |
103 | 0 | let mut bytes = Vec::new(); |
104 | 0 | self.encode(&mut bytes); |
105 | 0 | bytes |
106 | 0 | } Unexecuted instantiation: <rustls::msgs::handshake::ClientHelloPayload as rustls::msgs::codec::Codec>::get_encoding Unexecuted instantiation: <rustls::msgs::handshake::CertificatePayloadTls13 as rustls::msgs::codec::Codec>::get_encoding Unexecuted instantiation: <rustls::msgs::handshake::HandshakeMessagePayload as rustls::msgs::codec::Codec>::get_encoding Unexecuted instantiation: <rustls::msgs::handshake::Random as rustls::msgs::codec::Codec>::get_encoding Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::get_encoding |
107 | | |
108 | | /// Function for wrapping a call to the read function in |
109 | | /// a Reader for the slice of bytes provided |
110 | | /// |
111 | | /// Returns `Err(InvalidMessage::ExcessData(_))` if |
112 | | /// `Self::read` does not read the entirety of `bytes`. |
113 | 0 | fn read_bytes(bytes: &'a [u8]) -> Result<Self, InvalidMessage> { |
114 | 0 | let mut reader = Reader::init(bytes); |
115 | 0 | Self::read(&mut reader).and_then(|r| { |
116 | 0 | reader.expect_empty("read_bytes")?; |
117 | 0 | Ok(r) |
118 | 0 | }) Unexecuted instantiation: <rustls::msgs::codec::u24 as rustls::msgs::codec::Codec>::read_bytes::{closure#0} Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::read_bytes::{closure#0} |
119 | 0 | } Unexecuted instantiation: <rustls::msgs::codec::u24 as rustls::msgs::codec::Codec>::read_bytes Unexecuted instantiation: <rustls::msgs::persist::ServerSessionValue as rustls::msgs::codec::Codec>::read_bytes |
120 | | } |
121 | | |
122 | | impl Codec<'_> for u8 { |
123 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
124 | 0 | bytes.push(*self); |
125 | 0 | } |
126 | | |
127 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
128 | 0 | match r.take(1) { |
129 | 0 | Some(&[byte]) => Ok(byte), |
130 | 0 | _ => Err(InvalidMessage::MissingData("u8")), |
131 | | } |
132 | 0 | } |
133 | | } |
134 | | |
135 | 0 | pub(crate) fn put_u16(v: u16, out: &mut [u8]) { |
136 | 0 | let out: &mut [u8; 2] = (&mut out[..2]).try_into().unwrap(); |
137 | 0 | *out = u16::to_be_bytes(v); |
138 | 0 | } |
139 | | |
140 | | impl Codec<'_> for u16 { |
141 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
142 | 0 | let mut b16 = [0u8; 2]; |
143 | 0 | put_u16(*self, &mut b16); |
144 | 0 | bytes.extend_from_slice(&b16); |
145 | 0 | } |
146 | | |
147 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
148 | 0 | match r.take(2) { |
149 | 0 | Some(&[b1, b2]) => Ok(Self::from_be_bytes([b1, b2])), |
150 | 0 | _ => Err(InvalidMessage::MissingData("u16")), |
151 | | } |
152 | 0 | } |
153 | | } |
154 | | |
155 | | // Make a distinct type for u24, even though it's a u32 underneath |
156 | | #[allow(non_camel_case_types)] |
157 | | #[derive(Debug, Copy, Clone)] |
158 | | pub struct u24(pub u32); |
159 | | |
160 | | #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] |
161 | | impl From<u24> for usize { |
162 | | #[inline] |
163 | 0 | fn from(v: u24) -> Self { |
164 | 0 | v.0 as Self |
165 | 0 | } |
166 | | } |
167 | | |
168 | | impl Codec<'_> for u24 { |
169 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
170 | 0 | let be_bytes = u32::to_be_bytes(self.0); |
171 | 0 | bytes.extend_from_slice(&be_bytes[1..]); |
172 | 0 | } |
173 | | |
174 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
175 | 0 | match r.take(3) { |
176 | 0 | Some(&[a, b, c]) => Ok(Self(u32::from_be_bytes([0, a, b, c]))), |
177 | 0 | _ => Err(InvalidMessage::MissingData("u24")), |
178 | | } |
179 | 0 | } |
180 | | } |
181 | | |
182 | | impl Codec<'_> for u32 { |
183 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
184 | 0 | bytes.extend(Self::to_be_bytes(*self)); |
185 | 0 | } |
186 | | |
187 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
188 | 0 | match r.take(4) { |
189 | 0 | Some(&[a, b, c, d]) => Ok(Self::from_be_bytes([a, b, c, d])), |
190 | 0 | _ => Err(InvalidMessage::MissingData("u32")), |
191 | | } |
192 | 0 | } |
193 | | } |
194 | | |
195 | 0 | pub(crate) fn put_u64(v: u64, bytes: &mut [u8]) { |
196 | 0 | let bytes: &mut [u8; 8] = (&mut bytes[..8]).try_into().unwrap(); |
197 | 0 | *bytes = u64::to_be_bytes(v); |
198 | 0 | } |
199 | | |
200 | | impl Codec<'_> for u64 { |
201 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
202 | 0 | let mut b64 = [0u8; 8]; |
203 | 0 | put_u64(*self, &mut b64); |
204 | 0 | bytes.extend_from_slice(&b64); |
205 | 0 | } |
206 | | |
207 | 0 | fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> { |
208 | 0 | match r.take(8) { |
209 | 0 | Some(&[a, b, c, d, e, f, g, h]) => Ok(Self::from_be_bytes([a, b, c, d, e, f, g, h])), |
210 | 0 | _ => Err(InvalidMessage::MissingData("u64")), |
211 | | } |
212 | 0 | } |
213 | | } |
214 | | |
215 | | /// Implement `Codec` for lists of elements that implement `TlsListElement`. |
216 | | /// |
217 | | /// `TlsListElement` provides the size of the length prefix for the list. |
218 | | impl<'a, T: Codec<'a> + TlsListElement + Debug> Codec<'a> for Vec<T> { |
219 | 0 | fn encode(&self, bytes: &mut Vec<u8>) { |
220 | 0 | let nest = LengthPrefixedBuffer::new(T::SIZE_LEN, bytes); |
221 | | |
222 | 0 | for i in self { |
223 | 0 | i.encode(nest.buf); |
224 | 0 | } |
225 | 0 | } Unexecuted instantiation: <alloc::vec::Vec<rustls_pki_types::CertificateDer> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::NamedGroup> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::Compression> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ECPointFormat> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ExtensionType> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::CertificateType> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::PSKKeyExchangeMode> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ClientCertificateType> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerName> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ResponderId> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ProtocolName> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::KeyShareEntry> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ClientExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertReqExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateEntry> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigPayload> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::DistinguishedName> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyBinder> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HelloRetryExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyIdentity> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HpkeSymmetricCipherSuite> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::NewSessionTicketExtension> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CipherSuite> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::ProtocolVersion> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::SignatureScheme> as rustls::msgs::codec::Codec>::encode Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CertificateCompressionAlgorithm> as rustls::msgs::codec::Codec>::encode |
226 | | |
227 | 0 | fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> { |
228 | 0 | let len = match T::SIZE_LEN { |
229 | 0 | ListLength::U8 => usize::from(u8::read(r)?), |
230 | 0 | ListLength::U16 => usize::from(u16::read(r)?), |
231 | 0 | ListLength::U24 { max, error } => match usize::from(u24::read(r)?) { |
232 | 0 | len if len > max => return Err(error), |
233 | 0 | len => len, |
234 | | }, |
235 | | }; |
236 | | |
237 | 0 | let mut sub = r.sub(len)?; |
238 | 0 | let mut ret = Self::new(); |
239 | 0 | while sub.any_left() { |
240 | 0 | ret.push(T::read(&mut sub)?); |
241 | | } |
242 | | |
243 | 0 | Ok(ret) |
244 | 0 | } Unexecuted instantiation: <alloc::vec::Vec<rustls_pki_types::CertificateDer> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::NamedGroup> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::Compression> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ECPointFormat> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ExtensionType> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::CertificateType> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::PSKKeyExchangeMode> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::enums::ClientCertificateType> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerName> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ResponderId> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ProtocolName> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::KeyShareEntry> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ClientExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::ServerExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertReqExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateEntry> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigPayload> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::DistinguishedName> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::EchConfigExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyBinder> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HelloRetryExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::CertificateExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::PresharedKeyIdentity> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::HpkeSymmetricCipherSuite> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::msgs::handshake::NewSessionTicketExtension> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CipherSuite> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::ProtocolVersion> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::SignatureScheme> as rustls::msgs::codec::Codec>::read Unexecuted instantiation: <alloc::vec::Vec<rustls::enums::CertificateCompressionAlgorithm> as rustls::msgs::codec::Codec>::read |
245 | | } |
246 | | |
247 | | /// A trait for types that can be encoded and decoded in a list. |
248 | | /// |
249 | | /// This trait is used to implement `Codec` for `Vec<T>`. Lists in the TLS wire format are |
250 | | /// prefixed with a length, the size of which depends on the type of the list elements. |
251 | | /// As such, the `Codec` implementation for `Vec<T>` requires an implementation of this trait |
252 | | /// for its element type `T`. |
253 | | pub(crate) trait TlsListElement { |
254 | | const SIZE_LEN: ListLength; |
255 | | } |
256 | | |
257 | | /// The length of the length prefix for a list. |
258 | | /// |
259 | | /// The types that appear in lists are limited to three kinds of length prefixes: |
260 | | /// 1, 2, and 3 bytes. For the latter kind, we require a `TlsListElement` implementer |
261 | | /// to specify a maximum length and error if the actual length is larger. |
262 | | pub(crate) enum ListLength { |
263 | | U8, |
264 | | U16, |
265 | | U24 { max: usize, error: InvalidMessage }, |
266 | | } |
267 | | |
268 | | /// Tracks encoding a length-delimited structure in a single pass. |
269 | | pub(crate) struct LengthPrefixedBuffer<'a> { |
270 | | pub(crate) buf: &'a mut Vec<u8>, |
271 | | len_offset: usize, |
272 | | size_len: ListLength, |
273 | | } |
274 | | |
275 | | impl<'a> LengthPrefixedBuffer<'a> { |
276 | | /// Inserts a dummy length into `buf`, and remembers where it went. |
277 | | /// |
278 | | /// After this, the body of the length-delimited structure should be appended to `LengthPrefixedBuffer::buf`. |
279 | | /// The length header is corrected in `LengthPrefixedBuffer::drop`. |
280 | 0 | pub(crate) fn new(size_len: ListLength, buf: &'a mut Vec<u8>) -> Self { |
281 | 0 | let len_offset = buf.len(); |
282 | 0 | buf.extend(match size_len { |
283 | 0 | ListLength::U8 => &[0xff][..], |
284 | 0 | ListLength::U16 => &[0xff, 0xff], |
285 | 0 | ListLength::U24 { .. } => &[0xff, 0xff, 0xff], |
286 | | }); |
287 | | |
288 | 0 | Self { |
289 | 0 | buf, |
290 | 0 | len_offset, |
291 | 0 | size_len, |
292 | 0 | } |
293 | 0 | } |
294 | | } |
295 | | |
296 | | impl Drop for LengthPrefixedBuffer<'_> { |
297 | | /// Goes back and corrects the length previously inserted at the start of the structure. |
298 | 0 | fn drop(&mut self) { |
299 | 0 | match self.size_len { |
300 | | ListLength::U8 => { |
301 | 0 | let len = self.buf.len() - self.len_offset - 1; |
302 | 0 | debug_assert!(len <= 0xff); |
303 | 0 | self.buf[self.len_offset] = len as u8; |
304 | | } |
305 | | ListLength::U16 => { |
306 | 0 | let len = self.buf.len() - self.len_offset - 2; |
307 | 0 | debug_assert!(len <= 0xffff); |
308 | 0 | let out: &mut [u8; 2] = (&mut self.buf[self.len_offset..self.len_offset + 2]) |
309 | 0 | .try_into() |
310 | 0 | .unwrap(); |
311 | 0 | *out = u16::to_be_bytes(len as u16); |
312 | | } |
313 | | ListLength::U24 { .. } => { |
314 | 0 | let len = self.buf.len() - self.len_offset - 3; |
315 | 0 | debug_assert!(len <= 0xff_ffff); |
316 | 0 | let len_bytes = u32::to_be_bytes(len as u32); |
317 | 0 | let out: &mut [u8; 3] = (&mut self.buf[self.len_offset..self.len_offset + 3]) |
318 | 0 | .try_into() |
319 | 0 | .unwrap(); |
320 | 0 | out.copy_from_slice(&len_bytes[1..]); |
321 | | } |
322 | | } |
323 | 0 | } |
324 | | } |
325 | | |
326 | | #[cfg(test)] |
327 | | mod tests { |
328 | | use std::prelude::v1::*; |
329 | | use std::vec; |
330 | | |
331 | | use super::*; |
332 | | |
333 | | #[test] |
334 | | fn interrupted_length_prefixed_buffer_leaves_maximum_length() { |
335 | | let mut buf = Vec::new(); |
336 | | let nested = LengthPrefixedBuffer::new(ListLength::U16, &mut buf); |
337 | | nested.buf.push(0xaa); |
338 | | assert_eq!(nested.buf, &vec![0xff, 0xff, 0xaa]); |
339 | | // <- if the buffer is accidentally read here, there is no possibility |
340 | | // that the contents of the length-prefixed buffer are interpreted |
341 | | // as a subsequent encoding (perhaps allowing injection of a different |
342 | | // extension) |
343 | | drop(nested); |
344 | | assert_eq!(buf, vec![0x00, 0x01, 0xaa]); |
345 | | } |
346 | | } |