Skip to content

Commit 0d7ca71

Browse files
authored
Merge pull request #446 from RalfJung/zero-sized-accesses
Strictly enforce pointer validity even for zero-sized accesses
2 parents 63c2a2f + c096d34 commit 0d7ca71

File tree

4 files changed

+50
-22
lines changed

4 files changed

+50
-22
lines changed

rust-toolchain

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2018-09-15
1+
nightly-2018-09-17

src/intrinsic.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -145,21 +145,17 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
145145
let elem_layout = self.layout_of(elem_ty)?;
146146
let elem_size = elem_layout.size.bytes();
147147
let count = self.read_scalar(args[2])?.to_usize(&self)?;
148-
if count * elem_size != 0 {
149-
// TODO: We do not even validate alignment for the 0-bytes case. libstd relies on this in vec::IntoIter::next.
150-
// Also see the write_bytes intrinsic.
151-
let elem_align = elem_layout.align;
152-
let src = self.read_scalar(args[0])?.not_undef()?;
153-
let dest = self.read_scalar(args[1])?.not_undef()?;
154-
self.memory.copy(
155-
src,
156-
elem_align,
157-
dest,
158-
elem_align,
159-
Size::from_bytes(count * elem_size),
160-
intrinsic_name.ends_with("_nonoverlapping"),
161-
)?;
162-
}
148+
let elem_align = elem_layout.align;
149+
let src = self.read_scalar(args[0])?.not_undef()?;
150+
let dest = self.read_scalar(args[1])?.not_undef()?;
151+
self.memory.copy(
152+
src,
153+
elem_align,
154+
dest,
155+
elem_align,
156+
Size::from_bytes(count * elem_size),
157+
intrinsic_name.ends_with("_nonoverlapping"),
158+
)?;
163159
}
164160

165161
"discriminant_value" => {
@@ -436,12 +432,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
436432
let val_byte = self.read_scalar(args[1])?.to_u8()?;
437433
let ptr = self.read_scalar(args[0])?.not_undef()?;
438434
let count = self.read_scalar(args[2])?.to_usize(&self)?;
439-
if count > 0 {
440-
// HashMap relies on write_bytes on a NULL ptr with count == 0 to work
441-
// TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
442-
self.memory.check_align(ptr, ty_layout.align)?;
443-
self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?;
444-
}
435+
self.memory.check_align(ptr, ty_layout.align)?;
436+
self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?;
445437
}
446438

447439
name => return err!(Unimplemented(format!("unimplemented intrinsic: {}", name))),

tests/compile-fail/copy_null.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//error-pattern: invalid use of NULL pointer
12+
13+
fn main() {
14+
let mut data = [0u16; 4];
15+
let ptr = &mut data[0] as *mut u16;
16+
// Even copying 0 elements from NULL should error
17+
unsafe { ptr.copy_from(std::ptr::null(), 0); }
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//error-pattern: tried to access memory with alignment 1, but alignment 2 is required
12+
13+
fn main() {
14+
let mut data = [0u16; 8];
15+
let ptr = (&mut data[0] as *mut u16 as *mut u8).wrapping_add(1) as *mut u16;
16+
// Even copying 0 elements to something unaligned should error
17+
unsafe { ptr.copy_from(&data[5], 0); }
18+
}

0 commit comments

Comments
 (0)