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