Skip to main content

structured_asn1/
reader.rs

1//! Reading elements in sequence, and descending into the constructed ones.
2//!
3//! Three invariants hold throughout. Nothing copies the document: elements
4//! borrow it and carry the range they occupy. Nothing recurses: depth is
5//! bounded by the caller's budget rather than by the stack. An element carries
6//! no path; the path belongs to the reader that produced it.
7
8use crate::error::{Error, ErrorCode, Limit, Path, Result};
9use crate::length::{self, Encoding, Length};
10use crate::limits::{Budget, Limits};
11use crate::memory::{Memory, Work};
12use crate::tag::{self, Tag, universal};
13use crate::value::{self, BitString, Integer, Oid};
14
15mod integer;
16pub use integer::IntegerReading;
17
18/// Holds the budget for one parse and hands out readers that share it.
19#[derive(Debug)]
20pub struct Parser {
21    budget: Budget,
22    encoding: Encoding,
23}
24
25impl Parser {
26    /// A parser for one document, in one encoding, with one budget.
27    #[must_use]
28    pub fn new(encoding: Encoding, limits: Limits, memory: Memory) -> Self {
29        Self {
30            budget: Budget::new(limits, memory),
31            encoding,
32        }
33    }
34
35    /// A parser for DER, with the default budget.
36    #[must_use]
37    pub fn der(memory: Memory) -> Self {
38        Self::new(Encoding::Der, Limits::default(), memory)
39    }
40
41    /// A parser that also accepts the BER forms CMS permits.
42    #[must_use]
43    pub fn ber(memory: Memory) -> Self {
44        Self::new(Encoding::Ber, Limits::default(), memory)
45    }
46
47    /// The limits this parser was given.
48    #[must_use]
49    pub fn limits(&self) -> Limits {
50        self.budget.limits()
51    }
52
53    /// The aggregate account shared with other parsers and retained results.
54    ///
55    /// `Limits.max_work` additionally bounds this parser's scanning, not later
56    /// owned-result processing. Memory's cumulative work bounds the whole domain.
57    #[must_use]
58    pub fn memory(&self) -> &Memory {
59        self.budget.memory()
60    }
61
62    /// A reader over `data`, whose first byte sits at `base` in the document.
63    ///
64    /// `base` is what makes an error's offset and an element's span mean
65    /// something to a caller holding a whole document while handing this parser
66    /// a window into it.
67    ///
68    /// Refused when the end of `data` would not fit an offset. Checking that
69    /// here is what lets every offset computed while reading be ordinary
70    /// arithmetic: each is at most `base + data.len()`.
71    pub fn read<'a>(&'a self, data: &'a [u8], base: u64) -> Result<Reader<'a>> {
72        self.read_as(data, base, self.encoding)
73    }
74
75    /// A reader over `data` under a chosen encoding, sharing this parser's
76    /// budget.
77    ///
78    /// For a window whose schema fixes its encoding regardless of what this
79    /// parser was built for: the value of a certificate extension is DER even
80    /// when the parser was made lenient for the envelope the certificate
81    /// arrived in.
82    pub fn read_as<'a>(
83        &'a self,
84        data: &'a [u8],
85        base: u64,
86        encoding: Encoding,
87    ) -> Result<Reader<'a>> {
88        self.read_as_in(data, base, encoding, self.memory())
89    }
90
91    fn read_as_in<'a>(
92        &'a self,
93        data: &'a [u8],
94        base: u64,
95        encoding: Encoding,
96        execution: &Memory,
97    ) -> Result<Reader<'a>> {
98        u64::try_from(data.len())
99            .ok()
100            .and_then(|length| base.checked_add(length))
101            .ok_or_else(|| Error::new(ErrorCode::OffsetTooLarge, base, Path::default()))?;
102
103        Ok(Reader {
104            data,
105            pos: 0,
106            base,
107            depth: 0,
108            next_index: 0,
109            path: Path::default(),
110            encoding,
111            parser: self,
112            execution: execution.clone(),
113        })
114    }
115
116    /// A reader over bytes another element carries as its value, one level
117    /// below the reader that element was found in.
118    ///
119    /// For an encoding wrapped in a primitive, an octet string above all: a
120    /// certificate extension's value, a signed message's content. `outer` is
121    /// [`Reader::depth`] of the reader the carrying element came from. A
122    /// reader made with [`Parser::read_as`] would count the wrapped structure
123    /// from the top again, and a caller's depth ceiling would bound each
124    /// wrapping rather than the document.
125    ///
126    /// # Errors
127    ///
128    /// [`ErrorCode::LimitExceeded`] where the level is past the depth
129    /// ceiling, and what [`Parser::read_as`] refuses.
130    pub fn read_nested<'a>(
131        &'a self,
132        data: &'a [u8],
133        base: u64,
134        encoding: Encoding,
135        outer: u32,
136    ) -> Result<Reader<'a>> {
137        self.read_nested_in(data, base, encoding, outer, self.memory())
138    }
139
140    /// Nested lazy reader using the current execution domain from creation.
141    ///
142    /// Original offsets, depth and this parser session's cumulative ceilings
143    /// remain in force. New storage and deferred work use `execution`.
144    pub fn read_nested_in<'a>(
145        &'a self,
146        data: &'a [u8],
147        base: u64,
148        encoding: Encoding,
149        outer: u32,
150        execution: &Memory,
151    ) -> Result<Reader<'a>> {
152        let mut reader = self.read_as_in(data, base, encoding, execution)?;
153        let depth = outer.checked_add(1).ok_or_else(|| {
154            Error::new(
155                ErrorCode::LimitExceeded(Limit::Depth),
156                base,
157                Path::default(),
158            )
159        })?;
160        self.budget
161            .depth(depth)
162            .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
163        reader.depth = depth;
164        Ok(reader)
165    }
166}
167
168/// Where in a document one run of bytes sits.
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
170pub struct Span {
171    /// Offset of the first byte, counted in the whole document.
172    pub start: u64,
173    /// How many bytes.
174    pub length: u64,
175}
176
177impl Span {
178    /// The offset just past the last byte.
179    ///
180    /// Ordinary arithmetic: a span is only ever built by a reader, which
181    /// refuses a window whose end does not fit an offset, so `start + length`
182    /// has already been shown to fit.
183    #[must_use]
184    pub fn end(self) -> u64 {
185        self.start + self.length
186    }
187}
188
189/// One element, as it was found.
190#[derive(Debug, Clone, Copy)]
191pub struct Element<'a> {
192    tag: Tag,
193    contents: &'a [u8],
194    bytes: &'a [u8],
195    contents_span: Span,
196    whole: Span,
197    indefinite: bool,
198    index: u32,
199}
200
201impl<'a> Element<'a> {
202    /// What kind of element this is.
203    #[must_use]
204    pub fn tag(self) -> Tag {
205        self.tag
206    }
207
208    /// The contents, borrowed from the document.
209    ///
210    /// For an indefinite-length element this is everything up to but not
211    /// including the end-of-contents marker.
212    #[must_use]
213    pub fn contents(self) -> &'a [u8] {
214        self.contents
215    }
216
217    /// The whole element as it arrived, header included.
218    ///
219    /// What a signature is computed over wherever a schema says the signature
220    /// covers an element as encoded, and what identity is compared on wherever
221    /// a schema says two structures are the same one when their bytes are.
222    /// Handing these back rather than re-encoding what was understood is the
223    /// difference between checking a signature over the document somebody was
224    /// sent and checking it over this parser's opinion of that document.
225    #[must_use]
226    pub fn as_bytes(self) -> &'a [u8] {
227        self.bytes
228    }
229
230    /// Where the contents sit in the document.
231    #[must_use]
232    pub fn contents_span(self) -> Span {
233        self.contents_span
234    }
235
236    /// Where the whole element sits, header included.
237    ///
238    /// This is the range a signature is computed over wherever a schema says
239    /// the signature covers an element as encoded.
240    #[must_use]
241    pub fn span(self) -> Span {
242        self.whole
243    }
244
245    /// Whether the length was written in the indefinite form.
246    #[must_use]
247    pub fn is_indefinite(self) -> bool {
248        self.indefinite
249    }
250
251    /// Its position among the elements of the container it was read from.
252    #[must_use]
253    pub fn index(self) -> u32 {
254        self.index
255    }
256}
257
258/// Reads the elements of one container, in order.
259///
260/// Cloning one keeps where it is and how deep it sits, so a caller that has to
261/// come back to a container later can put the reader aside rather than start
262/// again from the document and count the nesting as one.
263#[derive(Debug)]
264pub struct Reader<'a> {
265    data: &'a [u8],
266    pos: usize,
267    base: u64,
268    depth: u32,
269    next_index: u32,
270    path: Path,
271    encoding: Encoding,
272    parser: &'a Parser,
273    execution: Memory,
274}
275
276impl<'a> Reader<'a> {
277    /// Current domain for deferred work, copies and new storage.
278    #[must_use]
279    pub fn memory(&self) -> &Memory {
280        &self.execution
281    }
282
283    /// Borrows both the current account and original cumulative work ceiling.
284    ///
285    /// Schema scratch must use this boundary when work belongs to the parse:
286    /// allocator growth, copying and sorting then retain the session ceiling
287    /// as well as the aggregate account. Independently retained results use
288    /// [`Self::memory`] instead.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// use std::sync::Arc;
294    /// use structured_asn1::{Parser, memory::{Memory, MemoryAccount, Work}};
295    /// let parser = Parser::ber(Memory::new(Arc::new(MemoryAccount::new(1024, 1024))));
296    /// let reader = parser.read(&[], 900).unwrap();
297    /// let mut scratch = reader.execution().vector();
298    /// scratch.try_push(7_u8)?;
299    /// assert_eq!(&*scratch, &[7]);
300    /// # Ok::<(), structured_asn1::memory::MemoryError>(())
301    /// ```
302    #[must_use]
303    pub fn execution(&self) -> crate::memory::Execution<'_> {
304        crate::memory::Execution::new(self.memory(), self.budget())
305    }
306
307    /// Selects the domain for subsequent execution without moving existing
308    /// storage charges. Offsets, depth and parser-session cumulative limits
309    /// remain unchanged; a new domain does not reset that session ceiling.
310    #[must_use]
311    pub fn with_execution(mut self, execution: &Memory) -> Self {
312        self.execution = execution.clone();
313        self
314    }
315
316    /// Copies the reader position and diagnostic path fallibly in the same domain.
317    pub fn try_clone(&self) -> Result<Self> {
318        self.admit_path(0)
319            .map_err(|reason| Error::resource(reason, self.offset()))?;
320        Ok(Self {
321            data: self.data,
322            pos: self.pos,
323            base: self.base,
324            depth: self.depth,
325            next_index: self.next_index,
326            path: self
327                .path
328                .try_copy_in(self.memory())
329                .map_err(|reason| Error::resource(reason, self.offset()))?,
330            encoding: self.encoding,
331            parser: self.parser,
332            execution: self.execution.clone(),
333        })
334    }
335    /// Whether every element here has been read.
336    #[must_use]
337    pub fn is_empty(&self) -> bool {
338        self.pos >= self.data.len()
339    }
340
341    /// Original parser, whose session ceilings remain cumulative across
342    /// deferred reads. Use [`Self::memory`] for the current execution domain;
343    /// the parser's storage domain may belong to an earlier operation.
344    #[must_use]
345    pub fn parser(&self) -> &'a Parser {
346        self.parser
347    }
348
349    /// The shared budget, by way of the parser.
350    fn budget(&self) -> &'a Budget {
351        &self.parser.budget
352    }
353
354    /// Charges caller-side scanning to the shared work budget.
355    ///
356    /// For a schema layer that walks an element's contents itself, text
357    /// validation and named-bit walks among them: the walk costs what the
358    /// bytes cost, and a caller bounding work must see that cost on the
359    /// same meter the reads use.
360    pub fn charge(&self, amount: u64) -> Result<()> {
361        self.budget()
362            .work_in(amount, self.memory())
363            .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), self.offset()))
364    }
365
366    /// How many containers deep this reader sits, counted as the depth
367    /// ceiling counts it. What [`Parser::read_nested`] is given for a value
368    /// found here.
369    #[must_use]
370    pub fn depth(&self) -> u32 {
371        self.depth
372    }
373
374    /// The offset of the next unread byte, in the document.
375    ///
376    /// Ordinary arithmetic, because `pos` never exceeds the length of `data`
377    /// and `base` plus that length was shown to fit when this reader was made.
378    #[must_use]
379    pub fn offset(&self) -> u64 {
380        self.base + self.pos as u64
381    }
382
383    /// The bytes not yet read.
384    #[must_use]
385    pub fn remaining(&self) -> &'a [u8] {
386        &self.data[self.pos.min(self.data.len())..]
387    }
388
389    /// The path to this container, for a caller building its own diagnostics.
390    #[must_use]
391    pub fn path(&self) -> &Path {
392        &self.path
393    }
394
395    /// Which encoding this reader accepts, for a schema whose own rules
396    /// differ between the two, such as the ordering DER requires of a set.
397    #[must_use]
398    pub fn encoding(&self) -> Encoding {
399        self.encoding
400    }
401
402    /// A reader over an element's own bytes, header included, under a chosen
403    /// encoding.
404    ///
405    /// For a structure whose schema fixes its encoding regardless of the
406    /// container's: a certificate is DER even when the envelope carrying it
407    /// is BER, and reading it with the container's leniency would let
408    /// spellings survive that the certificate's own rules refuse. The
409    /// element's header is read again under the chosen rules, so a header
410    /// only the lenient encoding accepts is refused too. Offsets stay offsets
411    /// in the document and the budget stays the shared one.
412    pub fn reread(&self, element: &Element<'a>, encoding: Encoding) -> Result<Reader<'a>> {
413        self.admit_path(0)
414            .map_err(|reason| Error::resource(reason, element.whole.start))?;
415        Ok(Reader {
416            data: element.bytes,
417            pos: 0,
418            base: element.whole.start,
419            depth: self.depth,
420            next_index: 0,
421            path: self
422                .path
423                .try_copy_in(self.memory())
424                .map_err(|reason| Error::resource(reason, element.whole.start))?,
425            encoding,
426            parser: self.parser,
427            execution: self.execution.clone(),
428        })
429    }
430
431    /// Reads the next element, or `None` at the end of this container.
432    pub fn next_element(&mut self) -> Result<Option<Element<'a>>> {
433        if self.is_empty() {
434            return Ok(None);
435        }
436
437        let header = self.read_header()?;
438
439        // An end-of-contents marker belongs to whichever reader opened the
440        // indefinite element, and that reader stops before handing it out.
441        // Meeting one here means it closes something never opened.
442        if header.tag.is_end_of_contents() {
443            return Err(self.fail_at(ErrorCode::MalformedEndOfContents, header.start));
444        }
445
446        self.finish(header).map(Some)
447    }
448
449    /// Reads the next element and requires it to carry `tag`.
450    pub fn expect(&mut self, tag: Tag) -> Result<Element<'a>> {
451        let offset = self.offset();
452        match self.next_element()? {
453            Some(element) if element.tag == tag => Ok(element),
454            // Named under the element that carried the wrong tag: it was read,
455            // so it has an index, and the fault is that element rather than
456            // the container holding it. Nothing was read in the other arm, so
457            // there is no element to name and the container is the answer.
458            Some(element) => Err(self.fail_under(ErrorCode::UnexpectedTag, &element)),
459            None => Err(self.fail_at(ErrorCode::UnexpectedEnd, offset)),
460        }
461    }
462
463    /// Reads and discards the next element, whatever it is.
464    ///
465    /// This is how a schema layer steps over an extension it does not know: the
466    /// element is skipped within its declared length, so an unknown tag costs
467    /// what a known one costs and cannot make the reader wander.
468    pub fn skip(&mut self) -> Result<bool> {
469        Ok(self.next_element()?.is_some())
470    }
471
472    /// A reader over the contents of a constructed element read from here.
473    ///
474    /// Refused for a primitive element: its contents are a value rather than
475    /// further elements, and reading them as elements is how a parser is
476    /// talked into finding structure inside an octet string that nobody put
477    /// there.
478    pub fn enter(&self, element: &Element<'a>) -> Result<Reader<'a>> {
479        if !element.tag.is_constructed() {
480            return Err(self.fail_under(ErrorCode::WrongConstruction, element));
481        }
482
483        // Check depth before copying/growing a path: a rejected descent must
484        // not perform the allocation it was supposed to prevent.
485        let depth = self.depth.checked_add(1).ok_or_else(|| {
486            self.fail_under_at(
487                ErrorCode::LimitExceeded(Limit::Depth),
488                element,
489                element.contents_span.start,
490            )
491        })?;
492        self.budget().depth(depth).map_err(|limit| {
493            self.fail_under_at(
494                ErrorCode::LimitExceeded(limit),
495                element,
496                element.contents_span.start,
497            )
498        })?;
499        self.admit_path(1)
500            .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
501        let mut path = self
502            .path
503            .try_copy_in(self.memory())
504            .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
505        path.push(self.memory(), element.index)
506            .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
507
508        Ok(Reader {
509            data: element.contents,
510            pos: 0,
511            base: element.contents_span.start,
512            depth,
513            next_index: 0,
514            path,
515            encoding: self.encoding,
516            parser: self.parser,
517            execution: self.execution.clone(),
518        })
519    }
520
521    /// Reads an element's contents as an object identifier.
522    pub fn oid(&self, element: &Element<'a>) -> Result<Oid<'a>> {
523        self.primitive(element)?;
524        // The arcs are scanned byte by byte, so the scan is charged to the
525        // shared work budget like the headers are: one long identifier must
526        // not cost time the caller's limits never metered.
527        self.budget()
528            .work_in(element.contents.len() as u64, self.memory())
529            .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
530        value::oid(element.contents).map_err(|code| self.fail_under(code, element))
531    }
532
533    /// Reads an element's contents as an integer.
534    pub fn integer(&self, element: &Element<'a>) -> Result<Integer<'a>> {
535        self.primitive(element)?;
536        value::integer(element.contents).map_err(|code| self.fail_under(code, element))
537    }
538
539    /// Reads an element's contents as a bit string.
540    ///
541    /// The segmented form BER allows for a constructed bit string is refused:
542    /// every bit string this product reads is covered by a signature computed
543    /// over the bytes, where one value with two spellings is one value too
544    /// many.
545    pub fn bit_string(&self, element: &Element<'a>) -> Result<BitString<'a>> {
546        self.primitive(element)?;
547        value::bit_string(element.contents, self.encoding)
548            .map_err(|code| self.fail_under(code, element))
549    }
550
551    /// Reads an element's contents as a boolean.
552    pub fn boolean(&self, element: &Element<'a>) -> Result<bool> {
553        self.primitive(element)?;
554        value::boolean(element.contents, self.encoding)
555            .map_err(|code| self.fail_under(code, element))
556    }
557
558    /// Reads an element's contents as a null, which has none.
559    pub fn null(&self, element: &Element<'a>) -> Result<()> {
560        self.primitive(element)?;
561        value::null(element.contents).map_err(|code| self.fail_under(code, element))
562    }
563
564    /// Reads an element's contents as a real, and answers only whether they
565    /// are a value of the type.
566    ///
567    /// The number itself is not read: no schema this product parses has a
568    /// real in it, and one arrives only inside a value preserved for
569    /// somebody else, who is promised octets that are what they claim.
570    pub fn real(&self, element: &Element<'a>) -> Result<()> {
571        self.primitive(element)?;
572        // The decimal form's field is walked digit by digit, so the scan is
573        // charged to the shared work budget like the headers are: one long
574        // value must not cost time the caller's limits never metered.
575        self.budget()
576            .work_in(element.contents.len() as u64, self.memory())
577            .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
578        value::real(element.contents, self.encoding).map_err(|code| self.fail_under(code, element))
579    }
580
581    /// Reads the next element as an object identifier.
582    pub fn read_oid(&mut self) -> Result<Oid<'a>> {
583        let element = self.expect(Tag::primitive(universal::OID))?;
584        self.oid(&element)
585    }
586
587    /// Reads the next element as an integer.
588    pub fn read_integer(&mut self) -> Result<Integer<'a>> {
589        let element = self.expect(Tag::primitive(universal::INTEGER))?;
590        self.integer(&element)
591    }
592
593    /// Reads the next element as a bit string.
594    pub fn read_bit_string(&mut self) -> Result<BitString<'a>> {
595        let element = self.expect(Tag::primitive(universal::BIT_STRING))?;
596        self.bit_string(&element)
597    }
598
599    /// Reads the next element as a boolean.
600    pub fn read_boolean(&mut self) -> Result<bool> {
601        let element = self.expect(Tag::primitive(universal::BOOLEAN))?;
602        self.boolean(&element)
603    }
604
605    fn primitive(&self, element: &Element<'a>) -> Result<()> {
606        if element.tag.is_constructed() {
607            return Err(self.fail_under(ErrorCode::WrongConstruction, element));
608        }
609        Ok(())
610    }
611
612    /// An error naming an element read from this container.
613    #[must_use]
614    pub fn fail_under(&self, code: ErrorCode, element: &Element<'a>) -> Error {
615        self.fail_under_at(code, element, element.whole.start)
616    }
617
618    fn fail_under_at(&self, code: ErrorCode, element: &Element<'a>, offset: u64) -> Error {
619        match self.path_into(element.index, &[]) {
620            Ok(path) => Error::new(code, offset, path),
621            Err(reason) => Error::resource(reason, offset),
622        }
623    }
624
625    fn fail_at(&self, code: ErrorCode, offset: u64) -> Error {
626        if let Err(reason) = self.admit_path(0) {
627            return Error::resource(reason, offset);
628        }
629        match self.path.try_copy_in(self.memory()) {
630            Ok(path) => Error::new(code, offset, path),
631            Err(reason) => Error::resource(reason, offset),
632        }
633    }
634
635    fn read_header(&mut self) -> Result<Header> {
636        let start = self.offset();
637        self.budget()
638            .element()
639            .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), start))?;
640
641        let rest = &self.data[self.pos..];
642        header_at(rest, self.encoding, start, self.budget(), self.memory())
643            .map_err(|(code, at)| self.fail_at(code, at))
644    }
645
646    fn finish(&mut self, header: Header) -> Result<Element<'a>> {
647        let contents_at = self.pos + header.len;
648        let contents_start = header.start + header.len as u64;
649
650        let (contents_len, total_len, indefinite) = match header.length {
651            Length::Definite(length) => {
652                self.budget()
653                    .length(length)
654                    .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
655
656                let length = usize::try_from(length)
657                    .map_err(|_| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
658
659                let end = contents_at
660                    .checked_add(length)
661                    .ok_or_else(|| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
662
663                if end > self.data.len() {
664                    return Err(self.fail_at(ErrorCode::UnexpectedEnd, header.start));
665                }
666
667                (length, header.len + length, false)
668            }
669            Length::Indefinite => {
670                if !header.tag.is_constructed() {
671                    return Err(self.fail_at(ErrorCode::WrongConstruction, header.start));
672                }
673                let contents_len =
674                    self.scan_to_end_of_contents(contents_at, contents_start, self.next_index)?;
675
676                // An indefinite element declares no length, so nothing has held
677                // it to one yet. Its size is what the scan just measured, and a
678                // container assembled from many small children would otherwise
679                // pass a budget its declared-length siblings could not.
680                self.budget()
681                    .length(contents_len as u64)
682                    .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
683
684                // Two further bytes for the end-of-contents marker, which is
685                // exactly two: the scan refuses any other spelling of it.
686                (contents_len, header.len + contents_len + 2, true)
687            }
688        };
689
690        let contents = &self.data[contents_at..contents_at + contents_len];
691        // The element as it arrived, header and any end-of-contents marker
692        // included. Both bounds were established above, so the slice exists.
693        let bytes = &self.data[self.pos..self.pos + total_len];
694        let index = self.next_index;
695
696        self.pos += total_len;
697        self.next_index = self
698            .next_index
699            .checked_add(1)
700            .ok_or_else(|| self.fail_at(ErrorCode::LimitExceeded(Limit::Elements), header.start))?;
701
702        Ok(Element {
703            tag: header.tag,
704            contents,
705            bytes,
706            contents_span: Span {
707                start: contents_start,
708                length: contents_len as u64,
709            },
710            whole: Span {
711                start: header.start,
712                length: total_len as u64,
713            },
714            indefinite,
715            index,
716        })
717    }
718
719    /// Finds where an indefinite-length element's contents end.
720    ///
721    /// Walks the elements inside it with an explicit stack rather than by
722    /// recursing, so a document nested a million deep is refused by the depth
723    /// budget instead of ending the process.
724    ///
725    /// A measurement, not a reading: the elements it steps over are charged to
726    /// the element budget later, where they are actually read. This costs
727    /// work.
728    fn scan_to_end_of_contents(
729        &self,
730        from: usize,
731        from_offset: u64,
732        own_index: u32,
733    ) -> Result<usize> {
734        let mut cursor = from;
735        let mut offset = from_offset;
736
737        // The index of the next element at each level entered so far, so an
738        // error inside nested contents names where it is rather than naming the
739        // container the scan started from.
740        let mut trail = self.execution().vector::<u32>();
741        let mut index: u32 = 0;
742
743        // Assembled only where an error is returned: building it per header is
744        // work proportional to depth times children, which the work budget
745        // does not count.
746        let fail = |code: ErrorCode, at: u64, trail: &[u32]| match self.path_into(own_index, trail)
747        {
748            Ok(path) => Error::new(code, at, path),
749            Err(reason) => Error::resource(reason, at),
750        };
751        let spent =
752            |limit: Limit, at: u64, trail: &[u32]| fail(ErrorCode::LimitExceeded(limit), at, trail);
753
754        loop {
755            let depth = u32::try_from(trail.len())
756                .ok()
757                .and_then(|nested| self.depth.checked_add(nested))
758                .and_then(|depth| depth.checked_add(1))
759                .ok_or_else(|| spent(Limit::Depth, offset, &trail))?;
760            self.budget()
761                .depth(depth)
762                .map_err(|limit| spent(limit, offset, &trail))?;
763
764            let rest = self
765                .data
766                .get(cursor..)
767                .filter(|rest| !rest.is_empty())
768                .ok_or_else(|| fail(ErrorCode::UnterminatedContents, from_offset, &trail))?;
769
770            let header = header_at(rest, self.encoding, offset, self.budget(), self.memory())
771                .map_err(|(code, at)| fail(code, at, &trail))?;
772            let inner_tag = header.tag;
773            let inner_length = header.length;
774            let header_len = header.len;
775
776            if inner_tag.is_end_of_contents() {
777                // Exactly two octets. A zero length written the long way reads
778                // as a zero length, and taking it for the marker would end the
779                // element short and leave the rest of the marker to be read as
780                // another element.
781                if header_len != 2 || !matches!(inner_length, Length::Definite(0)) {
782                    return Err(fail(ErrorCode::MalformedEndOfContents, offset, &trail));
783                }
784                match trail.pop() {
785                    // This one closes the element the scan was opened for.
786                    None => return Ok(cursor - from),
787                    // Back at the level that container sat on, with it read.
788                    Some(outer) => {
789                        index = outer
790                            .checked_add(1)
791                            .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
792                    }
793                }
794                cursor += header_len;
795                offset += header_len as u64;
796                continue;
797            }
798
799            let step = match inner_length {
800                Length::Indefinite => {
801                    if !inner_tag.is_constructed() {
802                        return Err(fail(ErrorCode::WrongConstruction, offset, &trail));
803                    }
804                    // The index this container itself sits at, so a fault
805                    // inside it is reported under it rather than beside it.
806                    trail
807                        .try_push(index)
808                        .map_err(|reason| Error::resource(reason, offset))?;
809                    index = 0;
810                    header_len
811                }
812                Length::Definite(length) => {
813                    self.budget()
814                        .length(length)
815                        .map_err(|limit| spent(limit, offset, &trail))?;
816                    let length = usize::try_from(length)
817                        .map_err(|_| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
818                    index = index
819                        .checked_add(1)
820                        .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
821                    header_len
822                        .checked_add(length)
823                        .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?
824                }
825            };
826
827            cursor = cursor
828                .checked_add(step)
829                .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
830            if cursor > self.data.len() {
831                return Err(fail(ErrorCode::UnexpectedEnd, offset, &trail));
832            }
833            offset += step as u64;
834        }
835    }
836
837    /// The path to a point inside an element of this container: this
838    /// container's path, the element's own index, then the index of each
839    /// nested container entered on the way.
840    fn path_into(
841        &self,
842        own_index: u32,
843        trail: &[u32],
844    ) -> core::result::Result<Path, crate::memory::MemoryError> {
845        let additional = trail
846            .len()
847            .checked_add(1)
848            .ok_or(crate::memory::MemoryError::WorkExceeded)?;
849        self.admit_path(additional)?;
850        let mut path = self.path.try_copy_in(self.memory())?;
851        path.push(self.memory(), own_index)?;
852        for index in trail {
853            path.push(self.memory(), *index)?;
854        }
855        Ok(path)
856    }
857
858    fn admit_path(
859        &self,
860        additional: usize,
861    ) -> core::result::Result<(), crate::memory::MemoryError> {
862        let work = self.path.copy_work(additional)?;
863        self.budget()
864            .local_work(work)
865            .map_err(|_| crate::memory::MemoryError::WorkExceeded)
866    }
867}
868
869#[derive(Clone, Copy)]
870struct Header {
871    tag: Tag,
872    length: Length,
873    start: u64,
874    len: usize,
875}
876
877/// Both ordinary parsing and indefinite scans use the same pre-admission path.
878fn header_at(
879    input: &[u8],
880    encoding: Encoding,
881    start: u64,
882    budget: &Budget,
883    execution: &Memory,
884) -> core::result::Result<Header, (ErrorCode, u64)> {
885    // Common short headers use one aggregate atomic admission for both bytes.
886    // Extra high-tag octets and long lengths spend only before they are examined.
887    budget
888        .work_in(2, execution)
889        .map_err(|limit| (ErrorCode::LimitExceeded(limit), start))?;
890    let mut credit = 2;
891    let mut charge = |amount: u64| {
892        if amount <= credit {
893            credit -= amount;
894            return Ok(());
895        }
896        let additional = amount - credit;
897        credit = 0;
898        budget
899            .work_in(additional, execution)
900            .map_err(ErrorCode::LimitExceeded)
901    };
902    let (tag, tag_len) = tag::read_accounted(input, start, &mut charge)?;
903    let (length, length_len) = length::read_accounted(
904        &input[tag_len..],
905        encoding,
906        start + tag_len as u64,
907        &mut charge,
908    )?;
909    Ok(Header {
910        tag,
911        length,
912        start,
913        len: tag_len + length_len,
914    })
915}
916
917#[cfg(test)]
918mod tests;