check alignment of pointers on Ref
This commit is contained in:
parent
f0c8df2291
commit
b1acc130bb
@ -664,6 +664,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Ref(_, _, ref lvalue) => {
|
||||
let src = self.eval_lvalue(lvalue)?;
|
||||
let (ptr, extra) = self.force_allocation(src)?.to_ptr_and_extra();
|
||||
let ty = self.lvalue_ty(lvalue);
|
||||
|
||||
let val = match extra {
|
||||
LvalueExtra::None => Value::ByVal(ptr),
|
||||
@ -673,6 +674,26 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
bug!("attempted to take a reference to an enum downcast lvalue"),
|
||||
};
|
||||
|
||||
// Check alignment and non-NULLness.
|
||||
let (_, align) = self.size_and_align_of_dst(ty, val)?;
|
||||
if ptr.is_ptr() {
|
||||
let ptr = ptr.to_ptr()?;
|
||||
if !ptr.points_to_zst() { // assume ZST pointer to be always fully alignd (and anyway ZST pointers are going to disappear soon)
|
||||
self.memory.check_align(ptr, align, 0)?;
|
||||
}
|
||||
} else {
|
||||
let v = (ptr.to_u128()? % (1 << self.memory.pointer_size())) as u64;
|
||||
if v == 0 {
|
||||
return Err(EvalError::InvalidNullPointerUsage);
|
||||
}
|
||||
if v % align != 0 {
|
||||
return Err(EvalError::AlignmentCheckFailed {
|
||||
has: v % align,
|
||||
required: align,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.write_value(val, dest, dest_ty)?;
|
||||
}
|
||||
|
||||
|
5
tests/compile-fail/int_ptr_cast.rs
Normal file
5
tests/compile-fail/int_ptr_cast.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let x = 2usize as *const u32;
|
||||
// This must fail because alignment is violated
|
||||
let _ = unsafe { &*x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required
|
||||
}
|
5
tests/compile-fail/int_ptr_cast2.rs
Normal file
5
tests/compile-fail/int_ptr_cast2.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let x = 0usize as *const u32;
|
||||
// This must fail because the pointer is NULL
|
||||
let _ = unsafe { &*x }; //~ ERROR: invalid use of NULL pointer
|
||||
}
|
@ -11,6 +11,6 @@ fn main() {
|
||||
x: 42,
|
||||
y: 99,
|
||||
};
|
||||
let p = &foo.x;
|
||||
let i = *p; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
}
|
||||
let p = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
let i = *p;
|
||||
}
|
||||
|
@ -11,6 +11,6 @@ fn main() {
|
||||
x: 42,
|
||||
y: 99,
|
||||
};
|
||||
let p: *const i32 = &foo.x;
|
||||
let x = unsafe { *p + foo.x }; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
let p: *const i32 = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
let x = unsafe { *p + foo.x };
|
||||
}
|
||||
|
6
tests/compile-fail/unaligned_ptr_cast.rs
Normal file
6
tests/compile-fail/unaligned_ptr_cast.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
let x = &2u16;
|
||||
let x = x as *const _ as *const u32;
|
||||
// This must fail because alignment is violated
|
||||
let _ = unsafe { &*x }; //~ ERROR: tried to access memory with alignment 2, but alignment 4 is required
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user