mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #104617 - RalfJung:miri, r=RalfJung
update Miri r? `@thomcc` for the lib changes (removing a `cfg(miri)` that is no longer needed)
This commit is contained in:
commit
911cbf8e46
@ -2330,7 +2330,6 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-workspace-hack",
|
||||
"rustc_version",
|
||||
"shell-escape",
|
||||
"smallvec",
|
||||
"ui_test",
|
||||
]
|
||||
|
@ -150,7 +150,7 @@ impl From<libc::timespec> for Timespec {
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "macos", any(not(target_arch = "aarch64"), miri)),
|
||||
all(target_os = "macos", any(not(target_arch = "aarch64"))),
|
||||
target_os = "ios",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
@ -270,7 +270,7 @@ mod inner {
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
all(target_os = "macos", any(not(target_arch = "aarch64"), miri)),
|
||||
all(target_os = "macos", any(not(target_arch = "aarch64"))),
|
||||
target_os = "ios",
|
||||
target_os = "watchos"
|
||||
)))]
|
||||
|
@ -383,7 +383,6 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-workspace-hack",
|
||||
"rustc_version",
|
||||
"shell-escape",
|
||||
"smallvec",
|
||||
"ui_test",
|
||||
]
|
||||
@ -632,12 +631,6 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shell-escape"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
|
@ -21,7 +21,6 @@ doctest = false # and no doc tests
|
||||
getrandom = { version = "0.2", features = ["std"] }
|
||||
env_logger = "0.9"
|
||||
log = "0.4"
|
||||
shell-escape = "0.1.4"
|
||||
rand = "0.8"
|
||||
smallvec = "1.7"
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
# Miri
|
||||
|
||||
[![Actions build status][actions-badge]][actions-url]
|
||||
|
||||
[actions-badge]: https://github.com/rust-lang/miri/workflows/CI/badge.svg?branch=master
|
||||
[actions-url]: https://github.com/rust-lang/miri/actions
|
||||
|
||||
An experimental interpreter for [Rust][rust]'s
|
||||
[mid-level intermediate representation][mir] (MIR). It can run binaries and
|
||||
test suites of cargo projects and detect certain classes of
|
||||
@ -200,7 +195,7 @@ randomness that is used to determine allocation base addresses. The following
|
||||
snippet calls Miri in a loop with different values for the seed:
|
||||
|
||||
```
|
||||
for SEED in $({ echo obase=16; seq 0 255; } | bc); do
|
||||
for SEED in $(seq 0 255); do
|
||||
echo "Trying seed: $SEED"
|
||||
MIRIFLAGS=-Zmiri-seed=$SEED cargo miri test || { echo "Failing seed: $SEED"; break; };
|
||||
done
|
||||
@ -308,7 +303,7 @@ environment variable. We first document the most relevant and most commonly used
|
||||
tell what it is doing when a program just keeps running. You can customize how frequently the
|
||||
report is printed via `-Zmiri-report-progress=<blocks>`, which prints the report every N basic
|
||||
blocks.
|
||||
* `-Zmiri-seed=<hex>` configures the seed of the RNG that Miri uses to resolve non-determinism. This
|
||||
* `-Zmiri-seed=<num>` configures the seed of the RNG that Miri uses to resolve non-determinism. This
|
||||
RNG is used to pick base addresses for allocations, to determine preemption and failure of
|
||||
`compare_exchange_weak`, and to control store buffering for weak memory emulation. When isolation
|
||||
is enabled (the default), this is also used to emulate system entropy. The default seed is 0. You
|
||||
|
@ -48,10 +48,10 @@ Update and activate the rustup toolchain 'miri' to the commit given in the
|
||||
`rustup-toolchain-install-master` must be installed for this to work. Any extra
|
||||
flags are passed to `rustup-toolchain-install-master`.
|
||||
|
||||
./miri rustc-pull:
|
||||
Pull and merge Miri changes from the rustc repo. The fetched commit is stored in
|
||||
the `rust-version` file, so the next `./miri toolchain` will install the rustc
|
||||
we just pulled.
|
||||
./miri rustc-pull <commit>:
|
||||
Pull and merge Miri changes from the rustc repo. Defaults to fetching the latest
|
||||
rustc commit. The fetched commit is stored in the `rust-version` file, so the
|
||||
next `./miri toolchain` will install the rustc that just got pulled.
|
||||
|
||||
./miri rustc-push <github user> <branch>:
|
||||
Push Miri changes back to the rustc repo. This will pull a copy of the rustc
|
||||
@ -113,18 +113,17 @@ toolchain)
|
||||
;;
|
||||
rustc-pull)
|
||||
cd "$MIRIDIR"
|
||||
FETCH_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
|
||||
# We can't pull from a commit with josh
|
||||
# (https://github.com/josh-project/josh/issues/1034), so we just hope that
|
||||
# nothing gets merged into rustc *during* this pull.
|
||||
git fetch http://localhost:8000/rust-lang/rust.git$JOSH_FILTER.git master
|
||||
# Just verify that `master` didn't move.
|
||||
if [[ $FETCH_COMMIT != $(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1) ]]; then
|
||||
echo "Looks like something got merged into Rust *while we were pulling*. Aborting. Please try again."
|
||||
FETCH_COMMIT="$1"
|
||||
if [ -z "$FETCH_COMMIT" ]; then
|
||||
FETCH_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
|
||||
fi
|
||||
echo "$FETCH_COMMIT" > rust-version # do this *before* merging as merging will fail in case of conflicts
|
||||
# Update rust-version file. As a separate commit, since making it part of
|
||||
# the merge has confused the heck out of josh in the past.
|
||||
echo "$FETCH_COMMIT" > rust-version
|
||||
git commit rust-version -m "Preparing for merge from rustc"
|
||||
# Fetch given rustc commit and note down which one that was
|
||||
git fetch http://localhost:8000/rust-lang/rust.git@$FETCH_COMMIT$JOSH_FILTER.git
|
||||
git merge FETCH_HEAD --no-ff -m "Merge from rustc"
|
||||
git commit rust-version --amend -m "Merge from rustc"
|
||||
exit 0
|
||||
;;
|
||||
rustc-push)
|
||||
@ -157,16 +156,27 @@ rustc-push)
|
||||
fi
|
||||
git fetch https://github.com/rust-lang/rust $BASE
|
||||
git push https://github.com/$USER/rust $BASE:refs/heads/$BRANCH -f
|
||||
echo
|
||||
# Do the actual push.
|
||||
cd "$MIRIDIR"
|
||||
echo "Pushing Miri changes..."
|
||||
git push http://localhost:8000/$USER/rust.git$JOSH_FILTER.git HEAD:$BRANCH
|
||||
exit 0
|
||||
# Do a round-trip check to make sure the push worked as expected.
|
||||
echo
|
||||
git fetch http://localhost:8000/$USER/rust.git@$JOSH_FILTER.git $BRANCH &>/dev/null
|
||||
if [[ $(git rev-parse HEAD) != $(git rev-parse FETCH_HEAD) ]]; then
|
||||
echo "ERROR: Josh created a non-roundtrip push! Do NOT merge this into rustc!"
|
||||
exit 1
|
||||
else
|
||||
echo "Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:"
|
||||
echo " https://github.com/$USER/rust/pull/new/$BRANCH"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
many-seeds)
|
||||
for SEED in $({ echo obase=16; seq 0 255; } | bc); do
|
||||
for SEED in $(seq 0 255); do
|
||||
echo "Trying seed: $SEED"
|
||||
MIRIFLAGS="$MIRIFLAGS -Zmiri-seed=$SEED" $@ || { echo "Failing seed: $SEED"; break; }
|
||||
MIRIFLAGS="$MIRIFLAGS -Zlayout-seed=$SEED -Zmiri-seed=$SEED" $@ || { echo "Failing seed: $SEED"; break; }
|
||||
done
|
||||
exit 0
|
||||
;;
|
||||
|
@ -1 +1 @@
|
||||
101e1822c3e54e63996c8aaa014d55716f3937eb
|
||||
7477c1f4f7d6bef037d523099b240d22aa1b63a0
|
||||
|
@ -394,10 +394,9 @@ fn main() {
|
||||
if miri_config.seed.is_some() {
|
||||
show_error!("Cannot specify -Zmiri-seed multiple times!");
|
||||
}
|
||||
let seed = u64::from_str_radix(param, 16)
|
||||
.unwrap_or_else(|_| show_error!(
|
||||
"-Zmiri-seed should only contain valid hex digits [0-9a-fA-F] and must fit into a u64 (max 16 characters)"
|
||||
));
|
||||
let seed = param.parse::<u64>().unwrap_or_else(|_| {
|
||||
show_error!("-Zmiri-seed must be an integer that fits into u64")
|
||||
});
|
||||
miri_config.seed = Some(seed);
|
||||
} else if let Some(_param) = arg.strip_prefix("-Zmiri-env-exclude=") {
|
||||
show_error!(
|
||||
|
@ -89,6 +89,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
let ptr = this.read_pointer(ptr_op)?;
|
||||
// If this carries no provenance, treat it like an integer.
|
||||
if ptr.provenance.is_none() {
|
||||
// Use actual implementation.
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
if let Ok((alloc_id, _offset, _)) = this.ptr_try_get_alloc_id(ptr) {
|
||||
// Only do anything if we can identify the allocation this goes to.
|
||||
let (_size, cur_align, _kind) = this.get_alloc_info(alloc_id);
|
||||
|
@ -22,21 +22,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.assert_target_os("linux", "clock_gettime");
|
||||
this.assert_target_os_is_unix("clock_gettime");
|
||||
|
||||
let clk_id = this.read_scalar(clk_id_op)?.to_i32()?;
|
||||
|
||||
// Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
|
||||
// Unix epoch, including effects which may cause time to move backwards such as NTP.
|
||||
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
|
||||
// is just specified to be "faster and less precise", so we implement both the same way.
|
||||
let absolute_clocks =
|
||||
[this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?];
|
||||
// The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
|
||||
// never allowed to go backwards. We don't need to do any additonal monotonicity
|
||||
// enforcement because std::time::Instant already guarantees that it is monotonic.
|
||||
let relative_clocks =
|
||||
[this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?];
|
||||
let absolute_clocks;
|
||||
let mut relative_clocks;
|
||||
|
||||
match this.tcx.sess.target.os.as_ref() {
|
||||
"linux" => {
|
||||
// Linux has two main kinds of clocks. REALTIME clocks return the actual time since the
|
||||
// Unix epoch, including effects which may cause time to move backwards such as NTP.
|
||||
// Linux further distinguishes regular and "coarse" clocks, but the "coarse" version
|
||||
// is just specified to be "faster and less precise", so we implement both the same way.
|
||||
absolute_clocks = vec![
|
||||
this.eval_libc_i32("CLOCK_REALTIME")?,
|
||||
this.eval_libc_i32("CLOCK_REALTIME_COARSE")?,
|
||||
];
|
||||
// The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are
|
||||
// never allowed to go backwards. We don't need to do any additonal monotonicity
|
||||
// enforcement because std::time::Instant already guarantees that it is monotonic.
|
||||
relative_clocks = vec![
|
||||
this.eval_libc_i32("CLOCK_MONOTONIC")?,
|
||||
this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?,
|
||||
];
|
||||
}
|
||||
"macos" => {
|
||||
absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?];
|
||||
relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?];
|
||||
// Some clocks only seem to exist in the aarch64 version of the target.
|
||||
if this.tcx.sess.target.arch == "aarch64" {
|
||||
// `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but
|
||||
// that's not really something a program running inside Miri can tell, anyway.
|
||||
// We need to support it because std uses it.
|
||||
relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?);
|
||||
}
|
||||
}
|
||||
target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"),
|
||||
}
|
||||
|
||||
let duration = if absolute_clocks.contains(&clk_id) {
|
||||
this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?;
|
||||
@ -44,6 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
} else if relative_clocks.contains(&clk_id) {
|
||||
this.machine.clock.now().duration_since(this.machine.clock.anchor())
|
||||
} else {
|
||||
// Unsupported clock.
|
||||
let einval = this.eval_libc("EINVAL")?;
|
||||
this.set_last_error(einval)?;
|
||||
return Ok(Scalar::from_i32(-1));
|
||||
|
@ -180,6 +180,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let result = this.gettimeofday(tv, tz)?;
|
||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
||||
}
|
||||
"clock_gettime" => {
|
||||
let [clk_id, tp] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let result = this.clock_gettime(clk_id, tp)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Allocation
|
||||
"posix_memalign" => {
|
||||
|
@ -43,15 +43,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Time related shims
|
||||
"clock_gettime" => {
|
||||
// This is a POSIX function but it has only been tested on linux.
|
||||
let [clk_id, tp] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let result = this.clock_gettime(clk_id, tp)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
||||
// Threading
|
||||
"pthread_condattr_setclock" => {
|
||||
let [attr, clock_id] =
|
||||
|
@ -14,7 +14,6 @@ use rustc_middle::mir::RetagKind;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
layout::{HasParamEnv, LayoutOf},
|
||||
Ty,
|
||||
};
|
||||
use rustc_target::abi::Abi;
|
||||
use rustc_target::abi::Size;
|
||||
@ -983,28 +982,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
|
||||
return visitor.visit_value(place);
|
||||
|
||||
// Determine mutability and whether to add a protector.
|
||||
// Cannot use `builtin_deref` because that reports *immutable* for `Box`,
|
||||
// making it useless.
|
||||
fn qualify(ty: Ty<'_>, kind: RetagKind) -> Option<(RefKind, bool)> {
|
||||
match ty.kind() {
|
||||
// References are simple.
|
||||
ty::Ref(_, _, Mutability::Mut) =>
|
||||
Some((
|
||||
RefKind::Unique { two_phase: kind == RetagKind::TwoPhase },
|
||||
kind == RetagKind::FnEntry,
|
||||
)),
|
||||
ty::Ref(_, _, Mutability::Not) =>
|
||||
Some((RefKind::Shared, kind == RetagKind::FnEntry)),
|
||||
// Raw pointers need to be enabled.
|
||||
ty::RawPtr(tym) if kind == RetagKind::Raw =>
|
||||
Some((RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, false)),
|
||||
// Boxes are handled separately due to that allocator situation,
|
||||
// see the visitor below.
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// The actual visitor.
|
||||
struct RetagVisitor<'ecx, 'mir, 'tcx> {
|
||||
ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
|
||||
@ -1057,34 +1034,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let recurse_for_fields = || {
|
||||
match self.retag_fields {
|
||||
RetagFields::No => false,
|
||||
RetagFields::Yes => true,
|
||||
RetagFields::OnlyScalar => {
|
||||
// Matching `ArgAbi::new` at the time of writing, only fields of
|
||||
// `Scalar` and `ScalarPair` ABI are considered.
|
||||
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
|
||||
// Check the type of this value to see what to do with it (retag, or recurse).
|
||||
match place.layout.ty.kind() {
|
||||
ty::Ref(_, _, mutbl) => {
|
||||
let ref_kind = match mutbl {
|
||||
Mutability::Mut =>
|
||||
RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
|
||||
Mutability::Not => RefKind::Shared,
|
||||
};
|
||||
self.retag_place(
|
||||
place,
|
||||
ref_kind,
|
||||
self.retag_cause,
|
||||
/*protector*/ self.kind == RetagKind::FnEntry,
|
||||
)?;
|
||||
}
|
||||
ty::RawPtr(tym) => {
|
||||
// We definitely do *not* want to recurse into raw pointers -- wide raw
|
||||
// pointers have fields, and for dyn Trait pointees those can have reference
|
||||
// type!
|
||||
if self.kind == RetagKind::Raw {
|
||||
// Raw pointers need to be enabled.
|
||||
self.retag_place(
|
||||
place,
|
||||
RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
|
||||
self.retag_cause,
|
||||
/*protector*/ false,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
_ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
|
||||
// Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
|
||||
// (Yes this means we technically also recursively retag the allocator itself
|
||||
// even if field retagging is not enabled. *shrug*)
|
||||
self.walk_value(place)?;
|
||||
}
|
||||
_ => {
|
||||
// Not a reference/pointer/box. Only recurse if configured appropriately.
|
||||
let recurse = match self.retag_fields {
|
||||
RetagFields::No => false,
|
||||
RetagFields::Yes => true,
|
||||
RetagFields::OnlyScalar => {
|
||||
// Matching `ArgAbi::new` at the time of writing, only fields of
|
||||
// `Scalar` and `ScalarPair` ABI are considered.
|
||||
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
|
||||
}
|
||||
};
|
||||
if recurse {
|
||||
self.walk_value(place)?;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) {
|
||||
self.retag_place(place, ref_kind, self.retag_cause, protector)?;
|
||||
} else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
|
||||
// Wide raw pointers *do* have fields and their types are strange.
|
||||
// vtables have a type like `&[*const (); 3]` or so!
|
||||
// Do *not* recurse into them.
|
||||
// (No need to worry about wide references, those always "qualify". And Boxes
|
||||
// are handles specially by the visitor anyway.)
|
||||
} else if recurse_for_fields()
|
||||
|| place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box())
|
||||
{
|
||||
// Recurse deeper. Need to always recurse for `Box` to even hit `visit_box`.
|
||||
// (Yes this means we technically also recursively retag the allocator itself
|
||||
// even if field retagging is not enabled. *shrug*)
|
||||
self.walk_value(place)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ def test_cargo_miri_test():
|
||||
test("`cargo miri test`",
|
||||
cargo_miri("test"),
|
||||
default_ref, "test.stderr-empty.ref",
|
||||
env={'MIRIFLAGS': "-Zmiri-permissive-provenance -Zmiri-seed=feed"},
|
||||
env={'MIRIFLAGS': "-Zmiri-permissive-provenance -Zmiri-seed=4242"},
|
||||
)
|
||||
test("`cargo miri test` (no isolation, no doctests)",
|
||||
cargo_miri("test") + ["--bins", "--tests"], # no `--lib`, we disabled that in `Cargo.toml`
|
||||
|
@ -181,17 +181,25 @@ fn test_thread_local_errno() {
|
||||
}
|
||||
|
||||
/// Tests whether clock support exists at all
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_clocks() {
|
||||
let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit();
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
let is_error =
|
||||
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
}
|
||||
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
||||
{
|
||||
let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) };
|
||||
assert_eq!(is_error, 0);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_posix_gettimeofday() {
|
||||
@ -293,11 +301,11 @@ fn main() {
|
||||
test_thread_local_errno();
|
||||
|
||||
test_isatty();
|
||||
test_clocks();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
test_posix_fadvise();
|
||||
test_sync_file_range();
|
||||
test_clocks();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,7 @@
|
||||
//@compile-flags: -Zmiri-symbolic-alignment-check
|
||||
#![feature(strict_provenance)]
|
||||
|
||||
use std::ptr;
|
||||
|
||||
fn test_align_offset() {
|
||||
let d = Box::new([0u32; 4]);
|
||||
@ -16,6 +19,9 @@ fn test_align_offset() {
|
||||
assert_eq!(raw.wrapping_offset(2).align_offset(2), 0);
|
||||
assert_eq!(raw.wrapping_offset(2).align_offset(4), 2);
|
||||
assert_eq!(raw.wrapping_offset(2).align_offset(8), usize::MAX); // requested alignment higher than allocation alignment
|
||||
|
||||
let p = ptr::invalid::<()>(1);
|
||||
assert_eq!(p.align_offset(1), 0);
|
||||
}
|
||||
|
||||
fn test_align_to() {
|
||||
|
@ -69,7 +69,7 @@ fn main() {
|
||||
});
|
||||
|
||||
test(Some("align_offset: align is not a power-of-two"), |_old_val| {
|
||||
(0usize as *const u8).align_offset(3);
|
||||
let _ = (0usize as *const u8).align_offset(3);
|
||||
loop {}
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user