From b1acc130bb96fdce35ab50c0b64a8a6d470ba2a0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Jun 2017 21:01:24 -0700 Subject: [PATCH] check alignment of pointers on Ref --- src/eval_context.rs | 21 +++++++++++++++++++ tests/compile-fail/int_ptr_cast.rs | 5 +++++ tests/compile-fail/int_ptr_cast2.rs | 5 +++++ tests/compile-fail/reference_to_packed.rs | 6 +++--- .../reference_to_packed_unsafe.rs | 4 ++-- tests/compile-fail/unaligned_ptr_cast.rs | 6 ++++++ 6 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 tests/compile-fail/int_ptr_cast.rs create mode 100644 tests/compile-fail/int_ptr_cast2.rs create mode 100644 tests/compile-fail/unaligned_ptr_cast.rs diff --git a/src/eval_context.rs b/src/eval_context.rs index ece2b37209c..c08fb24c03f 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -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)?; } diff --git a/tests/compile-fail/int_ptr_cast.rs b/tests/compile-fail/int_ptr_cast.rs new file mode 100644 index 00000000000..ae5f65a7166 --- /dev/null +++ b/tests/compile-fail/int_ptr_cast.rs @@ -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 +} diff --git a/tests/compile-fail/int_ptr_cast2.rs b/tests/compile-fail/int_ptr_cast2.rs new file mode 100644 index 00000000000..1897066f7bc --- /dev/null +++ b/tests/compile-fail/int_ptr_cast2.rs @@ -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 +} diff --git a/tests/compile-fail/reference_to_packed.rs b/tests/compile-fail/reference_to_packed.rs index 119225f3e36..4cf353298b9 100644 --- a/tests/compile-fail/reference_to_packed.rs +++ b/tests/compile-fail/reference_to_packed.rs @@ -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 -} \ No newline at end of file + let p = &foo.x; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required + let i = *p; +} diff --git a/tests/compile-fail/reference_to_packed_unsafe.rs b/tests/compile-fail/reference_to_packed_unsafe.rs index 5761f23b7dd..b5893cd1019 100644 --- a/tests/compile-fail/reference_to_packed_unsafe.rs +++ b/tests/compile-fail/reference_to_packed_unsafe.rs @@ -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 }; } diff --git a/tests/compile-fail/unaligned_ptr_cast.rs b/tests/compile-fail/unaligned_ptr_cast.rs new file mode 100644 index 00000000000..fcab430f8fc --- /dev/null +++ b/tests/compile-fail/unaligned_ptr_cast.rs @@ -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 +}