Skip to content

Commit d9de72f

Browse files
committed
miri: restrict fn argument punning to Rust ABI
1 parent e1ca4f6 commit d9de72f

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

src/librustc_mir/interpret/terminator.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -182,19 +182,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
182182
}
183183

184184
fn check_argument_compat(
185+
rust_abi: bool,
185186
caller: TyLayout<'tcx>,
186187
callee: TyLayout<'tcx>,
187188
) -> bool {
188189
if caller.ty == callee.ty {
189190
// No question
190191
return true;
191192
}
193+
if !rust_abi {
194+
// Don't risk anything
195+
return false;
196+
}
192197
// Compare layout
193198
match (&caller.abi, &callee.abi) {
199+
// Different valid ranges are okay (once we enforce validity,
200+
// that will take care to make it UB to leave the range, just
201+
// like for transmute).
194202
(layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
195-
// Different valid ranges are okay (once we enforce validity,
196-
// that will take care to make it UB to leave the range, just
197-
// like for transmute).
198203
caller.value == callee.value,
199204
(layout::Abi::ScalarPair(ref caller1, ref caller2),
200205
layout::Abi::ScalarPair(ref callee1, ref callee2)) =>
@@ -207,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
207212
/// Pass a single argument, checking the types for compatibility.
208213
fn pass_argument(
209214
&mut self,
210-
skip_zst: bool,
215+
rust_abi: bool,
211216
caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
212217
callee_arg: PlaceTy<'tcx, M::PointerTag>,
213218
) -> EvalResult<'tcx> {
214-
if skip_zst && callee_arg.layout.is_zst() {
219+
if rust_abi && callee_arg.layout.is_zst() {
215220
// Nothing to do.
216221
trace!("Skipping callee ZST");
217222
return Ok(());
218223
}
219224
let caller_arg = caller_arg.next()
220225
.ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
221-
if skip_zst {
226+
if rust_abi {
222227
debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
223228
}
224229
// Now, check
225-
if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
230+
if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
226231
return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
227232
}
228233
// We allow some transmutes here
@@ -322,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
322327
// Figure out how to pass which arguments.
323328
// We have two iterators: Where the arguments come from,
324329
// and where they go to.
325-
let skip_zst = match caller_abi {
330+
let rust_abi = match caller_abi {
326331
Abi::Rust | Abi::RustCall => true,
327332
_ => false
328333
};
@@ -347,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
347352
};
348353
// Skip ZSTs
349354
let mut caller_iter = caller_args.iter()
350-
.filter(|op| !skip_zst || !op.layout.is_zst())
355+
.filter(|op| !rust_abi || !op.layout.is_zst())
351356
.map(|op| *op);
352357

353358
// Now we have to spread them out across the callee's locals,
@@ -362,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
362367
// Must be a tuple
363368
for i in 0..dest.layout.fields.count() {
364369
let dest = self.place_field(dest, i as u64)?;
365-
self.pass_argument(skip_zst, &mut caller_iter, dest)?;
370+
self.pass_argument(rust_abi, &mut caller_iter, dest)?;
366371
}
367372
} else {
368373
// Normal argument
369-
self.pass_argument(skip_zst, &mut caller_iter, dest)?;
374+
self.pass_argument(rust_abi, &mut caller_iter, dest)?;
370375
}
371376
}
372377
// Now we should have no more caller args
@@ -377,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
377382
// Don't forget to check the return type!
378383
if let Some(caller_ret) = dest {
379384
let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
380-
if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
385+
if !Self::check_argument_compat(
386+
rust_abi,
387+
caller_ret.layout,
388+
callee_ret.layout,
389+
) {
381390
return err!(FunctionRetMismatch(
382391
caller_ret.layout.ty, callee_ret.layout.ty
383392
));

0 commit comments

Comments
 (0)