nonymous/
view.rs

1//! Fast views into encoded protocol elements.
2//!
3//! Most of these views consist of a reference to the whole source material (often necessary to
4//! decode names under message compression), a starting offset into that source material, and some
5//! additional information we can use to quickly revisit parts of that protocol element.
6
7mod cmp;
8mod inherent;
9mod iter;
10
11pub use self::iter::{CharacterStrings, Labels, Questions, Records};
12
13use core::{
14    fmt::{Debug, Display},
15    ops::{Bound, Range, RangeBounds},
16};
17
18use byteorder::{ByteOrder, NetworkEndian};
19
20use crate::{core::Type, seen::Seen};
21
22/// A view and the part of the given range that wasn’t consumed, or an error.
23// FIXME Result<'s, V: View<'s>> (rust-lang/rust#21903)
24pub type Result<V, E> = core::result::Result<(V, Range<usize>), E>;
25
26/// A trait for objects that view a given buffer and range into that buffer.
27pub trait View<'s>: 's {
28    type Error: Debug + Display;
29
30    fn view(source: &'s [u8], range: impl RangeBounds<usize>) -> Result<Self, Self::Error>
31    where
32        Self: Sized,
33    {
34        let start = match range.start_bound() {
35            Bound::Included(&x) => x,
36            Bound::Excluded(&x) => x + 1,
37            Bound::Unbounded => 0,
38        };
39        let stop = match range.end_bound() {
40            Bound::Included(&x) => x + 1,
41            Bound::Excluded(&x) => x,
42            Bound::Unbounded => source.len(),
43        };
44
45        Self::view_range(source, start..stop)
46    }
47
48    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error>
49    where
50        Self: Sized;
51}
52
53pub trait BorrowedView<'s> {
54    fn source(&self) -> &'s [u8];
55    fn offset(&self) -> usize;
56    fn len(&self) -> usize;
57    fn as_bytes(&self) -> &'s [u8] {
58        &self.source()[self.offset()..][..self.len()]
59    }
60}
61
62pub trait ViewToOwned<Owned> {
63    fn to_owned(&self) -> Owned;
64}
65
66/// A query or response (RFC 1035 § 4.1).
67///
68/// # Examples
69///
70/// ```rust
71/// use nonymous::view::{Message, View};
72/// let source = b"\x13\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
73/// let (message, rest) = Message::view(source, ..)?;
74/// # Ok::<(), nonymous::view::MessageError>(())
75/// ```
76#[derive(Debug, Clone)]
77pub struct Message<'s> {
78    source: &'s [u8],
79    offset: usize,
80    qd_len: usize,
81    an_len: usize,
82    ns_len: usize,
83    ar_len: usize,
84    opt: Option<Extension<'s>>,
85}
86
87/// A header section (RFC 1035 § 4.1.1).
88///
89/// # Examples
90///
91/// ```rust
92/// use nonymous::view::{Header, View};
93/// let source = b"\x13\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
94/// let (header, rest) = Header::view(source, ..)?;
95/// # Ok::<(), nonymous::view::BoundsError>(())
96/// ```
97#[derive(Debug, Clone)]
98pub struct Header<'s> {
99    source: &'s [u8],
100    offset: usize,
101}
102
103/// A question (RFC 1035 § 4.1.2).
104///
105/// # Examples
106///
107/// ```rust
108/// use nonymous::view::{Question, View};
109/// let source = b"\x05daria\x03daz\x03cat\0\x00\x01\x00\x01";
110/// let (question, rest) = Question::view(source, ..)?;
111/// # Ok::<(), nonymous::view::QuestionError>(())
112/// ```
113#[derive(Debug, Clone)]
114pub struct Question<'s> {
115    source: &'s [u8],
116    offset: usize,
117    len: usize,
118}
119
120/// A resource record (RFC 1035 § 4.1.3).
121///
122/// # Examples
123///
124/// ```rust
125/// use nonymous::view::{Record, View};
126/// let source = b"\x05daria\x03daz\x03cat\0\x00\x01\x00\x01\0\0\0\0\x00\x04\xC0\x00\x02\x01";
127/// let (record, rest) = Record::view(source, ..)?;
128/// # Ok::<(), nonymous::view::RecordError>(())
129/// ```
130#[derive(Debug, Clone)]
131pub struct Record<'s> {
132    source: &'s [u8],
133    offset: usize,
134    name_len: usize,
135    rdata_len: usize,
136}
137
138/// A domain name (RFC 1035 § 3.1). Always rooted, with the last label being the root label.
139///
140/// # Examples
141///
142/// ```rust
143/// use nonymous::view::{Name, View};
144/// let source = b"\x05daria\x03daz\x03cat\0";
145/// let (name, rest) = Name::view(source, ..)?;
146/// # Ok::<(), nonymous::view::NameError>(())
147/// ```
148#[derive(Debug, Clone)]
149pub struct Name<'s> {
150    source: &'s [u8],
151    offset: usize,
152    len: usize,
153}
154
155/// A label or pointer (RFC 1035 § 4.1.4).
156///
157/// # Examples
158///
159/// ```rust
160/// use nonymous::view::{Label, View};
161/// let source = b"\x07example";
162/// let (label, rest) = Label::view(source, ..)?;
163/// # Ok::<(), nonymous::view::LabelError>(())
164/// ```
165#[derive(Debug, Clone)]
166pub struct Label<'s> {
167    source: &'s [u8],
168    offset: usize,
169    len: usize,
170}
171
172/// An OPT record (RFC 6891 § 6.1.1).
173///
174/// # Examples
175///
176/// ```rust
177/// # #[macro_use] extern crate nonymous;
178/// # declare_any_error!(AnyError);
179/// use nonymous::view::{Extension, Record, View};
180/// let source = b"\0\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00";
181/// let (record, rest) = Record::view(source, ..)?;
182/// let extension = Extension::wrap(record)?;
183/// # Ok::<(), AnyError>(())
184/// ```
185#[derive(Debug, Clone)]
186pub struct Extension<'s> {
187    pub inner: Record<'s>,
188}
189
190/// A character string (RFC 1035 § 3.3).
191///
192/// # Examples
193///
194/// ```rust
195/// use nonymous::view::{CharacterString, View};
196/// let source = b"\x0BHello, world!";
197/// let (class, rest) = CharacterString::view(source, ..)?;
198/// # Ok::<(), nonymous::view::BoundsError>(())
199/// ```
200pub struct CharacterString<'s> {
201    source: &'s [u8],
202    offset: usize,
203    len: usize,
204}
205
206error!(BoundsError);
207#[derive(Debug, displaydoc::Display)]
208#[prefix_enum_doc_attributes]
209/// bounds check failed
210pub enum BoundsError {
211    /// range start ({0}) exceeds end ({1})
212    BackwardsRange(usize, usize),
213
214    /// range end ({0}) exceeds source length ({1})
215    RangeOverflow(usize, usize),
216
217    /// read length ({0}) exceeds remaining offset range ({1}..{2})
218    ReadOverflow(usize, usize, usize),
219}
220
221error!(MessageError(_edns_version, [inner: inner]));
222/// failed to view message: {1}
223#[derive(Debug, displaydoc::Display)]
224pub struct MessageError(pub Option<u8>, pub MessageErrorKind);
225
226error!(MessageErrorKind, Header, Question, Record, Extension);
227#[derive(Debug, displaydoc::Display)]
228pub enum MessageErrorKind {
229    /// message has malformed header
230    Header(BoundsError),
231
232    /// message has malformed question
233    Question(QuestionError),
234
235    /// message has malformed record
236    Record(RecordError),
237
238    /// message has malformed OPT RR
239    Extension(ExtensionError),
240
241    /// OPT RR outside of the additional section (RFC 6891 § 6.1.1)
242    MisplacedOptRecord,
243
244    /// message has more than one OPT RR (RFC 6891 § 6.1.1)
245    MultipleOptRecords,
246}
247
248error!(QuestionError, Bounds, Name);
249/// failed to view question
250#[derive(Debug, displaydoc::Display)]
251#[prefix_enum_doc_attributes]
252pub enum QuestionError {
253    /// eof while viewing QTYPE or QCLASS
254    Bounds(BoundsError),
255
256    /// question has malformed QNAME
257    Name(NameError),
258}
259
260error!(RecordError, Bounds, Name);
261/// failed to view record
262#[derive(Debug, displaydoc::Display)]
263#[prefix_enum_doc_attributes]
264pub enum RecordError {
265    /// eof while viewing TYPE or CLASS or TTL or RDLENGTH or RDATA
266    Bounds(BoundsError),
267
268    /// record has malformed NAME
269    Name(NameError),
270}
271
272error!(NameError, Label);
273/// failed to view name
274#[derive(Debug, displaydoc::Display)]
275#[prefix_enum_doc_attributes]
276pub enum NameError {
277    /// name has malformed label
278    Label(LabelError),
279
280    /// message compression pointer forms cycle
281    PointerCycle,
282
283    /// name is longer than 255 octets excluding null label (RFC 2181 § 11)
284    TooLong,
285}
286
287error!(LabelError, Bounds);
288/// failed to view label
289#[derive(Debug, displaydoc::Display)]
290#[prefix_enum_doc_attributes]
291pub enum LabelError {
292    /// eof while viewing length octet or label content
293    Bounds(BoundsError),
294
295    /// label has reserved length octet (RFC 1035 § 4.1.4)
296    ReservedLength,
297}
298
299error!(ExtensionError);
300/// failed to view OPT RR
301#[derive(Debug, displaydoc::Display)]
302#[prefix_enum_doc_attributes]
303pub enum ExtensionError {
304    /// OPT RR has NAME other than “.” (RFC 6891 § 6.1.2)
305    BadName,
306
307    /// OPT RR has unimplemented VERSION (RFC 6891 § 6.1.3)
308    UnimplementedVersion,
309}
310
311impl<'s> View<'s> for Message<'s> {
312    type Error = MessageError;
313
314    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
315        use self::MessageErrorKind as Kind;
316
317        let (header, rest) =
318            Header::view(source, range.clone()).map_err(|e| MessageError(None, Kind::Header(e)))?;
319
320        let qdcount = header.qdcount();
321        let ancount = header.ancount();
322        let nscount = header.nscount();
323        let arcount = header.arcount();
324
325        let mut next = rest;
326        let section = next.clone();
327
328        for _ in 0..qdcount {
329            let (_, rest) =
330                Question::view(source, next).map_err(|e| MessageError(None, Kind::Question(e)))?;
331            next = rest;
332        }
333
334        let qd_len = next.start - section.start;
335        let section = next.clone();
336
337        for _ in 0..ancount {
338            let (record, rest) =
339                Record::view(source, next).map_err(|e| MessageError(None, Kind::Record(e)))?;
340            next = rest;
341
342            if record.r#type() == Type::OPT {
343                let version = record.ttl().edns_version();
344                return Err(MessageError(Some(version), Kind::MisplacedOptRecord));
345            }
346        }
347
348        let an_len = next.start - section.start;
349        let section = next.clone();
350
351        for _ in 0..nscount {
352            let (record, rest) =
353                Record::view(source, next).map_err(|e| MessageError(None, Kind::Record(e)))?;
354            next = rest;
355
356            if record.r#type() == Type::OPT {
357                let version = record.ttl().edns_version();
358                return Err(MessageError(Some(version), Kind::MisplacedOptRecord));
359            }
360        }
361
362        let ns_len = next.start - section.start;
363        let section = next.clone();
364        let mut opt = None;
365        let mut edns_version = None;
366
367        for _ in 0..arcount {
368            let (record, rest) = Record::view(source, next)
369                .map_err(|e| MessageError(edns_version, Kind::Record(e)))?;
370            next = rest;
371
372            if record.r#type() == Type::OPT {
373                if opt.is_some() {
374                    return Err(MessageError(edns_version, Kind::MultipleOptRecords));
375                }
376                edns_version = Some(record.ttl().edns_version());
377                opt = Some(
378                    Extension::wrap(record)
379                        .map_err(|e| MessageError(edns_version, Kind::Extension(e)))?,
380                );
381            }
382        }
383
384        let ar_len = next.start - section.start;
385        let rest = next;
386
387        Ok((
388            Message {
389                source,
390                opt,
391                offset: range.start,
392                qd_len,
393                an_len,
394                ns_len,
395                ar_len,
396            },
397            rest,
398        ))
399    }
400}
401impl<'s> BorrowedView<'s> for Message<'s> {
402    fn source(&self) -> &'s [u8] {
403        self.source
404    }
405    fn offset(&self) -> usize {
406        self.offset
407    }
408    fn len(&self) -> usize {
409        self.header().len() + self.qd_len + self.an_len + self.ns_len + self.ar_len
410    }
411}
412
413impl<'s> View<'s> for Header<'s> {
414    type Error = BoundsError;
415
416    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
417        let mut rest = range.clone();
418
419        assert(source, &rest, 12)?;
420        rest.start += 12;
421
422        Ok((
423            Header {
424                source,
425                offset: range.start,
426            },
427            rest,
428        ))
429    }
430}
431impl<'s> BorrowedView<'s> for Header<'s> {
432    fn source(&self) -> &'s [u8] {
433        self.source
434    }
435    fn offset(&self) -> usize {
436        self.offset
437    }
438    fn len(&self) -> usize {
439        12
440    }
441}
442
443impl<'s> View<'s> for Question<'s> {
444    type Error = QuestionError;
445
446    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
447        let (_, mut rest) = Name::view(source, range.clone()).map_err(Self::Error::Name)?;
448
449        assert(source, &rest, 4).map_err(Self::Error::Bounds)?;
450        rest.start += 4;
451
452        Ok((
453            Question {
454                source,
455                offset: range.start,
456                len: rest.start - range.start,
457            },
458            rest,
459        ))
460    }
461}
462impl<'s> BorrowedView<'s> for Question<'s> {
463    fn source(&self) -> &'s [u8] {
464        self.source
465    }
466    fn offset(&self) -> usize {
467        self.offset
468    }
469    fn len(&self) -> usize {
470        self.len
471    }
472}
473
474impl<'s> View<'s> for Record<'s> {
475    type Error = RecordError;
476
477    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
478        let (_, mut rest) = Name::view(source, range.clone()).map_err(Self::Error::Name)?;
479        let name_len = rest.start - range.start;
480
481        assert(source, &rest, 8).map_err(Self::Error::Bounds)?;
482        rest.start += 8;
483
484        let (rdlength, mut rest) = u16::view(source, rest).map_err(Self::Error::Bounds)?;
485        let rdata_len = usize::from(rdlength);
486
487        assert(source, &rest, rdata_len).map_err(Self::Error::Bounds)?;
488        rest.start += rdata_len;
489
490        Ok((
491            Record {
492                source,
493                offset: range.start,
494                name_len,
495                rdata_len,
496            },
497            rest,
498        ))
499    }
500}
501impl<'s> BorrowedView<'s> for Record<'s> {
502    fn source(&self) -> &'s [u8] {
503        self.source
504    }
505    fn offset(&self) -> usize {
506        self.offset
507    }
508    fn len(&self) -> usize {
509        self.name_len + 10 + self.rdata_len
510    }
511}
512
513impl<'s> View<'s> for Name<'s> {
514    type Error = NameError;
515
516    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
517        let mut result = None;
518        let mut next = range.clone();
519        let mut seen = Seen::default();
520        let mut len = 0;
521
522        let rest = loop {
523            let (label, rest) = Label::view(source, next.clone()).map_err(Self::Error::Label)?;
524
525            if label.is_null() {
526                break result.unwrap_or(rest);
527            } else if let Some(offset) = label.pointer() {
528                if seen.see(offset) {
529                    return Err(Self::Error::PointerCycle);
530                }
531
532                next = offset.into()..source.len();
533                result.get_or_insert_with(|| rest.clone());
534            } else {
535                len += label.len();
536
537                if len > 255 {
538                    return Err(Self::Error::TooLong);
539                }
540
541                next = rest;
542            }
543        };
544
545        let offset = range.start;
546        let len = rest.start - offset;
547
548        Ok((
549            Name {
550                source,
551                offset,
552                len,
553            },
554            rest,
555        ))
556    }
557}
558impl<'s> BorrowedView<'s> for Name<'s> {
559    fn source(&self) -> &'s [u8] {
560        self.source
561    }
562    fn offset(&self) -> usize {
563        self.offset
564    }
565    fn len(&self) -> usize {
566        self.len
567    }
568}
569
570impl<'s> View<'s> for Label<'s> {
571    type Error = LabelError;
572
573    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
574        let (length, mut rest) = u8::view(source, range.clone()).map_err(Self::Error::Bounds)?;
575
576        let len = if length < 64 {
577            usize::from(length)
578        } else if length < 192 {
579            return Err(Self::Error::ReservedLength);
580        } else {
581            1
582        };
583
584        assert(source, &rest, len).map_err(Self::Error::Bounds)?;
585        rest.start += len;
586
587        Ok((
588            Label {
589                source,
590                offset: range.start,
591                len: rest.start - range.start,
592            },
593            rest,
594        ))
595    }
596}
597impl<'s> BorrowedView<'s> for Label<'s> {
598    fn source(&self) -> &'s [u8] {
599        self.source
600    }
601    fn offset(&self) -> usize {
602        self.offset
603    }
604    fn len(&self) -> usize {
605        self.len
606    }
607}
608
609impl<'s> BorrowedView<'s> for Extension<'s> {
610    fn source(&self) -> &'s [u8] {
611        self.inner.source()
612    }
613    fn offset(&self) -> usize {
614        self.inner.offset()
615    }
616    fn len(&self) -> usize {
617        self.inner.len()
618    }
619}
620
621impl<'s> View<'s> for CharacterString<'s> {
622    type Error = BoundsError;
623
624    fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
625        let (length, mut rest) = u8::view(source, range.clone())?;
626
627        assert(source, &rest, length.into())?;
628        rest.start += usize::from(length);
629
630        Ok((
631            CharacterString {
632                source,
633                offset: range.start,
634                len: rest.start - range.start,
635            },
636            rest,
637        ))
638    }
639}
640impl<'s> BorrowedView<'s> for CharacterString<'s> {
641    fn source(&self) -> &'s [u8] {
642        self.source
643    }
644    fn offset(&self) -> usize {
645        self.offset
646    }
647    fn len(&self) -> usize {
648        self.len
649    }
650}
651
652impl View<'_> for u32 {
653    type Error = BoundsError;
654
655    fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
656        assert(source, &range, 4)?;
657
658        let result = NetworkEndian::read_u32(&source[range.start..]);
659
660        range.start += 4;
661
662        Ok((result, range))
663    }
664}
665
666impl View<'_> for u16 {
667    type Error = BoundsError;
668
669    fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
670        assert(source, &range, 2)?;
671
672        let result = NetworkEndian::read_u16(&source[range.start..]);
673
674        range.start += 2;
675
676        Ok((result, range))
677    }
678}
679
680impl View<'_> for u8 {
681    type Error = BoundsError;
682
683    fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
684        assert(source, &range, 1)?;
685
686        let result = source[range.start];
687
688        range.start += 1;
689
690        Ok((result, range))
691    }
692}
693
694pub(crate) fn assert(
695    source: &[u8],
696    range: &Range<usize>,
697    len: usize,
698) -> core::result::Result<(), BoundsError> {
699    if range.end < range.start {
700        return Err(BoundsError::BackwardsRange(range.start, range.end));
701    }
702
703    if source.len() < range.end {
704        return Err(BoundsError::RangeOverflow(range.end, source.len()));
705    }
706
707    if range.end - range.start < len {
708        return Err(BoundsError::ReadOverflow(len, range.start, range.end));
709    }
710
711    Ok(())
712}
713
714#[cfg(test)]
715mod test {
716    use core::iter::once;
717
718    use arrayvec::ArrayVec;
719    use assert_matches::assert_matches;
720
721    use super::{Extension, Label, Message, Name, Question, Record, View};
722
723    type A12 = ArrayVec<u8, 4096>;
724
725    #[test]
726    fn message() {
727        use super::MessageError;
728        use super::MessageErrorKind as Kind;
729
730        let source = include_bytes!("../samples/daria.daz.cat.a.dns");
731        let len = source.len();
732
733        assert_matches!(
734            Message::view(source, 0..len),
735            Ok((
736                Message {
737                    source: _,
738                    opt: Some(Extension {
739                        inner: Record {
740                            source: _,
741                            offset: 141,
742                            name_len: 1,
743                            rdata_len: 0
744                        }
745                    }),
746                    offset: 0,
747                    qd_len: 19,
748                    an_len: 16,
749                    ns_len: 66,
750                    ar_len: 39
751                },
752                ref x
753            )) if *x == (len..len)
754        );
755
756        let header = b"\x13\x13\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00";
757        let question = b"\0\x00\x02\x00\x01";
758        let v0 = b"\0\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00";
759        let v13 = b"\0\x00\x29\x10\x00\x00\x0D\x00\x00\x00\x00";
760
761        let source: A12 = header
762            .iter()
763            .copied()
764            .chain(question.iter().copied())
765            .chain(v13.iter().copied())
766            .collect();
767
768        assert_matches!(
769            Message::view(&source, ..),
770            Err(MessageError(Some(13), Kind::MisplacedOptRecord))
771        );
772
773        let header = b"\x13\x13\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00";
774
775        let source: A12 = header
776            .iter()
777            .copied()
778            .chain(question.iter().copied())
779            .chain(v13.iter().copied())
780            .collect();
781
782        assert_matches!(
783            Message::view(&source, ..),
784            Err(MessageError(Some(13), Kind::MisplacedOptRecord))
785        );
786
787        let header = b"\x13\x13\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02";
788
789        let source: A12 = header
790            .iter()
791            .copied()
792            .chain(question.iter().copied())
793            .chain(v0.iter().copied())
794            .chain(v13.iter().copied())
795            .collect();
796
797        assert_matches!(
798            Message::view(&source, ..),
799            Err(MessageError(Some(0), Kind::MultipleOptRecords))
800        );
801    }
802
803    #[test]
804    fn question() {
805        assert_matches!(
806            Question::view(b"\0\xFF\xFE\xFF\xFE", 0..5),
807            Ok((Question { source: _, offset: 0, len: 5 }, ref x)) if *x == (5..5)
808        );
809    }
810
811    #[test]
812    fn record() {
813        assert_matches!(
814            Record::view(
815                b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x00\x00",
816                0..12,
817            ),
818            Ok((
819                Record {
820                    source: _,
821                    offset: 0,
822                    name_len: 1,
823                    rdata_len: 0
824                },
825                ref x
826            )) if *x == (11..12)
827        );
828
829        assert_matches!(
830            Record::view(
831                b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x01\x00",
832                0..12,
833            ),
834            Ok((
835                Record {
836                    source: _,
837                    offset: 0,
838                    name_len: 1,
839                    rdata_len: 1
840                },
841                ref x
842            )) if *x == (12..12)
843        );
844    }
845
846    #[test]
847    fn name() {
848        use super::{BoundsError, LabelError::Bounds, NameError::*};
849
850        assert_matches!(
851            Name::view(b"\x05daria\x03daz\x03cat\0", 0..15),
852            Ok((Name { source: _, offset: 0, len: 15 }, ref x)) if *x == (15..15)
853        );
854
855        assert_matches!(
856            Name::view(
857                b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x06",
858                15..26,
859            ),
860            Ok((
861                Name {
862                    source: _,
863                    offset: 15,
864                    len: 11
865                },
866                ref x
867            )) if *x == (26..26)
868        );
869
870        assert_matches!(
871            Name::view(
872                b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x06\xC0\x0F",
873                26..28,
874            ),
875            Ok((
876                Name {
877                    source: _,
878                    offset: 26,
879                    len: 2
880                },
881                ref x
882            )) if *x == (28..28)
883        );
884
885        assert_matches!(
886            Name::view(b"\xC0\x03", 0..2),
887            Err(Label(Bounds(BoundsError::BackwardsRange(3, 2))))
888        );
889        assert_matches!(
890            Name::view(b"\xC0\x02", 0..2),
891            Err(Label(Bounds(BoundsError::ReadOverflow(1, 2, 2))))
892        );
893        assert_matches!(
894            Name::view(b"\xC0\x01", 0..2),
895            Err(Label(Bounds(BoundsError::ReadOverflow(1, 2, 2))))
896        );
897
898        // https://lists.dns-oarc.net/pipermail/dns-operations/2009-September/004404.html
899        assert_matches!(
900            Name::view(b"\xC0\x02\0", 0..2),
901            Ok((Name { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
902        );
903
904        // CERT VU#23495 (CVE-2000-0333)
905        assert_matches!(Name::view(b"\xC0\x02\xC0\x00", 0..2), Err(PointerCycle));
906        assert_matches!(Name::view(b"\xC0\x00", 0..2), Err(PointerCycle));
907
908        // RFC 2181 § 11: 85 three-octet labels
909        let source = [2; 255].iter().copied().chain(once(0)).collect::<A12>();
910        assert_matches!(Name::view(&source, 0..256), Ok((Name { source: _, offset: 0, len: 256 }, ref x)) if *x == (256..256));
911
912        // RFC 2181 § 11: 64 four-octet labels
913        let source = [3; 256].iter().copied().chain(once(0)).collect::<A12>();
914        assert_matches!(Name::view(&source, 0..257), Err(TooLong));
915
916        // RFC 2181 § 11: 32 four-octet labels followed by a pointer to 32 four-octet labels
917        let source = [3; 128]
918            .iter()
919            .copied()
920            .chain(once(0))
921            .chain([3; 128].iter().copied())
922            .chain([0xC0, 0x00].iter().copied())
923            .collect::<A12>();
924        assert_matches!(Name::view(&source, 129..259), Err(TooLong));
925    }
926
927    #[test]
928    #[rustfmt::skip]
929    fn label() {
930        use super::{BoundsError, LabelError::*};
931
932        assert_matches!(
933            Label::view(b"\0", 0..1),
934            Ok((Label { source: _, offset: 0, len: 1 }, ref x)) if *x == (1..1)
935        );
936
937        assert_matches!(
938            Label::view(b"\x01\0", 0..2),
939            Ok((Label { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
940        );
941
942        assert_matches!(
943            Label::view(b"\0\0", 0..2),
944            Ok((Label { source: _, offset: 0, len: 1 }, ref x)) if *x == (1..2)
945        );
946
947        assert_matches!(
948            Label::view(&[63; 64], 0..64),
949            Ok((Label { source: _, offset: 0, len: 64 }, ref x)) if *x == (64..64)
950        );
951
952        assert_matches!(Label::view(&[64; 65], 0..65), Err(ReservedLength));
953        assert_matches!(Label::view(&[191; 192], 191..192), Err(ReservedLength));
954
955        assert_matches!(
956            Label::view(&[192, 0], 0..2),
957            Ok((Label { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
958        );
959
960        assert_matches!(Label::view(b"\x01\0", 0..1), Err(Bounds(BoundsError::ReadOverflow(1, 1, 1))));
961        assert_matches!(Label::view(b"\x01", 0..1), Err(Bounds(BoundsError::ReadOverflow(1, 1, 1))));
962        assert_matches!(Label::view(b"", 0..0), Err(Bounds(BoundsError::ReadOverflow(1, 0, 0))));
963    }
964
965    #[test]
966    #[rustfmt::skip]
967    fn assert() {
968        use super::{assert, BoundsError};
969
970        assert_matches!(assert(b"", &(0..0), 0), Ok(()));
971        assert_matches!(assert(b"", &(0..0), 1), Err(BoundsError::ReadOverflow(1, 0, 0)));
972
973        assert_matches!(assert(b"", &(0..1), 0), Err(BoundsError::RangeOverflow(1, 0)));
974        assert_matches!(assert(b"", &(0..1), 1), Err(BoundsError::RangeOverflow(1, 0)));
975
976        assert_matches!(assert(b"~", &(0..0), 0), Ok(()));
977        assert_matches!(assert(b"~", &(0..0), 1), Err(BoundsError::ReadOverflow(1, 0, 0)));
978
979        assert_matches!(assert(b"~", &(0..1), 0), Ok(()));
980        assert_matches!(assert(b"~", &(0..1), 1), Ok(()));
981        assert_matches!(assert(b"~", &(0..1), 2), Err(BoundsError::ReadOverflow(2, 0, 1)));
982
983        assert_matches!(assert(b"~", &(1..1), 0), Ok(()));
984        assert_matches!(assert(b"~", &(1..1), 1), Err(BoundsError::ReadOverflow(1, 1, 1)));
985
986        assert_matches!(assert(b"~", &(1..0), 0), Err(BoundsError::BackwardsRange(1, 0)));
987
988        assert_matches!(assert(b"<>", &(0..2), 2), Ok(()));
989        assert_matches!(assert(b"<>", &(0..1), 2), Err(BoundsError::ReadOverflow(2, 0, 1)));
990    }
991}
992
993#[cfg(all(test, feature = "bench"))]
994mod bench {
995    extern crate test;
996
997    use test::Bencher;
998
999    use super::{Message, Name, Question, Record, View};
1000
1001    #[bench]
1002    fn message(bencher: &mut Bencher) {
1003        let source = include_bytes!("../samples/daria.daz.cat.a.dns");
1004        let len = source.len();
1005
1006        bencher.iter(|| Message::view(source, 0..len));
1007    }
1008
1009    #[bench]
1010    fn question(bencher: &mut Bencher) {
1011        bencher.iter(|| Question::view(b"\0\xFF\xFE\xFF\xFE", 0..5));
1012    }
1013
1014    #[bench]
1015    fn record(bencher: &mut Bencher) {
1016        bencher.iter(|| Record::view(b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x00", 0..11));
1017    }
1018
1019    #[bench]
1020    fn name0(bencher: &mut Bencher) {
1021        bencher.iter(|| Name::view(b"\0", 0..1));
1022    }
1023
1024    #[bench]
1025    fn name1(bencher: &mut Bencher) {
1026        bencher.iter(|| Name::view(b"\x05daria\x03daz\x03cat\0", 0..15));
1027    }
1028
1029    #[bench]
1030    fn name2(bencher: &mut Bencher) {
1031        bencher.iter(|| Name::view(b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x00", 15..26));
1032    }
1033
1034    #[bench]
1035    fn name3(bencher: &mut Bencher) {
1036        let mut source = alloc::vec![];
1037
1038        source.extend(b"\x08charming\xFF\xFF");
1039        source.resize(16383, b'\0');
1040        source.extend(b"\x03daz\x03cat\0");
1041
1042        bencher.iter(|| Name::view(&source, 0..11));
1043    }
1044}