Prefer refutable slice patterns over len check + index op
This commit is contained in:
parent
f7400c390b
commit
f46e1624cb
@ -859,14 +859,15 @@ fn can_be_replaced_by_single_child(
|
||||
) -> Option<UniIndex> {
|
||||
let node = self.nodes.get(idx).unwrap();
|
||||
|
||||
let [child_idx] = node.children[..] else { return None };
|
||||
|
||||
// We never want to replace the root node, as it is also kept in `root_ptr_tags`.
|
||||
if node.children.len() != 1 || live.contains(&node.tag) || node.parent.is_none() {
|
||||
if live.contains(&node.tag) || node.parent.is_none() {
|
||||
return None;
|
||||
}
|
||||
// Since protected nodes are never GC'd (see `borrow_tracker::FrameExtra::visit_provenance`),
|
||||
// we know that `node` is not protected because otherwise `live` would
|
||||
// have contained `node.tag`.
|
||||
let child_idx = node.children[0];
|
||||
let child = self.nodes.get(child_idx).unwrap();
|
||||
// Check that for that one child, `can_be_replaced_by_child` holds for the permission
|
||||
// on all locations.
|
||||
|
@ -481,14 +481,14 @@ fn flock(&mut self, fd_num: i32, op: i32) -> InterpResult<'tcx, Scalar> {
|
||||
fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
if args.len() < 2 {
|
||||
let [fd_num, cmd, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for fcntl: got {}, expected at least 2",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
let fd_num = this.read_scalar(&args[0])?.to_i32()?;
|
||||
let cmd = this.read_scalar(&args[1])?.to_i32()?;
|
||||
};
|
||||
let fd_num = this.read_scalar(fd_num)?.to_i32()?;
|
||||
let cmd = this.read_scalar(cmd)?.to_i32()?;
|
||||
|
||||
// We only support getting the flags for a descriptor.
|
||||
if cmd == this.eval_libc_i32("F_GETFD") {
|
||||
@ -508,13 +508,13 @@ fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
|
||||
// because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
|
||||
// differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor,
|
||||
// thus they can share the same implementation here.
|
||||
if args.len() < 3 {
|
||||
let [_, _, start, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for fcntl with cmd=`F_DUPFD`/`F_DUPFD_CLOEXEC`: got {}, expected at least 3",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
let start = this.read_scalar(&args[2])?.to_i32()?;
|
||||
};
|
||||
let start = this.read_scalar(start)?.to_i32()?;
|
||||
|
||||
match this.machine.fds.get(fd_num) {
|
||||
Some(fd) =>
|
||||
|
@ -433,18 +433,18 @@ fn maybe_sync_file(
|
||||
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
|
||||
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
|
||||
if args.len() < 2 {
|
||||
let [path_raw, flag, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `open`: got {}, expected at least 2",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let path_raw = this.read_pointer(&args[0])?;
|
||||
let path_raw = this.read_pointer(path_raw)?;
|
||||
let path = this.read_path_from_c_str(path_raw)?;
|
||||
let flag = this.read_scalar(&args[1])?.to_i32()?;
|
||||
let flag = this.read_scalar(flag)?.to_i32()?;
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
|
||||
|
@ -122,19 +122,19 @@ fn emulate_foreign_item_inner(
|
||||
id if id == sys_getrandom => {
|
||||
// Used by getrandom 0.1
|
||||
// The first argument is the syscall id, so skip over it.
|
||||
if args.len() < 4 {
|
||||
let [_, ptr, len, flags, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `getrandom` syscall: got {}, expected at least 4",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let ptr = this.read_pointer(&args[1])?;
|
||||
let len = this.read_target_usize(&args[2])?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
|
||||
// neither of which have any effect on our current PRNG.
|
||||
// See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
|
||||
let _flags = this.read_scalar(&args[3])?.to_i32()?;
|
||||
let _flags = this.read_scalar(flags)?.to_i32()?;
|
||||
|
||||
this.gen_random(ptr, len)?;
|
||||
this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
|
||||
|
@ -15,19 +15,19 @@ pub fn futex<'tcx>(
|
||||
// may or may not be left out from the `syscall()` call.
|
||||
// Therefore we don't use `check_arg_count` here, but only check for the
|
||||
// number of arguments to fall within a range.
|
||||
if args.len() < 3 {
|
||||
let [addr, op, val, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `futex` syscall: got {}, expected at least 3",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// The first three arguments (after the syscall number itself) are the same to all futex operations:
|
||||
// (int *addr, int op, int val).
|
||||
// We checked above that these definitely exist.
|
||||
let addr = this.read_pointer(&args[0])?;
|
||||
let op = this.read_scalar(&args[1])?.to_i32()?;
|
||||
let val = this.read_scalar(&args[2])?.to_i32()?;
|
||||
let addr = this.read_pointer(addr)?;
|
||||
let op = this.read_scalar(op)?.to_i32()?;
|
||||
let val = this.read_scalar(val)?.to_i32()?;
|
||||
|
||||
// This is a vararg function so we have to bring our own type for this pointer.
|
||||
let addr = this.ptr_to_mplace(addr, this.machine.layouts.i32);
|
||||
@ -55,15 +55,15 @@ pub fn futex<'tcx>(
|
||||
let wait_bitset = op & !futex_realtime == futex_wait_bitset;
|
||||
|
||||
let bitset = if wait_bitset {
|
||||
if args.len() < 6 {
|
||||
let [_, _, _, timeout, uaddr2, bitset, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `futex` syscall with `op=FUTEX_WAIT_BITSET`: got {}, expected at least 6",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
let _timeout = this.read_pointer(&args[3])?;
|
||||
let _uaddr2 = this.read_pointer(&args[4])?;
|
||||
this.read_scalar(&args[5])?.to_u32()?
|
||||
};
|
||||
let _timeout = this.read_pointer(timeout)?;
|
||||
let _uaddr2 = this.read_pointer(uaddr2)?;
|
||||
this.read_scalar(bitset)?.to_u32()?
|
||||
} else {
|
||||
if args.len() < 4 {
|
||||
throw_ub_format!(
|
||||
@ -183,15 +183,15 @@ pub fn futex<'tcx>(
|
||||
// Same as FUTEX_WAKE, but allows you to specify a bitset to select which threads to wake up.
|
||||
op if op == futex_wake || op == futex_wake_bitset => {
|
||||
let bitset = if op == futex_wake_bitset {
|
||||
if args.len() < 6 {
|
||||
let [_, _, _, timeout, uaddr2, bitset, ..] = args else {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `futex` syscall with `op=FUTEX_WAKE_BITSET`: got {}, expected at least 6",
|
||||
args.len()
|
||||
);
|
||||
}
|
||||
let _timeout = this.read_pointer(&args[3])?;
|
||||
let _uaddr2 = this.read_pointer(&args[4])?;
|
||||
this.read_scalar(&args[5])?.to_u32()?
|
||||
};
|
||||
let _timeout = this.read_pointer(timeout)?;
|
||||
let _uaddr2 = this.read_pointer(uaddr2)?;
|
||||
this.read_scalar(bitset)?.to_u32()?
|
||||
} else {
|
||||
u32::MAX
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user