From fe9cd1c98d5ca861986eaf2bc0aaf953a375ca5c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 30 Aug 2018 10:50:13 +0200 Subject: [PATCH 1/3] strictly enforce pointer validity even for zero-sized accesses --- src/intrinsic.rs | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 6847d8e546..f562aec323 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -179,21 +179,17 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let elem_layout = self.layout_of(elem_ty)?; let elem_size = elem_layout.size.bytes(); let count = self.read_scalar(args[2])?.to_usize(&self)?; - if count * elem_size != 0 { - // TODO: We do not even validate alignment for the 0-bytes case. libstd relies on this in vec::IntoIter::next. - // Also see the write_bytes intrinsic. - let elem_align = elem_layout.align; - let src = self.read_scalar(args[0])?.not_undef()?; - let dest = self.read_scalar(args[1])?.not_undef()?; - self.memory.copy( - src, - elem_align, - dest, - elem_align, - Size::from_bytes(count * elem_size), - intrinsic_name.ends_with("_nonoverlapping"), - )?; - } + let elem_align = elem_layout.align; + let src = self.read_scalar(args[0])?.not_undef()?; + let dest = self.read_scalar(args[1])?.not_undef()?; + self.memory.copy( + src, + elem_align, + dest, + elem_align, + Size::from_bytes(count * elem_size), + intrinsic_name.ends_with("_nonoverlapping"), + )?; } "discriminant_value" => { @@ -563,12 +559,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let val_byte = self.read_scalar(args[1])?.to_u8()?; let ptr = self.read_scalar(args[0])?.not_undef()?; let count = self.read_scalar(args[2])?.to_usize(&self)?; - if count > 0 { - // HashMap relies on write_bytes on a NULL ptr with count == 0 to work - // TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic) - self.memory.check_align(ptr, ty_layout.align)?; - self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?; - } + self.memory.check_align(ptr, ty_layout.align)?; + self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?; } name => return err!(Unimplemented(format!("unimplemented intrinsic: {}", name))), From 95eb77c18e8532d490efbedff6424d369b7e83df Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Sep 2018 16:47:37 +0200 Subject: [PATCH 2/3] add some compile-fail tests --- tests/compile-fail/copy_null.rs | 18 ++++++++++++++++++ tests/compile-fail/copy_unaligned.rs | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/compile-fail/copy_null.rs create mode 100644 tests/compile-fail/copy_unaligned.rs diff --git a/tests/compile-fail/copy_null.rs b/tests/compile-fail/copy_null.rs new file mode 100644 index 0000000000..e46e327e61 --- /dev/null +++ b/tests/compile-fail/copy_null.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//error-pattern: invalid use of NULL pointer + +fn main() { + let mut data = [0u16; 4]; + let ptr = &mut data[0] as *mut u16; + // Even copying 0 elements from NULL should error + unsafe { ptr.copy_from(std::ptr::null(), 0); } +} diff --git a/tests/compile-fail/copy_unaligned.rs b/tests/compile-fail/copy_unaligned.rs new file mode 100644 index 0000000000..0f04dc68db --- /dev/null +++ b/tests/compile-fail/copy_unaligned.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//error-pattern: tried to access memory with alignment 1, but alignment 2 is required + +fn main() { + let mut data = [0u16; 8]; + let ptr = (&mut data[0] as *mut u16 as *mut u8).wrapping_add(1) as *mut u16; + // Even copying 0 elements to something unaligned should error + unsafe { ptr.copy_from(&data[5], 0); } +} From c096d3405389089bab4379161a1546094b1db479 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Sep 2018 08:40:17 +0200 Subject: [PATCH 3/3] bump toolchain --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 125ee2d988..60c47a9305 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2018-09-15 +nightly-2018-09-17