hickory_proto/serialize/binary/
decoder.rs

1/*
2 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::serialize::binary::Restrict;
18use thiserror::Error;
19
20/// This is non-destructive to the inner buffer, b/c for pointer types we need to perform a reverse
21///  seek to lookup names
22///
23/// A note on serialization, there was a thought to have this implement the Serde deserializer,
24///  but given that this is such a small subset of all the serialization which that performs
25///  this is a simpler implementation without the cruft, at least for serializing to/from the
26///  binary DNS protocols.
27pub struct BinDecoder<'a> {
28    buffer: &'a [u8],    // The entire original buffer
29    remaining: &'a [u8], // The unread section of the original buffer, so that reads do not cause a bounds check at the current seek offset
30}
31
32pub(crate) type DecodeResult<T> = Result<T, DecodeError>;
33
34/// An error that can occur deep in a decoder
35/// This type is kept very small so that function that use it inline often
36#[derive(Clone, Copy, Debug, Error)]
37#[non_exhaustive]
38pub enum DecodeError {
39    /// Insufficient data in the buffer for a read operation
40    #[error("unexpected end of input reached")]
41    InsufficientBytes,
42
43    /// slice_from was called with an invalid index
44    #[error(
45        "the index passed to BinDecoder::slice_from must be greater than the decoder position"
46    )]
47    InvalidPreviousIndex,
48
49    /// Pointer points to an index within or after the current label
50    #[error("label points to data not prior to idx: {idx} ptr: {ptr}")]
51    PointerNotPriorToLabel {
52        /// index of the label containing this pointer
53        idx: usize,
54        /// location to which the pointer is directing
55        ptr: u16,
56    },
57
58    /// Label bytes exceeded the limit of 63
59    #[error("label bytes exceed 63: {0}")]
60    LabelBytesTooLong(usize),
61
62    /// An unrecognized label code was found
63    #[error("unrecognized label code: {0:b}")]
64    UnrecognizedLabelCode(u8),
65
66    /// A domain name was too long
67    #[error("name label data exceed 255: {0}")]
68    DomainNameTooLong(usize),
69
70    /// Overlapping labels
71    #[error("overlapping labels name {label} other {other}")]
72    LabelOverlapsWithOther {
73        /// Start of the label that is overlaps
74        label: usize,
75        /// Start of the other label
76        other: usize,
77    },
78}
79
80impl<'a> BinDecoder<'a> {
81    /// Creates a new BinDecoder
82    ///
83    /// # Arguments
84    ///
85    /// * `buffer` - buffer from which all data will be read
86    pub fn new(buffer: &'a [u8]) -> Self {
87        BinDecoder {
88            buffer,
89            remaining: buffer,
90        }
91    }
92
93    /// Pop one byte from the buffer
94    pub fn pop(&mut self) -> DecodeResult<Restrict<u8>> {
95        if let Some((first, remaining)) = self.remaining.split_first() {
96            self.remaining = remaining;
97            return Ok(Restrict::new(*first));
98        }
99        Err(DecodeError::InsufficientBytes)
100    }
101
102    /// Returns the number of bytes in the buffer
103    ///
104    /// ```
105    /// use hickory_proto::serialize::binary::BinDecoder;
106    ///
107    /// let deadbeef = b"deadbeef";
108    /// let mut decoder = BinDecoder::new(deadbeef);
109    /// assert_eq!(decoder.len(), 8);
110    /// decoder.read_slice(7).unwrap();
111    /// assert_eq!(decoder.len(), 1);
112    /// ```
113    pub fn len(&self) -> usize {
114        self.remaining.len()
115    }
116
117    /// Returns `true` if the buffer is empty
118    pub fn is_empty(&self) -> bool {
119        self.len() == 0
120    }
121
122    /// Peed one byte forward, without moving the current index forward
123    pub fn peek(&self) -> Option<Restrict<u8>> {
124        Some(Restrict::new(*self.remaining.first()?))
125    }
126
127    /// Returns the current index in the buffer
128    pub fn index(&self) -> usize {
129        self.buffer.len() - self.remaining.len()
130    }
131
132    /// This is a pretty efficient clone, as the buffer is never cloned, and only the index is set
133    ///  to the value passed in
134    pub fn clone(&self, index_at: u16) -> Self {
135        BinDecoder {
136            buffer: self.buffer,
137            remaining: &self.buffer[index_at as usize..],
138        }
139    }
140
141    /// Reads a String from the buffer
142    ///
143    /// ```text
144    /// <character-string> is a single
145    /// length octet followed by that number of characters.  <character-string>
146    /// is treated as binary information, and can be up to 256 characters in
147    /// length (including the length octet).
148    /// ```
149    ///
150    /// # Returns
151    ///
152    /// A String version of the character data
153    pub fn read_character_data(&mut self) -> DecodeResult<Restrict<&[u8]>> {
154        let length = self.pop()?.unverified() as usize;
155        self.read_slice(length)
156    }
157
158    /// Reads a Vec out of the buffer
159    ///
160    /// # Arguments
161    ///
162    /// * `len` - number of bytes to read from the buffer
163    ///
164    /// # Returns
165    ///
166    /// The Vec of the specified length, otherwise an error
167    pub fn read_vec(&mut self, len: usize) -> DecodeResult<Restrict<Vec<u8>>> {
168        self.read_slice(len).map(|s| s.map(ToOwned::to_owned))
169    }
170
171    /// Reads a slice out of the buffer, without allocating
172    ///
173    /// # Arguments
174    ///
175    /// * `len` - number of bytes to read from the buffer
176    ///
177    /// # Returns
178    ///
179    /// The slice of the specified length, otherwise an error
180    pub fn read_slice(&mut self, len: usize) -> DecodeResult<Restrict<&'a [u8]>> {
181        if len > self.remaining.len() {
182            return Err(DecodeError::InsufficientBytes);
183        }
184        let (read, remaining) = self.remaining.split_at(len);
185        self.remaining = remaining;
186        Ok(Restrict::new(read))
187    }
188
189    /// Reads a slice from a previous index to the current
190    pub fn slice_from(&self, index: usize) -> DecodeResult<&'a [u8]> {
191        if index > self.index() {
192            return Err(DecodeError::InvalidPreviousIndex);
193        }
194
195        Ok(&self.buffer[index..self.index()])
196    }
197
198    /// Reads a byte from the buffer, equivalent to `Self::pop()`
199    pub fn read_u8(&mut self) -> DecodeResult<Restrict<u8>> {
200        self.pop()
201    }
202
203    /// Reads the next 2 bytes into u16
204    ///
205    /// This performs a byte-by-byte manipulation, there
206    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
207    ///
208    /// # Return
209    ///
210    /// Return the u16 from the buffer
211    pub fn read_u16(&mut self) -> DecodeResult<Restrict<u16>> {
212        Ok(self
213            .read_slice(2)?
214            .map(|s| u16::from_be_bytes([s[0], s[1]])))
215    }
216
217    /// Reads the next four bytes into i32.
218    ///
219    /// This performs a byte-by-byte manipulation, there
220    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
221    ///
222    /// # Return
223    ///
224    /// Return the i32 from the buffer
225    pub fn read_i32(&mut self) -> DecodeResult<Restrict<i32>> {
226        Ok(self.read_slice(4)?.map(|s| {
227            assert!(s.len() == 4);
228            i32::from_be_bytes([s[0], s[1], s[2], s[3]])
229        }))
230    }
231
232    /// Reads the next four bytes into u32.
233    ///
234    /// This performs a byte-by-byte manipulation, there
235    ///  which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
236    ///
237    /// # Return
238    ///
239    /// Return the u32 from the buffer
240    pub fn read_u32(&mut self) -> DecodeResult<Restrict<u32>> {
241        Ok(self.read_slice(4)?.map(|s| {
242            assert!(s.len() == 4);
243            u32::from_be_bytes([s[0], s[1], s[2], s[3]])
244        }))
245    }
246}
247
248#[cfg(test)]
249mod tests {
250    use super::*;
251
252    #[test]
253    fn test_read_slice() {
254        let deadbeef = b"deadbeef";
255        let mut decoder = BinDecoder::new(deadbeef);
256
257        let read = decoder.read_slice(4).expect("failed to read dead");
258        assert_eq!(&read.unverified(), b"dead");
259
260        let read = decoder.read_slice(2).expect("failed to read be");
261        assert_eq!(&read.unverified(), b"be");
262
263        let read = decoder.read_slice(0).expect("failed to read nothing");
264        assert_eq!(&read.unverified(), b"");
265
266        // this should fail
267        assert!(decoder.read_slice(3).is_err());
268    }
269
270    #[test]
271    fn test_read_slice_from() {
272        let deadbeef = b"deadbeef";
273        let mut decoder = BinDecoder::new(deadbeef);
274
275        decoder.read_slice(4).expect("failed to read dead");
276        let read = decoder.slice_from(0).expect("failed to get slice");
277        assert_eq!(&read, b"dead");
278
279        decoder.read_slice(2).expect("failed to read be");
280        let read = decoder.slice_from(4).expect("failed to get slice");
281        assert_eq!(&read, b"be");
282
283        decoder.read_slice(0).expect("failed to read nothing");
284        let read = decoder.slice_from(4).expect("failed to get slice");
285        assert_eq!(&read, b"be");
286
287        // this should fail
288        assert!(decoder.slice_from(10).is_err());
289    }
290}