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