Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/untrusted-0.9.0/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015-2021 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/main/src/io/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
#![no_std]
88
89
mod input;
90
mod no_panic;
91
mod reader;
92
93
pub use {
94
    input::Input,
95
    reader::{EndOfInput, Reader},
96
};
97
98
/// Calls `read` with the given input as a `Reader`, ensuring that `read`
99
/// consumed the entire input. When `input` is `None`, `read` will be
100
/// called with `None`.
101
0
pub fn read_all_optional<'a, F, R, E>(
102
0
    input: Option<Input<'a>>,
103
0
    incomplete_read: E,
104
0
    read: F,
105
0
) -> Result<R, E>
106
0
where
107
0
    F: FnOnce(Option<&mut Reader<'a>>) -> Result<R, E>,
108
0
{
109
0
    match input {
110
0
        Some(input) => {
111
0
            let mut input = Reader::new(input);
112
0
            let result = read(Some(&mut input))?;
113
0
            if input.at_end() {
114
0
                Ok(result)
115
            } else {
116
0
                Err(incomplete_read)
117
            }
118
        }
119
0
        None => read(None),
120
    }
121
0
}
Unexecuted instantiation: untrusted::read_all_optional::<webpki::verify_cert::check_issuer_independent_properties::{closure#2}, (), webpki::error::Error>
Unexecuted instantiation: untrusted::read_all_optional::<webpki::verify_cert::check_issuer_independent_properties::{closure#1}, (), webpki::error::Error>
Unexecuted instantiation: untrusted::read_all_optional::<webpki::verify_cert::check_signed_chain_name_constraints::{closure#1}, (), webpki::error::Error>
Unexecuted instantiation: untrusted::read_all_optional::<_, _, _>