untrusted-0.9.0/.cargo_vcs_info.json0000644000000001120000000000000130700ustar { "git": { "sha1": "89c8b8415f692d3803d183fc5fbf9ec08a6adcf4" } } untrusted-0.9.0/.gitattributes000064400000000000000000000002340000000000000145360ustar 00000000000000* text=auto !eol *.sln eol=crlf *.vcxproj eol=crlf *.vcxproj.filters eol=crlf *.props eol=crlf *.bat eol=crlf *.rc eol=crlf *.pl linguist-language=Assembly untrusted-0.9.0/.github/workflows/ci.yml000064400000000000000000000117530000000000000163660ustar 00000000000000name: ci permissions: contents: read on: pull_request: push: jobs: rustfmt: runs-on: ubuntu-18.04 steps: - uses: briansmith/actions-rs-toolchain@v1 with: toolchain: stable profile: minimal components: rustfmt - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - run: cargo fmt --all -- --check clippy: runs-on: ubuntu-18.04 steps: - uses: briansmith/actions-rs-toolchain@v1 with: toolchain: stable profile: minimal components: clippy - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - run: cargo clippy --all-features ---all-targets -- --deny warnings audit: runs-on: ubuntu-18.04 steps: - uses: briansmith/actions-rs-toolchain@v1 with: toolchain: stable profile: minimal - uses: briansmith/actions-cache@v2 with: path: | ~/.cargo/bin/cargo-audit ~/.cargo/.crates.toml ~/.cargo/.crates2.json key: ${{ runner.os }}-v2-cargo-audit-0.13.1 - run: cargo install cargo-audit --vers "0.13.1" - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - run: cargo generate-lockfile - run: cargo audit --deny warnings deny: runs-on: ubuntu-18.04 steps: - uses: briansmith/actions-rs-toolchain@v1 with: toolchain: stable profile: minimal - uses: briansmith/actions-cache@v2 with: path: | ~/.cargo/bin/cargo-deny ~/.cargo/.crates.toml ~/.cargo/.crates2.json key: ${{ runner.os }}-v2-cargo-deny-0.8.4 - run: cargo install cargo-deny --vers "0.8.4" - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - run: cargo deny check # Verify that documentation builds. rustdoc: runs-on: ubuntu-18.04 strategy: matrix: rust_channel: - stable - beta - nightly include: - target: x86_64-unknown-linux-gnu steps: - uses: briansmith/actions-rs-toolchain@v1 with: override: true target: ${{ matrix.target }} toolchain: ${{ matrix.rust_channel }} - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - run: | cargo doc --all-features test: runs-on: ${{ matrix.host_os }} strategy: matrix: features: - # Default target: - i686-unknown-linux-musl - x86_64-unknown-linux-gnu mode: - # debug - --release rust_channel: - stable - nightly - 1.49.0 # MSRV - beta include: - target: i686-unknown-linux-musl host_os: ubuntu-18.04 - target: x86_64-unknown-linux-gnu host_os: ubuntu-18.04 steps: - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - uses: briansmith/actions-rs-toolchain@v1 with: override: true target: ${{ matrix.target }} toolchain: ${{ matrix.rust_channel }} - run: | cargo test -vv --target=${{ matrix.target }} ${{ matrix.cargo_options }} ${{ matrix.features }} ${{ matrix.mode }} coverage: runs-on: ${{ matrix.host_os }} strategy: matrix: features: - --all-features target: - x86_64-unknown-linux-musl mode: - # debug # Coverage collection is Nightly-only rust_channel: - nightly # TODO: targets include: - target: x86_64-unknown-linux-musl host_os: ubuntu-18.04 steps: - if: ${{ contains(matrix.host_os, 'ubuntu') }} run: sudo apt-get update -y - uses: briansmith/actions-checkout@v2 with: persist-credentials: false - if: ${{ !contains(matrix.host_os, 'windows') }} run: RING_COVERAGE=1 mk/install-build-tools.sh --target=${{ matrix.target }} ${{ matrix.features }} - uses: briansmith/actions-rs-toolchain@v1 with: override: true target: ${{ matrix.target }} toolchain: ${{ matrix.rust_channel }} - if: ${{ matrix.target == 'aarch64-apple-darwin' }} run: echo "DEVELOPER_DIR=/Applications/Xcode_12.2.app/Contents/Developer" >> $GITHUB_ENV - if: ${{ !contains(matrix.host_os, 'windows') }} run: | RING_COVERAGE=1 mk/cargo.sh +${{ matrix.rust_channel }} test -vv --target=${{ matrix.target }} ${{ matrix.cargo_options }} ${{ matrix.features }} ${{ matrix.mode }} - uses: briansmith/codecov-codecov-action@v1 with: directory: ./target/${{ matrix.target }}/debug/coverage/reports fail_ci_if_error: true verbose: true untrusted-0.9.0/.gitignore000064400000000000000000000005020000000000000136310ustar 00000000000000build/ ssl/test/runner/runner *.bk *.orig *.swp *.swo doc/*.html doc/doc.css *~ # Visual Studio Junk .vs/ *.opensdf *.psess *.sdf *.sln.docstates *.suo *.user *.userosscache *.VC.db *.VC.opendb *.vsp *.vspx *.rsproj *.sln *.vcxproj *.filters # Cargo Junk Cargo.lock target/ # JetBrains Junk .idea *.iml CMakeLists.txt untrusted-0.9.0/Cargo.toml0000644000000017050000000000000110770ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "untrusted" version = "0.9.0" authors = ["Brian Smith "] description = "Safe, fast, zero-panic, zero-crashing, zero-allocation parsing of untrusted inputs in Rust." documentation = "https://briansmith.org/rustdoc/untrusted/" readme = "README.md" license = "ISC" repository = "https://github.com/briansmith/untrusted" [profile.bench] opt-level = 2 lto = true [lib] name = "untrusted" untrusted-0.9.0/Cargo.toml.orig000064400000000000000000000006710000000000000145370ustar 00000000000000[package] authors = ["Brian Smith "] description = "Safe, fast, zero-panic, zero-crashing, zero-allocation parsing of untrusted inputs in Rust." documentation = "https://briansmith.org/rustdoc/untrusted/" edition = "2018" license = "ISC" name = "untrusted" readme = "README.md" repository = "https://github.com/briansmith/untrusted" version = "0.9.0" [lib] name = "untrusted" [profile.bench] opt-level = 2 lto = true untrusted-0.9.0/LICENSE.txt000064400000000000000000000014010000000000000134630ustar 00000000000000// Copyright 2015-2016 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. untrusted-0.9.0/README.md000064400000000000000000000062550000000000000131330ustar 00000000000000THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. untrusted.rs ============ Safe, fast, zero-panic, zero-crashing, zero-allocation parsing of untrusted inputs in Rust. untrusted.rs is 100% Rust with no use of `unsafe`. It never uses the heap. No part of untrusted.rs's API will ever panic or cause a crash. It is `#![no_std]` and so it works perfectly with both libcore- and libstd- based projects. It does not depend on any crates other than libcore. untrusted.rs is intended to be used with the latest version of Rust Stable. It should usually work with the latest Rust Beta and Rust Nightly versions too. Using a version of untrusted.rs other than the latest release available on crates.io is not recommended. Documentation ------------- See the documentation at https://briansmith.org/rustdoc/untrusted/. To use untrusted.rs in your project, add a dependency to your Cargo.toml like this: ``` [dependencies] untrusted = "0.2" ``` Examples -------- [*ring*](https://github.com/briansmith/ring)'s parser for the subset of ASN.1 DER it needs to understand, [`ring::der`](https://github.com/briansmith/ring/blob/master/src/der.rs), is built on top of untrusted.rs. *ring* also uses untrusted.rs to parse ECC public keys, RSA PKCS#1 1.5 padding, and everything else. All of [webpki](https://github.com/briansmith/webpki)'s parsing of X.509 certificates (also ASN.1 DER) is done using untrusted.rs. Contributing ------------ Patches welcome! When contributing changes, state that you agree to license your contribution under the same terms as the existing code by putting this at the bottom of your commit message: ``` I agree to license my contributions to each file under the terms given at the top of each file I changed. ``` Currently, the biggest needs for this library are: * Unit tests. * Documentation. * More examples. * Static analysis and fuzzing. Online Automated Testing ------------------------ Travis CI is used for Android, Linux, and Mac OS X. The tests are run for the current release of each Rust channel (Stable, Beta, Nightly). Since untrusted.rs only depends on libcore and it only uses 100% cross-platform code without using `unsafe`, it should work anywhere as long as these platforms are passing. Bug Reporting ------------- Please report bugs either as pull requests or as issues in [the issue tracker](https://github.com/briansmith/untrusted/issues). untrusted.rs has a **full disclosure** vulnerability policy. **Please do NOT attempt to report any security vulnerability in this code privately to anybody.** License ------- See [LICENSE.txt](LICENSE.txt), an ISC-style (simplified MIT) license. untrusted-0.9.0/deny.toml000064400000000000000000000005250000000000000135020ustar 00000000000000[advisories] unmaintained = "deny" yanked = "deny" notice = "deny" [licenses] allow = [ "ISC", ] confidence-threshold = 1.0 [bans] # We don't maintain a fixed Cargo.lock so enforcing # `multiple-versions = "deny"` is impractical. multiple-versions = "allow" wildcards = "deny" [sources] unknown-registry = "deny" unknown-git = "deny" untrusted-0.9.0/mk/cargo.sh000064400000000000000000000142050000000000000137040ustar 00000000000000#!/usr/bin/env bash # # Copyright 2020 Brian Smith. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. set -eux -o pipefail IFS=$'\n\t' rustflags_self_contained="-Clink-self-contained=yes -Clinker=rust-lld" qemu_aarch64="qemu-aarch64 -L /usr/aarch64-linux-gnu" qemu_arm="qemu-arm -L /usr/arm-linux-gnueabihf" # Avoid putting the Android tools in `$PATH` because there are tools in this # directory like `clang` that would conflict with the same-named tools that may # be needed to compile the build script, or to compile for other targets. if [ -n "${ANDROID_SDK_ROOT-}" ]; then android_tools=$ANDROID_SDK_ROOT/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin fi for arg in $*; do case $arg in --target=*) target=${arg#*=} ;; *) ;; esac done # See comments in install-build-tools.sh. llvm_version=10 if [ -n "${RING_COVERAGE-}" ]; then llvm_version=11 fi case $target in aarch64-linux-android) export CC_aarch64_linux_android=$android_tools/aarch64-linux-android21-clang export AR_aarch64_linux_android=$android_tools/aarch64-linux-android-ar export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$android_tools/aarch64-linux-android21-clang ;; aarch64-unknown-linux-gnu) export CC_aarch64_unknown_linux_gnu=clang-$llvm_version export AR_aarch64_unknown_linux_gnu=llvm-ar-$llvm_version export CFLAGS_aarch64_unknown_linux_gnu="--sysroot=/usr/aarch64-linux-gnu" export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="$qemu_aarch64" ;; aarch64-unknown-linux-musl) export CC_aarch64_unknown_linux_musl=clang-$llvm_version export AR_aarch64_unknown_linux_musl=llvm-ar-$llvm_version export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="$rustflags_self_contained" export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUNNER="$qemu_aarch64" ;; arm-unknown-linux-gnueabihf) export CC_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc export AR_arm_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc-ar export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc export CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER="$qemu_arm" ;; armv7-linux-androideabi) export CC_armv7_linux_androideabi=$android_tools/armv7a-linux-androideabi18-clang export AR_armv7_linux_androideabi=$android_tools/arm-linux-androideabi-ar export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$android_tools/armv7a-linux-androideabi18-clang ;; armv7-unknown-linux-musleabihf) export CC_armv7_unknown_linux_musleabihf=clang-$llvm_version export AR_armv7_unknown_linux_musleabihf=llvm-ar-$llvm_version export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_MUSLEABIHF_RUSTFLAGS="$rustflags_self_contained" export CARGO_TARGET_ARMV7_UNKNOWN_LINUX_MUSLEABIHF_RUNNER="$qemu_arm" ;; i686-unknown-linux-gnu) export CC_i686_unknown_linux_gnu=clang-$llvm_version export AR_i686_unknown_linux_gnu=llvm-ar-$llvm_version export CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang-$llvm_version ;; i686-unknown-linux-musl) export CC_i686_unknown_linux_musl=clang-$llvm_version export AR_i686_unknown_linux_musl=llvm-ar-$llvm_version export CARGO_TARGET_I686_UNKNOWN_LINUX_MUSL_RUSTFLAGS="$rustflags_self_contained" ;; x86_64-unknown-linux-musl) export CC_x86_64_unknown_linux_musl=clang-$llvm_version export AR_x86_64_unknown_linux_musl=llvm-ar-$llvm_version # XXX: Work around https://github.com/rust-lang/rust/issues/79555. if [ -n "${RING_COVERAGE-}" ]; then export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=clang-$llvm_version else export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="$rustflags_self_contained" fi ;; wasm32-unknown-unknown) # The first two are only needed for when the "wasm_c" feature is enabled. export CC_wasm32_unknown_unknown=clang-$llvm_version export AR_wasm32_unknown_unknown=llvm-ar-$llvm_version export CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner ;; *) ;; esac if [ -n "${RING_COVERAGE-}" ]; then # XXX: Collides between release and debug. coverage_dir=$PWD/target/$target/debug/coverage mkdir -p "$coverage_dir" rm -f "$coverage_dir/*.profraw" export RING_BUILD_EXECUTABLE_LIST="$coverage_dir/executables" truncate --size=0 "$RING_BUILD_EXECUTABLE_LIST" # This doesn't work when profiling under QEMU. Instead mk/runner does # something similar but different. # export LLVM_PROFILE_FILE="$coverage_dir/%m.profraw" # ${target} with hyphens replaced by underscores, lowercase and uppercase. target_lower=${target//-/_} target_upper=${target_lower^^} cflags_var=CFLAGS_${target_lower} declare -x "${cflags_var}=-fprofile-instr-generate -fcoverage-mapping ${!cflags_var-}" runner_var=CARGO_TARGET_${target_upper}_RUNNER declare -x "${runner_var}=mk/runner ${!runner_var-}" rustflags_var=CARGO_TARGET_${target_upper}_RUSTFLAGS declare -x "${rustflags_var}=-Zinstrument-coverage ${!rustflags_var-}" fi cargo "$@" if [ -n "${RING_COVERAGE-}" ]; then while read executable; do basename=$(basename "$executable") llvm-profdata-$llvm_version merge -sparse ""$coverage_dir"/$basename.profraw" -o "$coverage_dir"/$basename.profdata mkdir -p "$coverage_dir"/reports llvm-cov-$llvm_version export \ --instr-profile "$coverage_dir"/$basename.profdata \ --format lcov \ "$executable" \ > "$coverage_dir"/reports/coverage-$basename.txt done < "$RING_BUILD_EXECUTABLE_LIST" fi untrusted-0.9.0/mk/install-build-tools.sh000064400000000000000000000056510000000000000165170ustar 00000000000000#!/usr/bin/env bash # # Copyright 2020 Brian Smith. # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. set -eux -o pipefail IFS=$'\n\t' target=$1 features=${2-} function install_packages { sudo apt-get -yq --no-install-suggests --no-install-recommends install "$@" } use_clang= case $target in --target*android*) mkdir -p "${ANDROID_SDK_ROOT}/licenses" android_license_file="${ANDROID_SDK_ROOT}/licenses/android-sdk-license" accept_android_license=24333f8a63b6825ea9c5514f83c2829b004d1fee grep --quiet --no-messages "$accept_android_license" "$android_license_file" \ || echo $accept_android_license >> "$android_license_file" sudo "${ANDROID_SDK_ROOT}/tools/bin/sdkmanager" ndk-bundle ;; esac case $target in --target=aarch64-unknown-linux-gnu) # Clang is needed for code coverage. use_clang=1 install_packages \ qemu-user \ gcc-aarch64-linux-gnu \ libc6-dev-arm64-cross ;; --target=aarch64-unknown-linux-musl|--target=armv7-unknown-linux-musleabihf) use_clang=1 install_packages \ qemu-user ;; --target=arm-unknown-linux-gnueabihf) install_packages \ qemu-user \ gcc-arm-linux-gnueabihf \ libc6-dev-armhf-cross ;; --target=i686-unknown-linux-gnu) use_clang=1 install_packages \ gcc-multilib \ libc6-dev-i386 ;; --target=i686-unknown-linux-musl|--target=x86_64-unknown-linux-musl) use_clang=1 ;; --target=wasm32-unknown-unknown) # The version of wasm-bindgen-cli must match the wasm-bindgen version. wasm_bindgen_version=$(cargo metadata --format-version 1 | jq -r '.packages | map(select( .name == "wasm-bindgen")) | map(.version) | .[0]') cargo install wasm-bindgen-cli --vers "$wasm_bindgen_version" --bin wasm-bindgen-test-runner case ${features-} in *wasm32_c*) use_clang=1 ;; *) ;; esac ;; --target=*) ;; esac if [ -n "$use_clang" ]; then llvm_version=10 if [ -n "${RING_COVERAGE-}" ]; then # https://github.com/rust-lang/rust/pull/79365 upgraded the coverage file # format to one that only LLVM 11+ can use llvm_version=11 sudo apt-key add mk/llvm-snapshot.gpg.key sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-$llvm_version main" sudo apt-get update fi install_packages clang-$llvm_version llvm-$llvm_version fi untrusted-0.9.0/mk/llvm-snapshot.gpg.key000064400000000000000000000062650000000000000163610ustar 00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: See https://apt.llvm.org/. Comment: Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 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 bXb5c6gCHESH5PXwPU4jQEE7Ib9J6sbk7ZT2Mw== =j+4q -----END PGP PUBLIC KEY BLOCK----- untrusted-0.9.0/mk/runner000064400000000000000000000010360000000000000135070ustar 00000000000000#!/bin/bash set -eux -o pipefail IFS=$'\n\t' for arg in $*; do # There can be some arguments prefixed in front of the executable, e.g. # when qemu-user is used. There can be arguments after the executable, # e.g. `cargo test` arguments like `TESTNAME`. if [[ $arg = */deps/* ]]; then executable=$arg break fi done export LLVM_PROFILE_FILE=$(dirname "$RING_BUILD_EXECUTABLE_LIST")/$(basename "$executable").profraw if [ -n "$RING_BUILD_EXECUTABLE_LIST" ]; then echo "$executable" >> "$RING_BUILD_EXECUTABLE_LIST" fi $* untrusted-0.9.0/rustfmt.toml000064400000000000000000000001570000000000000142500ustar 00000000000000edition = "2018" max_width = 100 newline_style = "Unix" reorder_imports = true use_field_init_shorthand = true untrusted-0.9.0/src/input.rs000064400000000000000000000065300000000000000141440ustar 00000000000000// Copyright 2015-2021 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::{no_panic, Reader}; /// A wrapper around `&'a [u8]` that helps in writing panic-free code. /// /// No methods of `Input` will ever panic. /// /// Intentionally avoids implementing `PartialEq` and `Eq` to avoid implicit /// non-constant-time comparisons. #[derive(Clone, Copy)] pub struct Input<'a> { value: no_panic::Slice<'a>, } /// The value is intentionally omitted from the output to avoid leaking /// secrets. impl core::fmt::Debug for Input<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Input").finish() } } impl<'a> Input<'a> { /// Construct a new `Input` for the given input `bytes`. pub const fn from(bytes: &'a [u8]) -> Self { // This limit is important for avoiding integer overflow. In particular, // `Reader` assumes that an `i + 1 > i` if `input.value.get(i)` does // not return `None`. According to the Rust language reference, the // maximum object size is `core::isize::MAX`, and in practice it is // impossible to create an object of size `core::usize::MAX` or larger. Self { value: no_panic::Slice::new(bytes), } } /// Returns `true` if the input is empty and false otherwise. #[inline] pub fn is_empty(&self) -> bool { self.value.is_empty() } /// Returns the length of the `Input`. #[inline] pub fn len(&self) -> usize { self.value.len() } /// Calls `read` with the given input as a `Reader`, ensuring that `read` /// consumed the entire input. If `read` does not consume the entire input, /// `incomplete_read` is returned. pub fn read_all(&self, incomplete_read: E, read: F) -> Result where F: FnOnce(&mut Reader<'a>) -> Result, { let mut input = Reader::new(*self); let result = read(&mut input)?; if input.at_end() { Ok(result) } else { Err(incomplete_read) } } /// Access the input as a slice so it can be processed by functions that /// are not written using the Input/Reader framework. #[inline] pub fn as_slice_less_safe(&self) -> &'a [u8] { self.value.as_slice_less_safe() } pub(super) fn into_value(self) -> no_panic::Slice<'a> { self.value } } impl<'a> From<&'a [u8]> for Input<'a> { #[inline] fn from(value: &'a [u8]) -> Self { no_panic::Slice::new(value).into() } } impl<'a> From> for Input<'a> { #[inline] fn from(value: no_panic::Slice<'a>) -> Self { Self { value } } } untrusted-0.9.0/src/lib.rs000064400000000000000000000131500000000000000135470ustar 00000000000000// Copyright 2015-2021 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. //! untrusted.rs: Safe, fast, zero-panic, zero-crashing, zero-allocation //! parsing of untrusted inputs in Rust. //! //! git clone https://github.com/briansmith/untrusted //! //! untrusted.rs goes beyond Rust's normal safety guarantees by also //! guaranteeing that parsing will be panic-free, as long as //! `untrusted::Input::as_slice_less_safe()` is not used. It avoids copying //! data and heap allocation and strives to prevent common pitfalls such as //! accidentally parsing input bytes multiple times. In order to meet these //! goals, untrusted.rs is limited in functionality such that it works best for //! input languages with a small fixed amount of lookahead such as ASN.1, TLS, //! TCP/IP, and many other networking, IPC, and related protocols. Languages //! that require more lookahead and/or backtracking require some significant //! contortions to parse using this framework. It would not be realistic to use //! it for parsing programming language code, for example. //! //! The overall pattern for using untrusted.rs is: //! //! 1. Write a recursive-descent-style parser for the input language, where the //! input data is given as a `&mut untrusted::Reader` parameter to each //! function. Each function should have a return type of `Result` for //! some value type `V` and some error type `E`, either or both of which may //! be `()`. Functions for parsing the lowest-level language constructs //! should be defined. Those lowest-level functions will parse their inputs //! using `::read_byte()`, `Reader::peek()`, and similar functions. //! Higher-level language constructs are then parsed by calling the //! lower-level functions in sequence. //! //! 2. Wrap the top-most functions of your recursive-descent parser in //! functions that take their input data as an `untrusted::Input`. The //! wrapper functions should call the `Input`'s `read_all` (or a variant //! thereof) method. The wrapper functions are the only ones that should be //! exposed outside the parser's module. //! //! 3. After receiving the input data to parse, wrap it in an `untrusted::Input` //! using `untrusted::Input::from()` as early as possible. Pass the //! `untrusted::Input` to the wrapper functions when they need to be parsed. //! //! In general parsers built using `untrusted::Reader` do not need to explicitly //! check for end-of-input unless they are parsing optional constructs, because //! `Reader::read_byte()` will return `Err(EndOfInput)` on end-of-input. //! Similarly, parsers using `untrusted::Reader` generally don't need to check //! for extra junk at the end of the input as long as the parser's API uses the //! pattern described above, as `read_all` and its variants automatically check //! for trailing junk. `Reader::skip_to_end()` must be used when any remaining //! unread input should be ignored without triggering an error. //! //! untrusted.rs works best when all processing of the input data is done //! through the `untrusted::Input` and `untrusted::Reader` types. In //! particular, avoid trying to parse input data using functions that take //! byte slices. However, when you need to access a part of the input data as //! a slice to use a function that isn't written using untrusted.rs, //! `Input::as_slice_less_safe()` can be used. //! //! It is recommend to use `use untrusted;` and then `untrusted::Input`, //! `untrusted::Reader`, etc., instead of using `use untrusted::*`. Qualifying //! the names with `untrusted` helps remind the reader of the code that it is //! dealing with *untrusted* input. //! //! # Examples //! //! [*ring*](https://github.com/briansmith/ring)'s parser for the subset of //! ASN.1 DER it needs to understand, //! [`ring::der`](https://github.com/briansmith/ring/blob/main/src/io/der.rs), //! is built on top of untrusted.rs. *ring* also uses untrusted.rs to parse ECC //! public keys, RSA PKCS#1 1.5 padding, and for all other parsing it does. //! //! All of [webpki](https://github.com/briansmith/webpki)'s parsing of X.509 //! certificates (also ASN.1 DER) is done using untrusted.rs. #![doc(html_root_url = "https://briansmith.org/rustdoc/")] #![no_std] mod input; mod no_panic; mod reader; pub use { input::Input, reader::{EndOfInput, Reader}, }; /// Calls `read` with the given input as a `Reader`, ensuring that `read` /// consumed the entire input. When `input` is `None`, `read` will be /// called with `None`. pub fn read_all_optional<'a, F, R, E>( input: Option>, incomplete_read: E, read: F, ) -> Result where F: FnOnce(Option<&mut Reader<'a>>) -> Result, { match input { Some(input) => { let mut input = Reader::new(input); let result = read(Some(&mut input))?; if input.at_end() { Ok(result) } else { Err(incomplete_read) } } None => read(None), } } untrusted-0.9.0/src/no_panic.rs000064400000000000000000000016200000000000000145660ustar 00000000000000/// A wrapper around a slice that exposes no functions that can panic. /// /// Intentionally avoids implementing `Debug`, `Eq`, and `PartialEq` to avoid /// creating a side channel that would leak information about the value. #[derive(Clone, Copy)] pub struct Slice<'a> { bytes: &'a [u8], } impl<'a> Slice<'a> { #[inline] pub const fn new(bytes: &'a [u8]) -> Self { Self { bytes } } #[inline] pub fn get(&self, i: usize) -> Option<&u8> { self.bytes.get(i) } #[inline] pub fn subslice(&self, r: core::ops::Range) -> Option { self.bytes.get(r).map(|bytes| Self { bytes }) } #[inline] pub fn is_empty(&self) -> bool { self.bytes.is_empty() } #[inline] pub fn len(&self) -> usize { self.bytes.len() } #[inline] pub fn as_slice_less_safe(&self) -> &'a [u8] { self.bytes } } untrusted-0.9.0/src/reader.rs000064400000000000000000000116470000000000000142540ustar 00000000000000// Copyright 2015-2021 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use crate::{no_panic, Input}; /// A read-only, forward-only cursor into the data in an `Input`. /// /// Using `Reader` to parse input helps to ensure that no byte of the input /// will be accidentally processed more than once. Using `Reader` in /// conjunction with `read_all` and `read_all_optional` helps ensure that no /// byte of the input is accidentally left unprocessed. The methods of `Reader` /// never panic, so `Reader` also assists the writing of panic-free code. /// /// Intentionally avoids implementing `PartialEq` and `Eq` to avoid implicit /// non-constant-time comparisons. pub struct Reader<'a> { input: no_panic::Slice<'a>, i: usize, } /// Avoids writing the value or position to avoid creating a side channel, /// though `Reader` can't avoid leaking the position via timing. impl core::fmt::Debug for Reader<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Reader").finish() } } impl<'a> Reader<'a> { /// Construct a new Reader for the given input. Use `read_all` or /// `read_all_optional` instead of `Reader::new` whenever possible. #[inline] pub fn new(input: Input<'a>) -> Self { Self { input: input.into_value(), i: 0, } } /// Returns `true` if the reader is at the end of the input, and `false` /// otherwise. #[inline] pub fn at_end(&self) -> bool { self.i == self.input.len() } /// Returns `true` if there is at least one more byte in the input and that /// byte is equal to `b`, and false otherwise. #[inline] pub fn peek(&self, b: u8) -> bool { match self.input.get(self.i) { Some(actual_b) => b == *actual_b, None => false, } } /// Reads the next input byte. /// /// Returns `Ok(b)` where `b` is the next input byte, or `Err(EndOfInput)` /// if the `Reader` is at the end of the input. #[inline] pub fn read_byte(&mut self) -> Result { match self.input.get(self.i) { Some(b) => { self.i += 1; // safe from overflow; see Input::from(). Ok(*b) } None => Err(EndOfInput), } } /// Skips `num_bytes` of the input, returning the skipped input as an /// `Input`. /// /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining, /// and `Err(EndOfInput)` otherwise. #[inline] pub fn read_bytes(&mut self, num_bytes: usize) -> Result, EndOfInput> { let new_i = self.i.checked_add(num_bytes).ok_or(EndOfInput)?; let ret = self .input .subslice(self.i..new_i) .map(From::from) .ok_or(EndOfInput)?; self.i = new_i; Ok(ret) } /// Skips the reader to the end of the input, returning the skipped input /// as an `Input`. #[inline] pub fn read_bytes_to_end(&mut self) -> Input<'a> { let to_skip = self.input.len() - self.i; self.read_bytes(to_skip).unwrap() } /// Calls `read()` with the given input as a `Reader`. On success, returns a /// pair `(bytes_read, r)` where `bytes_read` is what `read()` consumed and /// `r` is `read()`'s return value. pub fn read_partial(&mut self, read: F) -> Result<(Input<'a>, R), E> where F: FnOnce(&mut Reader<'a>) -> Result, { let start = self.i; let r = read(self)?; let bytes_read = self.input.subslice(start..self.i).unwrap().into(); Ok((bytes_read, r)) } /// Skips `num_bytes` of the input. /// /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining, /// and `Err(EndOfInput)` otherwise. #[inline] pub fn skip(&mut self, num_bytes: usize) -> Result<(), EndOfInput> { self.read_bytes(num_bytes).map(|_| ()) } /// Skips the reader to the end of the input. #[inline] pub fn skip_to_end(&mut self) { let _ = self.read_bytes_to_end(); } } /// The error type used to indicate the end of the input was reached before the /// operation could be completed. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct EndOfInput; untrusted-0.9.0/tests/tests.rs000064400000000000000000000075640000000000000145320ustar 00000000000000// Copyright 2015-2019 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #[test] fn test_debug() { const INPUTS: &[&[u8]] = &[b"", b"foo"]; for input in INPUTS { let input = untrusted::Input::from(input); assert_eq!(format!("{:?}", &input), "Input"); input .read_all(untrusted::EndOfInput, |r| { assert_eq!(format!("{:?}", r), "Reader"); r.skip_to_end(); assert_eq!(format!("{:?}", r), "Reader"); Ok(()) }) .unwrap(); } } #[test] fn test_input_clone_and_copy() { const INPUTS: &[&[u8]] = &[b"", b"a", b"foo"]; for input in INPUTS { let input = untrusted::Input::from(input); let copy = input; assert_eq!(input.as_slice_less_safe(), copy.as_slice_less_safe()); assert_eq!( input.as_slice_less_safe(), input.clone().as_slice_less_safe() ); } } #[test] fn test_input_from() { let _ = untrusted::Input::from(b"foo"); } #[test] fn test_input_is_empty() { let input = untrusted::Input::from(b""); assert!(input.is_empty()); let input = untrusted::Input::from(b"foo"); assert!(!input.is_empty()); } #[test] fn test_input_len() { let input = untrusted::Input::from(b"foo"); assert_eq!(input.len(), 3); } #[test] fn test_input_read_all() { let input = untrusted::Input::from(b"foo"); let result = input.read_all(untrusted::EndOfInput, |input| { assert_eq!(b'f', input.read_byte()?); assert_eq!(b'o', input.read_byte()?); assert_eq!(b'o', input.read_byte()?); assert!(input.at_end()); Ok(()) }); assert_eq!(result, Ok(())); } #[test] fn test_input_read_all_unconsume() { let input = untrusted::Input::from(b"foo"); let result = input.read_all(untrusted::EndOfInput, |input| { assert_eq!(b'f', input.read_byte()?); assert!(!input.at_end()); Ok(()) }); assert_eq!(result, Err(untrusted::EndOfInput)); } #[test] fn test_input_as_slice_less_safe() { let slice = b"foo"; let input = untrusted::Input::from(slice); assert_eq!(input.as_slice_less_safe(), slice); } #[test] fn using_reader_after_skip_and_get_error_returns_error_must_not_panic() { let input = untrusted::Input::from(&[]); let r = input.read_all(untrusted::EndOfInput, |input| { let r = input.read_bytes(1); assert_eq!(r.unwrap_err(), untrusted::EndOfInput); Ok(input.read_bytes_to_end()) }); let _ = r; // "Use" r. The value of `r` is undefined here. } #[test] fn size_assumptions() { // Assume that a pointer can address any point in the address space, and // infer that this implies that a byte slice will never be // `core::usize::MAX` bytes long. assert_eq!( core::mem::size_of::<*const u8>(), core::mem::size_of::() ); } #[test] fn const_fn() { const _INPUT: untrusted::Input<'static> = untrusted::Input::from(&[]); } #[test] fn test_vec_into() { extern crate std; let vec = vec![0u8; 0]; let _x: untrusted::Input = (&vec[..]).into(); } #[test] fn test_from_slice() { let slice: &[u8] = &[0u8]; let _x: untrusted::Input = slice.into(); }