Skip to content

Commit

Permalink
miri: restrict fn argument punning to Rust ABI
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Nov 22, 2018
1 parent e1ca4f6 commit d9de72f
Showing 1 changed file with 21 additions and 12 deletions.
33 changes: 21 additions & 12 deletions src/librustc_mir/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}

fn check_argument_compat(
rust_abi: bool,
caller: TyLayout<'tcx>,
callee: TyLayout<'tcx>,
) -> bool {
if caller.ty == callee.ty {
// No question
return true;
}
if !rust_abi {
// Don't risk anything
return false;
}
// Compare layout
match (&caller.abi, &callee.abi) {
// Different valid ranges are okay (once we enforce validity,
// that will take care to make it UB to leave the range, just
// like for transmute).
(layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
// Different valid ranges are okay (once we enforce validity,
// that will take care to make it UB to leave the range, just
// like for transmute).
caller.value == callee.value,
(layout::Abi::ScalarPair(ref caller1, ref caller2),
layout::Abi::ScalarPair(ref callee1, ref callee2)) =>
Expand All @@ -207,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
/// Pass a single argument, checking the types for compatibility.
fn pass_argument(
&mut self,
skip_zst: bool,
rust_abi: bool,
caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
callee_arg: PlaceTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx> {
if skip_zst && callee_arg.layout.is_zst() {
if rust_abi && callee_arg.layout.is_zst() {
// Nothing to do.
trace!("Skipping callee ZST");
return Ok(());
}
let caller_arg = caller_arg.next()
.ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
if skip_zst {
if rust_abi {
debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
}
// Now, check
if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
}
// We allow some transmutes here
Expand Down Expand Up @@ -322,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// Figure out how to pass which arguments.
// We have two iterators: Where the arguments come from,
// and where they go to.
let skip_zst = match caller_abi {
let rust_abi = match caller_abi {
Abi::Rust | Abi::RustCall => true,
_ => false
};
Expand All @@ -347,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
};
// Skip ZSTs
let mut caller_iter = caller_args.iter()
.filter(|op| !skip_zst || !op.layout.is_zst())
.filter(|op| !rust_abi || !op.layout.is_zst())
.map(|op| *op);

// Now we have to spread them out across the callee's locals,
Expand All @@ -362,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// Must be a tuple
for i in 0..dest.layout.fields.count() {
let dest = self.place_field(dest, i as u64)?;
self.pass_argument(skip_zst, &mut caller_iter, dest)?;
self.pass_argument(rust_abi, &mut caller_iter, dest)?;
}
} else {
// Normal argument
self.pass_argument(skip_zst, &mut caller_iter, dest)?;
self.pass_argument(rust_abi, &mut caller_iter, dest)?;
}
}
// Now we should have no more caller args
Expand All @@ -377,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
// Don't forget to check the return type!
if let Some(caller_ret) = dest {
let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
if !Self::check_argument_compat(
rust_abi,
caller_ret.layout,
callee_ret.layout,
) {
return err!(FunctionRetMismatch(
caller_ret.layout.ty, callee_ret.layout.ty
));
Expand Down

0 comments on commit d9de72f

Please sign in to comment.