Merge rust-bitcoin/rust-bitcoin#3328: Add basic `miri` checks

bd8ad1f5e2 Add basic `miri` checks (Martin Habovstiak)
fb5971cc2b Fix UB in `siphash24` (Martin Habovstiak)

Pull request description:

  We have a bit of `unsafe` code in the crates which should really be checked with `miri`. Thus this adds a basic CI check that automatically determines which crates need `miri` checking and checks them. It also makes sure to enable all target features so that SIMD code can be checked as well.

  This doesn't try to do anything fancy with maintainer tools or run task for now, since I just want to test the basic idea.

  Closes #3192

ACKs for top commit:
  storopoli:
    ACK bd8ad1f5e2
  tcharding:
    ACK bd8ad1f5e2
  sanket1729:
    ACK bd8ad1f5e2
  apoelstra:
    ACK bd8ad1f5e2 successfully ran local tests; wow, good find!

Tree-SHA512: a0d33c7851d6d6b288ca8cc1a902f187814dd82e3528c6f8169fdc0ba71991b99451276aaba5e3b6cde6029e09158063d65e48a71d1e01ee20302b9f653584ef
This commit is contained in:
merge-script 2024-09-10 15:21:37 +00:00
commit 0388930690
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
4 changed files with 63 additions and 9 deletions

33
.github/workflows/miri.yml vendored Normal file
View File

@ -0,0 +1,33 @@
--- # rust-bitcoin CI: If you edit this file please update README.md
on: # yamllint disable-line rule:truthy
push:
branches:
- master
- 'test-ci/**'
pull_request:
name: Miri
jobs:
Miri:
name: Miri
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
- name: "Read nightly version"
id: read_toolchain
run: echo "nightly_version=$(cat nightly-version)" >> $GITHUB_OUTPUT
- name: "Select toolchain"
uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ steps.read_toolchain.outputs.nightly_version }}
components: miri
- name: "Setup miri"
run: cargo miri setup
- name: "Set dependencies"
run: cp Cargo-recent.lock Cargo.lock
- name: "Run test script"
run: ./contrib/test-miri.sh

27
contrib/test-miri.sh Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euox pipefail
cd "$(dirname "$0")/.."
. contrib/test_vars.sh
target_features="$(rustc --print target-features | awk '{ if ($1 == "") { exit 0 } if (NR != 1 && $1 != "crt-static") { if (NR == 2) { printf "+%s", $1 } else { printf ",+%s", $1 } } }')"
for crate in $CRATES;
do
# The secp256k1 crate cannot be miri-checked because of FFI, so we have to exclude it
if cargo tree --manifest-path "$crate/Cargo.toml" | grep -q secp256k1;
then
echo "$crate depends on secp256k1, skipping..." >&2
continue
fi
# Running miri is expensive and not needed for crates that don't contain unsafe
if RUSTFLAGS="-C target-feature=$target_features -F unsafe-code" cargo check -q --all-features --target x86_64-unknown-linux-gnu 2>/dev/null;
then
echo "No unsafe code in $crate, skipping..." >&2
continue
fi
RUSTFLAGS="-C target-feature=$target_features" RUSTDOCFLAGS="-C target-feature=$target_features" MIRIFLAGS=-Zmiri-backtrace=full cargo miri test --manifest-path "$crate/Cargo.toml" --all-features --target x86_64-unknown-linux-gnu
done

View File

@ -4,7 +4,7 @@
use core::ops::Index; use core::ops::Index;
use core::slice::SliceIndex; use core::slice::SliceIndex;
use core::{cmp, mem, ptr}; use core::{cmp, mem};
use crate::HashEngine as _; use crate::HashEngine as _;
@ -53,13 +53,7 @@ macro_rules! compress {
macro_rules! load_int_le { macro_rules! load_int_le {
($buf:expr, $i:expr, $int_ty:ident) => {{ ($buf:expr, $i:expr, $int_ty:ident) => {{
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
let mut data = 0 as $int_ty; $int_ty::from_le_bytes($buf.get_unchecked($i..($i + mem::size_of::<$int_ty>())).try_into().expect("len is correctly computed using size_of"))
ptr::copy_nonoverlapping(
$buf.get_unchecked($i),
&mut data as *mut _ as *mut u8,
mem::size_of::<$int_ty>(),
);
data.to_le()
}}; }};
} }

View File

@ -1 +1 @@
nightly-2024-09-04 nightly-2024-09-07