Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure that integers cast to pointers will never point at a valid alloc, not even the zst alloc #81

Merged
merged 19 commits into from
Nov 17, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'tcx> Error for EvalError<'tcx> {
EvalError::DanglingPointerDeref =>
"dangling pointer was dereferenced",
EvalError::InvalidFunctionPointer =>
"tried to use a pointer as a function pointer",
"tried to use an integer pointer as a function pointer",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why doesn't this apply to general pointers casted to function pointers any more? The name InvalidFunctionPointer seems too general for the new error message.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oli-obk pinging to make sure you don't miss this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing changed here, the error message was outdated way before this pr, we can adjust the variant name to match that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of error do we actually get when treating a regular pointer as a function pointer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    let b = Box::new(42);
    let g = unsafe {
        std::mem::transmute::<&usize, &fn(i32)>(&b)
    };

    (*g)(42) //~ ERROR tried to use an integer pointer or a dangling pointer as a function pointer

We can't do transmute(42) because primvals panic in some cases right now. I think we should eliminate the expect functions and have the try functions return an EvalResult instead.

  10:     0x55e4c4ab7a18 - <core::option::Option<T>>::expect::hda65b98614e3f1e8
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libcore/option.rs:293
  11:     0x55e4c4bf53c3 - miri::primval::PrimVal::expect_fn_ptr::h87524394959696a3
                        at /home/ws/ca8159/Projects/rust/miri/src/primval.rs:198
  12:     0x55e4c4ba9ae7 - miri::interpreter::terminator::<impl miri::interpreter::EvalContext<'a, 'tcx>>::eval_terminator::h1e9da0fab75dcb3c
                        at /home/ws/ca8159/Projects/rust/miri/src/interpreter/terminator/mod.rs:88
  13:     0x55e4c4b960c5 - miri::interpreter::step::<impl miri::interpreter::EvalContext<'a, 'tcx>>::terminator::h0a43b45ccf9ebe32
                        at /home/ws/ca8159/Projects/rust/miri/src/interpreter/step.rs:98
  14:     0x55e4c4b95659 - miri::interpreter::step::<impl miri::interpreter::EvalContext<'a, 'tcx>>::step::ha153e9fdef721ba9
                        at /home/ws/ca8159/Projects/rust/miri/src/interpreter/step.rs:69
  15:     0x55e4c4be5fb8 - miri::interpreter::eval_main::h502fc7147a3a0d58
                        at /home/ws/ca8159/Projects/rust/miri/src/interpreter/mod.rs:1664
  16:     0x55e4c4a8c843 - <miri::MiriCompilerCalls as rustc_driver::CompilerCalls<'a>>::build_controller::{{closure}}::h01b87c9edeea1ee3
                        at /home/ws/ca8159/Projects/rust/miri/src/bin/miri.rs:72

EvalError::InvalidBool =>
"invalid boolean value read",
EvalError::InvalidDiscriminant =>
Expand Down
49 changes: 26 additions & 23 deletions src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
ty: Ty<'tcx>,
substs: &'tcx Substs<'tcx>
) -> EvalResult<'tcx, Pointer> {
let size = self.type_size_with_substs(ty, substs);
let size = self.type_size_with_substs(ty, substs).expect("cannot alloc memory for unsized type");
let align = self.type_align_with_substs(ty, substs);
self.memory.allocate(size, align)
}
Expand All @@ -203,10 +203,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
PrimVal::from_uint_with_size(n, self.memory.pointer_size())
}

fn isize_primval(&self, n: i64) -> PrimVal {
PrimVal::from_int_with_size(n, self.memory.pointer_size())
}

fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
// FIXME: cache these allocs
let ptr = self.memory.allocate(s.len(), 1)?;
Expand Down Expand Up @@ -290,16 +286,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.tcx.normalize_associated_type(&substituted)
}

fn type_size(&self, ty: Ty<'tcx>) -> usize {
fn type_size(&self, ty: Ty<'tcx>) -> Option<usize> {
self.type_size_with_substs(ty, self.substs())
}

fn type_align(&self, ty: Ty<'tcx>) -> usize {
self.type_align_with_substs(ty, self.substs())
}

fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
self.type_layout_with_substs(ty, substs).size(&self.tcx.data_layout).bytes() as usize
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> Option<usize> {
let layout = self.type_layout_with_substs(ty, substs);
if layout.is_unsized() {
None
} else {
Some(layout.size(&self.tcx.data_layout).bytes() as usize)
}
}

fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
Expand Down Expand Up @@ -480,7 +481,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

Array { .. } => {
let elem_size = match dest_ty.sty {
ty::TyArray(elem_ty, _) => self.type_size(elem_ty) as u64,
ty::TyArray(elem_ty, _) => self.type_size(elem_ty).expect("array elements are sized") as u64,
_ => bug!("tried to assign {:?} to non-array type {:?}", kind, dest_ty),
};
let offsets = (0..).map(|i| i * elem_size);
Expand Down Expand Up @@ -518,7 +519,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.write_value(value, dest, value_ty)?;
} else {
assert_eq!(operands.len(), 0);
let zero = self.isize_primval(0);
let value_size = self.type_size(dest_ty).expect("pointer types are sized");
let zero = PrimVal::from_int_with_size(0, value_size);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? I think we can assume isize is pointer sized, and isize_primval does mean the target isize.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want an isize here. The rawnullablepointer opt also happens for nonpointers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, right, for NonZero things that aren't pointer-sized? I hate the RawNullablePointer names in layout...

self.write_primval(dest, zero)?;
}
} else {
Expand All @@ -534,15 +536,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
} else {
for operand in operands {
let operand_ty = self.operand_ty(operand);
assert_eq!(self.type_size(operand_ty), 0);
assert_eq!(self.type_size(operand_ty), Some(0));
}
let offset = self.nonnull_offset(dest_ty, nndiscr, discrfield)?;
let (offset, ty) = self.nonnull_offset_and_ty(dest_ty, nndiscr, discrfield)?;

// FIXME(solson)
let dest = self.force_allocation(dest)?.to_ptr();

let dest = dest.offset(offset.bytes() as isize);
try!(self.memory.write_isize(dest, 0));
let dest_size = self.type_size(ty).unwrap_or(self.memory.pointer_size());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what cases can this default to self.memory.pointer_size()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the unsized case. Since any unsized value is a pointer to the actual sized value and this optimization only cares about the pointer part, not the extra part

Copy link
Member

@solson solson Nov 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What unsized case? ty is the type of the non-zero field that is used for the discriminant in this optimization, right? How can that field be unsized?

EDIT: Nevermind, I now see the conversation lower down; let's continue there.

try!(self.memory.write_int(dest, 0, dest_size));
}
} else {
bug!("tried to assign {:?} to Layout::RawNullablePointer", kind);
Expand Down Expand Up @@ -576,7 +579,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
ty::TyArray(elem_ty, n) => (elem_ty, n),
_ => bug!("tried to assign array-repeat to non-array type {:?}", dest_ty),
};
let elem_size = self.type_size(elem_ty);
let elem_size = self.type_size(elem_ty).expect("repeat element type must be sized");
let value = self.eval_operand(operand)?;

// FIXME(solson)
Expand Down Expand Up @@ -689,7 +692,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}

fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<'tcx, Size> {
fn nonnull_offset_and_ty(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<'tcx, (Size, Ty<'tcx>)> {
// Skip the constant 0 at the start meant for LLVM GEP.
let mut path = discrfield.iter().skip(1).map(|&i| i as usize);

Expand All @@ -704,10 +707,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
_ => bug!("non-enum for StructWrappedNullablePointer: {}", ty),
};

self.field_path_offset(inner_ty, path)
self.field_path_offset_and_ty(inner_ty, path)
}

fn field_path_offset<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult<'tcx, Size> {
fn field_path_offset_and_ty<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult<'tcx, (Size, Ty<'tcx>)> {
let mut offset = Size::from_bytes(0);

// Skip the initial 0 intended for LLVM GEP.
Expand All @@ -717,7 +720,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
offset = offset.checked_add(field_offset, &self.tcx.data_layout).unwrap();
}

Ok(offset)
Ok((offset, ty))
}

fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, Ty<'tcx>> {
Expand Down Expand Up @@ -991,7 +994,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let (base_ptr, _) = base.to_ptr_and_extra();

let (elem_ty, len) = base.elem_ty_and_len(base_ty);
let elem_size = self.type_size(elem_ty);
let elem_size = self.type_size(elem_ty).expect("slice element must be sized");
let n_ptr = self.eval_operand(operand)?;
let usize = self.tcx.types.usize;
let n = self.value_to_primval(n_ptr, usize)?
Expand All @@ -1007,7 +1010,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let (base_ptr, _) = base.to_ptr_and_extra();

let (elem_ty, n) = base.elem_ty_and_len(base_ty);
let elem_size = self.type_size(elem_ty);
let elem_size = self.type_size(elem_ty).expect("sequence element must be sized");
assert!(n >= min_length as u64);

let index = if from_end {
Expand All @@ -1026,7 +1029,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let (base_ptr, _) = base.to_ptr_and_extra();

let (elem_ty, n) = base.elem_ty_and_len(base_ty);
let elem_size = self.type_size(elem_ty);
let elem_size = self.type_size(elem_ty).expect("slice element must be sized");
assert!((from as u64) <= n - (to as u64));
let ptr = base_ptr.offset(from as isize * elem_size as isize);
let extra = LvalueExtra::Length(n - to as u64 - from as u64);
Expand All @@ -1046,7 +1049,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}

fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, ()> {
let size = self.type_size(ty);
let size = self.type_size(ty).expect("cannot copy from an unsized type");
let align = self.type_align(ty);
self.memory.copy(src, dest, size, align)?;
Ok(())
Expand Down Expand Up @@ -1512,7 +1515,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
for (i, (src_f, dst_f)) in iter {
let src_fty = monomorphize_field_ty(self.tcx, src_f, substs_a);
let dst_fty = monomorphize_field_ty(self.tcx, dst_f, substs_b);
if self.type_size(dst_fty) == 0 {
if self.type_size(dst_fty) == Some(0) {
continue;
}
let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize;
Expand Down
16 changes: 10 additions & 6 deletions src/interpreter/terminator/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
"copy_nonoverlapping" => {
// FIXME: check whether overlapping occurs
let elem_ty = substs.type_at(0);
let elem_size = self.type_size(elem_ty);
let elem_size = self.type_size(elem_ty).expect("cannot copy unsized value");
let elem_align = self.type_align(elem_ty);
let src = arg_vals[0].read_ptr(&self.memory)?;
let dest = arg_vals[1].read_ptr(&self.memory)?;
Expand Down Expand Up @@ -230,7 +230,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

"offset" => {
let pointee_ty = substs.type_at(0);
let pointee_size = self.type_size(pointee_ty) as isize;
let pointee_size = self.type_size(pointee_ty).expect("cannot offset a pointer to an unsized type") as isize;
let offset = self.value_to_primval(arg_vals[1], isize)?
.expect_int("offset second arg not isize");

Expand Down Expand Up @@ -281,7 +281,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

"size_of" => {
let ty = substs.type_at(0);
let size = self.type_size(ty) as u64;
// FIXME: change the `box_free` lang item to take `T: ?Sized` and have it use the
// `size_of_val` intrinsic, then change this back to
// .expect("size_of intrinsic called on unsized value")
// see https://github.com/rust-lang/rust/pull/37708
let size = self.type_size(ty).unwrap_or(!0) as u64;
let size_val = self.usize_primval(size);
self.write_primval(dest, size_val)?;
}
Expand Down Expand Up @@ -360,8 +364,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
value: Value,
) -> EvalResult<'tcx, (u64, u64)> {
let pointer_size = self.memory.pointer_size();
if self.type_is_sized(ty) {
Ok((self.type_size(ty) as u64, self.type_align(ty) as u64))
if let Some(size) = self.type_size(ty) {
Ok((size as u64, self.type_align(ty) as u64))
} else {
match ty.sty {
ty::TyAdt(def, substs) => {
Expand Down Expand Up @@ -435,7 +439,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

ty::TySlice(_) | ty::TyStr => {
let elem_ty = ty.sequence_element_type(self.tcx);
let elem_size = self.type_size(elem_ty) as u64;
let elem_size = self.type_size(elem_ty).expect("slice element must be sized") as u64;
let len = value.expect_slice_len(&self.memory)?;
let align = self.type_align(elem_ty);
Ok((len * elem_size, align as u64))
Expand Down
23 changes: 13 additions & 10 deletions src/interpreter/terminator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

Abi::C => {
let ty = fn_ty.sig.0.output;
let size = self.type_size(ty);
let size = self.type_size(ty).expect("function return type cannot be unsized");
let (ret, target) = destination.unwrap();
self.call_c_abi(def_id, arg_operands, ret, size)?;
self.goto_block(target);
Expand Down Expand Up @@ -263,14 +263,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.memory.read_int(adt_ptr, discr_size as usize)? as u64
}

RawNullablePointer { nndiscr, .. } => {
self.read_nonnull_discriminant_value(adt_ptr, nndiscr)?
RawNullablePointer { nndiscr, value } => {
let discr_size = value.size(&self.tcx.data_layout).bytes() as usize;
self.read_nonnull_discriminant_value(adt_ptr, nndiscr, discr_size)?
}

StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
let offset = self.nonnull_offset(adt_ty, nndiscr, discrfield)?;
let (offset, ty) = self.nonnull_offset_and_ty(adt_ty, nndiscr, discrfield)?;
let nonnull = adt_ptr.offset(offset.bytes() as isize);
self.read_nonnull_discriminant_value(nonnull, nndiscr)?
// only the pointer part of a fat pointer is used for this space optimization
let discr_size = self.type_size(ty).unwrap_or(self.memory.pointer_size());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here. When can the nonnull field be a unsized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be, but the MIR ends up giving us an index path that will give us the first field of the fat pointer, which ends up being te unsized value. Not sure if the code giving us the type path is wrong or if this is intended. I'll check and get back to you

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first field of the fat pointer is the thin data pointer. This is a GEP field path, it will not deref nested pointers, just offset into a flat structure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It sounds like we'd need to adjust the type, then, to match @eddyb's point. Alternately, maybe it can return the size instead of the type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

self.read_nonnull_discriminant_value(nonnull, nndiscr, discr_size)?
}

// The discriminant_value intrinsic returns 0 for non-sum types.
Expand All @@ -281,8 +284,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Ok(discr_val)
}

fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64) -> EvalResult<'tcx, u64> {
let not_null = match self.memory.read_usize(ptr) {
fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64, discr_size: usize) -> EvalResult<'tcx, u64> {
let not_null = match self.memory.read_uint(ptr, discr_size) {
Ok(0) => false,
Ok(_) | Err(EvalError::ReadPointerAsBytes) => true,
Err(e) => return Err(e),
Expand Down Expand Up @@ -639,7 +642,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
};
let drop_fn = self.memory.read_ptr(vtable)?;
// some values don't need to call a drop impl, so the value is null
if !drop_fn.points_to_zst() {
if drop_fn != Pointer::from_int(0) {
let (def_id, substs, ty) = self.memory.get_fn(drop_fn.alloc_id)?;
let fn_sig = self.tcx.erase_late_bound_regions_and_normalize(&ty.sig);
let real_ty = fn_sig.inputs[0];
Expand All @@ -655,7 +658,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => (ptr, len as isize),
_ => bug!("expected an lvalue with a length"),
};
let size = self.type_size(elem_ty) as isize;
let size = self.type_size(elem_ty).expect("slice element must be sized") as isize;
// FIXME: this creates a lot of stack frames if the element type has
// a drop impl
for i in 0..len {
Expand All @@ -668,7 +671,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Lvalue::Ptr { ptr, extra } => (ptr, extra),
_ => bug!("expected an lvalue with optional extra data"),
};
let size = self.type_size(elem_ty) as isize;
let size = self.type_size(elem_ty).expect("array element cannot be unsized") as isize;
// FIXME: this creates a lot of stack frames if the element type has
// a drop impl
for i in 0..len {
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}).collect();

let size = self.type_size(trait_ref.self_ty());
let size = self.type_size(trait_ref.self_ty()).expect("can't create a vtable for an unsized type");
let align = self.type_align(trait_ref.self_ty());

let ptr_size = self.memory.pointer_size();
Expand Down
8 changes: 4 additions & 4 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Pointer {
// FIXME(solson): Integer pointers should use u64, not usize. Target pointers can be larger
// than host usize.
pub fn from_int(i: usize) -> Self {
Pointer::new(ZST_ALLOC_ID, i)
Pointer::new(NEVER_ALLOC_ID, i)
Copy link
Contributor Author

@oli-obk oli-obk Nov 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I did this change to fix the assume bug, which then caused drop impls to fail: https://github.com/solson/miri/pull/81/files#diff-8f4a840e817b018e1d74153888641b27L642 and int to pointer cast error messages to show up as dangling pointers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine. I might have a plan to refactor Pointer::from_int out of existence, but I haven't taken a close enough look yet.

}

pub fn zst_ptr() -> Self {
Expand Down Expand Up @@ -290,7 +290,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
Some(alloc) => Ok(alloc),
None => match self.functions.get(&id) {
Some(_) => Err(EvalError::DerefFunctionPointer),
None if id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess),
None if id == NEVER_ALLOC_ID || id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess),
None => Err(EvalError::DanglingPointerDeref),
}
}
Expand All @@ -302,7 +302,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
Some(alloc) => Ok(alloc),
None => match self.functions.get(&id) {
Some(_) => Err(EvalError::DerefFunctionPointer),
None if id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess),
None if id == NEVER_ALLOC_ID || id == ZST_ALLOC_ID => Err(EvalError::InvalidMemoryAccess),
None => Err(EvalError::DanglingPointerDeref),
}
}
Expand Down Expand Up @@ -570,7 +570,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
2 => Ok(self.layout.i16_align.abi() as usize),
4 => Ok(self.layout.i32_align.abi() as usize),
8 => Ok(self.layout.i64_align.abi() as usize),
_ => bug!("bad integer size"),
_ => bug!("bad integer size: {}", size),
}
}

Expand Down
3 changes: 3 additions & 0 deletions tests/run-pass/assume_bug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
vec![()].into_iter();
}
14 changes: 14 additions & 0 deletions tests/run-pass/small_enum_size_bug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#![allow(dead_code)]

enum E {
A = 1,
B = 2,
C = 3,
}

fn main() {
let enone = None::<E>;
if let Some(..) = enone {
panic!();
}
}