Coverage Report

Created: 2026-07-25 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.7.1/src/untrusted.rs
Line
Count
Source
1
// Copyright 2015-2016 Brian Smith.
2
//
3
// Permission to use, copy, modify, and/or distribute this software for any
4
// purpose with or without fee is hereby granted, provided that the above
5
// copyright notice and this permission notice appear in all copies.
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15
//! untrusted.rs: Safe, fast, zero-panic, zero-crashing, zero-allocation
16
//! parsing of untrusted inputs in Rust.
17
//!
18
//! <code>git clone https://github.com/briansmith/untrusted</code>
19
//!
20
//! untrusted.rs goes beyond Rust's normal safety guarantees by  also
21
//! guaranteeing that parsing will be panic-free, as long as
22
//! `untrusted::Input::as_slice_less_safe()` is not used. It avoids copying
23
//! data and heap allocation and strives to prevent common pitfalls such as
24
//! accidentally parsing input bytes multiple times. In order to meet these
25
//! goals, untrusted.rs is limited in functionality such that it works best for
26
//! input languages with a small fixed amount of lookahead such as ASN.1, TLS,
27
//! TCP/IP, and many other networking, IPC, and related protocols. Languages
28
//! that require more lookahead and/or backtracking require some significant
29
//! contortions to parse using this framework. It would not be realistic to use
30
//! it for parsing programming language code, for example.
31
//!
32
//! The overall pattern for using untrusted.rs is:
33
//!
34
//! 1. Write a recursive-descent-style parser for the input language, where the
35
//!    input data is given as a `&mut untrusted::Reader` parameter to each
36
//!    function. Each function should have a return type of `Result<V, E>` for
37
//!    some value type `V` and some error type `E`, either or both of which may
38
//!    be `()`. Functions for parsing the lowest-level language constructs
39
//!    should be defined. Those lowest-level functions will parse their inputs
40
//!    using `::read_byte()`, `Reader::peek()`, and similar functions.
41
//!    Higher-level language constructs are then parsed by calling the
42
//!    lower-level functions in sequence.
43
//!
44
//! 2. Wrap the top-most functions of your recursive-descent parser in
45
//!    functions that take their input data as an `untrusted::Input`. The
46
//!    wrapper functions should call the `Input`'s `read_all` (or a variant
47
//!    thereof) method. The wrapper functions are the only ones that should be
48
//!    exposed outside the parser's module.
49
//!
50
//! 3. After receiving the input data to parse, wrap it in an `untrusted::Input`
51
//!    using `untrusted::Input::from()` as early as possible. Pass the
52
//!    `untrusted::Input` to the wrapper functions when they need to be parsed.
53
//!
54
//! In general parsers built using `untrusted::Reader` do not need to explicitly
55
//! check for end-of-input unless they are parsing optional constructs, because
56
//! `Reader::read_byte()` will return `Err(EndOfInput)` on end-of-input.
57
//! Similarly, parsers using `untrusted::Reader` generally don't need to check
58
//! for extra junk at the end of the input as long as the parser's API uses the
59
//! pattern described above, as `read_all` and its variants automatically check
60
//! for trailing junk. `Reader::skip_to_end()` must be used when any remaining
61
//! unread input should be ignored without triggering an error.
62
//!
63
//! untrusted.rs works best when all processing of the input data is done
64
//! through the `untrusted::Input` and `untrusted::Reader` types. In
65
//! particular, avoid trying to parse input data using functions that take
66
//! byte slices. However, when you need to access a part of the input data as
67
//! a slice to use a function that isn't written using untrusted.rs,
68
//! `Input::as_slice_less_safe()` can be used.
69
//!
70
//! It is recommend to use `use untrusted;` and then `untrusted::Input`,
71
//! `untrusted::Reader`, etc., instead of using `use untrusted::*`. Qualifying
72
//! the names with `untrusted` helps remind the reader of the code that it is
73
//! dealing with *untrusted* input.
74
//!
75
//! # Examples
76
//!
77
//! [*ring*](https://github.com/briansmith/ring)'s parser for the subset of
78
//! ASN.1 DER it needs to understand,
79
//! [`ring::der`](https://github.com/briansmith/ring/blob/master/src/der.rs),
80
//! is built on top of untrusted.rs. *ring* also uses untrusted.rs to parse ECC
81
//! public keys, RSA PKCS#1 1.5 padding, and for all other parsing it does.
82
//!
83
//! All of [webpki](https://github.com/briansmith/webpki)'s parsing of X.509
84
//! certificates (also ASN.1 DER) is done using untrusted.rs.
85
86
#![doc(html_root_url = "https://briansmith.org/rustdoc/")]
87
// `#[derive(...)]` uses `#[allow(unused_qualifications)]` internally.
88
#![deny(unused_qualifications)]
89
#![forbid(
90
    anonymous_parameters,
91
    box_pointers,
92
    missing_docs,
93
    trivial_casts,
94
    trivial_numeric_casts,
95
    unsafe_code,
96
    unstable_features,
97
    unused_extern_crates,
98
    unused_import_braces,
99
    unused_results,
100
    variant_size_differences,
101
    warnings
102
)]
103
#![no_std]
104
105
/// A wrapper around `&'a [u8]` that helps in writing panic-free code.
106
///
107
/// No methods of `Input` will ever panic.
108
#[derive(Clone, Copy, Debug, Eq)]
109
pub struct Input<'a> {
110
    value: no_panic::Slice<'a>,
111
}
112
113
impl<'a> Input<'a> {
114
    /// Construct a new `Input` for the given input `bytes`.
115
0
    pub const fn from(bytes: &'a [u8]) -> Self {
116
        // This limit is important for avoiding integer overflow. In particular,
117
        // `Reader` assumes that an `i + 1 > i` if `input.value.get(i)` does
118
        // not return `None`. According to the Rust language reference, the
119
        // maximum object size is `core::isize::MAX`, and in practice it is
120
        // impossible to create an object of size `core::usize::MAX` or larger.
121
0
        Self {
122
0
            value: no_panic::Slice::new(bytes),
123
0
        }
124
0
    }
125
126
    /// Returns `true` if the input is empty and false otherwise.
127
    #[inline]
128
0
    pub fn is_empty(&self) -> bool { self.value.is_empty() }
129
130
    /// Returns the length of the `Input`.
131
    #[inline]
132
0
    pub fn len(&self) -> usize { self.value.len() }
133
134
    /// Calls `read` with the given input as a `Reader`, ensuring that `read`
135
    /// consumed the entire input. If `read` does not consume the entire input,
136
    /// `incomplete_read` is returned.
137
0
    pub fn read_all<F, R, E>(&self, incomplete_read: E, read: F) -> Result<R, E>
138
0
    where
139
0
        F: FnOnce(&mut Reader<'a>) -> Result<R, E>,
140
    {
141
0
        let mut input = Reader::new(*self);
142
0
        let result = read(&mut input)?;
143
0
        if input.at_end() {
144
0
            Ok(result)
145
        } else {
146
0
            Err(incomplete_read)
147
        }
148
0
    }
Unexecuted instantiation: <untrusted::Input>::read_all::<aws_lc_rs::io::der::nonnegative_integer::{closure#0}::{closure#0}, (), aws_lc_rs::error::Unspecified>
Unexecuted instantiation: <untrusted::Input>::read_all::<aws_lc_rs::io::der::nonnegative_integer::{closure#0}, untrusted::Input, aws_lc_rs::error::Unspecified>
Unexecuted instantiation: <untrusted::Input>::read_all::<aws_lc_rs::io::der::bit_string_with_no_unused_bits::{closure#0}, untrusted::Input, aws_lc_rs::error::Unspecified>
Unexecuted instantiation: <untrusted::Input>::read_all::<aws_lc_rs::io::der::nonnegative_integer::check_minimum::{closure#0}, (), aws_lc_rs::error::Unspecified>
Unexecuted instantiation: <untrusted::Input>::read_all::<_, _, _>
149
150
    /// Access the input as a slice so it can be processed by functions that
151
    /// are not written using the Input/Reader framework.
152
    #[inline]
153
0
    pub fn as_slice_less_safe(&self) -> &'a [u8] { self.value.as_slice_less_safe() }
Unexecuted instantiation: <untrusted::Input>::as_slice_less_safe
Unexecuted instantiation: <untrusted::Input>::as_slice_less_safe
154
}
155
156
impl<'a> From<&'a [u8]> for Input<'a> {
157
    #[inline]
158
0
    fn from(value: &'a [u8]) -> Self { Self { value: no_panic::Slice::new(value)} }
159
}
160
161
// #[derive(PartialEq)] would result in lifetime bounds that are
162
// unnecessarily restrictive; see
163
// https://github.com/rust-lang/rust/issues/26925.
164
impl PartialEq<Input<'_>> for Input<'_> {
165
    #[inline]
166
0
    fn eq(&self, other: &Input) -> bool {
167
0
        self.as_slice_less_safe() == other.as_slice_less_safe()
168
0
    }
169
}
170
171
impl PartialEq<[u8]> for Input<'_> {
172
    #[inline]
173
0
    fn eq(&self, other: &[u8]) -> bool { self.as_slice_less_safe() == other }
174
}
175
176
impl PartialEq<Input<'_>> for [u8] {
177
    #[inline]
178
0
    fn eq(&self, other: &Input) -> bool { other.as_slice_less_safe() == self }
179
}
180
181
/// Calls `read` with the given input as a `Reader`, ensuring that `read`
182
/// consumed the entire input. When `input` is `None`, `read` will be
183
/// called with `None`.
184
0
pub fn read_all_optional<'a, F, R, E>(
185
0
    input: Option<Input<'a>>, incomplete_read: E, read: F,
186
0
) -> Result<R, E>
187
0
where
188
0
    F: FnOnce(Option<&mut Reader<'a>>) -> Result<R, E>,
189
{
190
0
    match input {
191
0
        Some(input) => {
192
0
            let mut input = Reader::new(input);
193
0
            let result = read(Some(&mut input))?;
194
0
            if input.at_end() {
195
0
                Ok(result)
196
            } else {
197
0
                Err(incomplete_read)
198
            }
199
        },
200
0
        None => read(None),
201
    }
202
0
}
203
204
/// A read-only, forward-only* cursor into the data in an `Input`.
205
///
206
/// Using `Reader` to parse input helps to ensure that no byte of the input
207
/// will be accidentally processed more than once. Using `Reader` in
208
/// conjunction with `read_all` and `read_all_optional` helps ensure that no
209
/// byte of the input is accidentally left unprocessed. The methods of `Reader`
210
/// never panic, so `Reader` also assists the writing of panic-free code.
211
///
212
/// \* `Reader` is not strictly forward-only because of the method
213
/// `get_input_between_marks`, which is provided mainly to support calculating
214
/// digests over parsed data.
215
#[derive(Debug)]
216
pub struct Reader<'a> {
217
    input: no_panic::Slice<'a>,
218
    i: usize,
219
}
220
221
/// An index into the already-parsed input of a `Reader`.
222
pub struct Mark {
223
    i: usize,
224
}
225
226
impl<'a> Reader<'a> {
227
    /// Construct a new Reader for the given input. Use `read_all` or
228
    /// `read_all_optional` instead of `Reader::new` whenever possible.
229
    #[inline]
230
0
    pub fn new(input: Input<'a>) -> Self {
231
0
        Self {
232
0
            input: input.value,
233
0
            i: 0,
234
0
        }
235
0
    }
Unexecuted instantiation: <untrusted::Reader>::new
Unexecuted instantiation: <untrusted::Reader>::new
236
237
    /// Returns `true` if the reader is at the end of the input, and `false`
238
    /// otherwise.
239
    #[inline]
240
0
    pub fn at_end(&self) -> bool { self.i == self.input.len() }
Unexecuted instantiation: <untrusted::Reader>::at_end
Unexecuted instantiation: <untrusted::Reader>::at_end
241
242
    /// Returns an `Input` for already-parsed input that has had its boundaries
243
    /// marked using `mark`.
244
    #[inline]
245
0
    pub fn get_input_between_marks(
246
0
        &self, mark1: Mark, mark2: Mark,
247
0
    ) -> Result<Input<'a>, EndOfInput> {
248
0
        self.input
249
0
            .subslice(mark1.i..mark2.i)
250
0
            .map(|subslice| Input { value: subslice })
251
0
            .ok_or(EndOfInput)
252
0
    }
253
254
    /// Return the current position of the `Reader` for future use in a call
255
    /// to `get_input_between_marks`.
256
    #[inline]
257
0
    pub fn mark(&self) -> Mark { Mark { i: self.i } }
258
259
    /// Returns `true` if there is at least one more byte in the input and that
260
    /// byte is equal to `b`, and false otherwise.
261
    #[inline]
262
0
    pub fn peek(&self, b: u8) -> bool {
263
0
        match self.input.get(self.i) {
264
0
            Some(actual_b) => b == *actual_b,
265
0
            None => false,
266
        }
267
0
    }
268
269
    /// Reads the next input byte.
270
    ///
271
    /// Returns `Ok(b)` where `b` is the next input byte, or `Err(EndOfInput)`
272
    /// if the `Reader` is at the end of the input.
273
    #[inline]
274
0
    pub fn read_byte(&mut self) -> Result<u8, EndOfInput> {
275
0
        match self.input.get(self.i) {
276
0
            Some(b) => {
277
0
                self.i += 1; // safe from overflow; see Input::from().
278
0
                Ok(*b)
279
            },
280
0
            None => Err(EndOfInput),
281
        }
282
0
    }
Unexecuted instantiation: <untrusted::Reader>::read_byte
Unexecuted instantiation: <untrusted::Reader>::read_byte
283
284
    /// Skips `num_bytes` of the input, returning the skipped input as an
285
    /// `Input`.
286
    ///
287
    /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining,
288
    /// and `Err(EndOfInput)` otherwise.
289
    #[inline]
290
0
    pub fn read_bytes(&mut self, num_bytes: usize) -> Result<Input<'a>, EndOfInput> {
291
0
        let new_i = self.i.checked_add(num_bytes).ok_or(EndOfInput)?;
292
0
        let ret = self
293
0
            .input
294
0
            .subslice(self.i..new_i)
295
0
            .map(|subslice| Input { value: subslice })
Unexecuted instantiation: <untrusted::Reader>::read_bytes::{closure#0}
Unexecuted instantiation: <untrusted::Reader>::read_bytes::{closure#0}
296
0
            .ok_or(EndOfInput)?;
297
0
        self.i = new_i;
298
0
        Ok(ret)
299
0
    }
Unexecuted instantiation: <untrusted::Reader>::read_bytes
Unexecuted instantiation: <untrusted::Reader>::read_bytes
300
301
    /// Skips the reader to the end of the input, returning the skipped input
302
    /// as an `Input`.
303
    #[inline]
304
0
    pub fn read_bytes_to_end(&mut self) -> Input<'a> {
305
0
        let to_skip = self.input.len() - self.i;
306
0
        self.read_bytes(to_skip).unwrap()
307
0
    }
Unexecuted instantiation: <untrusted::Reader>::read_bytes_to_end
Unexecuted instantiation: <untrusted::Reader>::read_bytes_to_end
308
309
    /// Calls `read()` with the given input as a `Reader`. On success, returns a
310
    /// pair `(bytes_read, r)` where `bytes_read` is what `read()` consumed and
311
    /// `r` is `read()`'s return value.
312
0
    pub fn read_partial<F, R, E>(&mut self, read: F) -> Result<(Input<'a>, R), E>
313
0
    where
314
0
        F: FnOnce(&mut Reader<'a>) -> Result<R, E>,
315
    {
316
0
        let start = self.i;
317
0
        let r = read(self)?;
318
0
        let bytes_read = Input {
319
0
            value: self.input.subslice(start..self.i).unwrap()
320
0
        };
321
0
        Ok((bytes_read, r))
322
0
    }
323
324
    /// Skips `num_bytes` of the input.
325
    ///
326
    /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining,
327
    /// and `Err(EndOfInput)` otherwise.
328
    #[inline]
329
0
    pub fn skip(&mut self, num_bytes: usize) -> Result<(), EndOfInput> {
330
0
        self.read_bytes(num_bytes).map(|_| ())
331
0
    }
332
333
    /// Skips the reader to the end of the input.
334
    #[inline]
335
0
    pub fn skip_to_end(&mut self) -> () { let _ = self.read_bytes_to_end(); }
336
}
337
338
/// The error type used to indicate the end of the input was reached before the
339
/// operation could be completed.
340
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
341
pub struct EndOfInput;
342
343
mod no_panic {
344
    use core;
345
346
    /// A wrapper around a slice that exposes no functions that can panic.
347
    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
348
    pub struct Slice<'a> {
349
        bytes: &'a [u8],
350
    }
351
352
    impl<'a> Slice<'a> {
353
        #[inline]
354
0
        pub const fn new(bytes: &'a [u8]) -> Self { Self { bytes } }
355
356
        #[inline]
357
0
        pub fn get(&self, i: usize) -> Option<&u8> { self.bytes.get(i) }
Unexecuted instantiation: <untrusted::no_panic::Slice>::get
Unexecuted instantiation: <untrusted::no_panic::Slice>::get
358
359
        #[inline]
360
0
        pub fn subslice(&self, r: core::ops::Range<usize>) -> Option<Self> {
361
0
            self.bytes.get(r).map(|bytes| Self { bytes })
Unexecuted instantiation: <untrusted::no_panic::Slice>::subslice::{closure#0}
Unexecuted instantiation: <untrusted::no_panic::Slice>::subslice::{closure#0}
362
0
        }
Unexecuted instantiation: <untrusted::no_panic::Slice>::subslice
Unexecuted instantiation: <untrusted::no_panic::Slice>::subslice
363
364
        #[inline]
365
0
        pub fn is_empty(&self) -> bool { self.bytes.is_empty() }
366
367
        #[inline]
368
0
        pub fn len(&self) -> usize { self.bytes.len() }
Unexecuted instantiation: <untrusted::no_panic::Slice>::len
Unexecuted instantiation: <untrusted::no_panic::Slice>::len
369
370
        #[inline]
371
0
        pub fn as_slice_less_safe(&self) -> &'a [u8] { self.bytes }
Unexecuted instantiation: <untrusted::no_panic::Slice>::as_slice_less_safe
Unexecuted instantiation: <untrusted::no_panic::Slice>::as_slice_less_safe
372
    }
373
374
} // mod no_panic