Skip to content

Commit 96baf1c

Browse files
committed
validate raw wide pointers
1 parent 92e75c0 commit 96baf1c

File tree

3 files changed

+131
-68
lines changed

3 files changed

+131
-68
lines changed

src/librustc_mir/interpret/validity.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -379,16 +379,23 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
379379
}
380380
}
381381
ty::RawPtr(..) => {
382+
// Check pointer part.
382383
if self.ref_tracking_for_consts.is_some() {
383384
// Integers/floats in CTFE: For consistency with integers, we do not
384385
// accept undef.
385386
let _ptr = try_validation!(value.to_scalar_ptr(),
386387
"undefined address in raw pointer", self.path);
387-
let _meta = try_validation!(value.to_meta(),
388-
"uninitialized data in raw fat pointer metadata", self.path);
389388
} else {
390389
// Remain consistent with `usize`: Accept anything.
391390
}
391+
392+
// Check metadata.
393+
let meta = try_validation!(value.to_meta(),
394+
"uninitialized data in wide pointer metadata", self.path);
395+
let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?;
396+
if layout.is_unsized() {
397+
self.check_wide_ptr_meta(meta, layout)?;
398+
}
392399
}
393400
_ if ty.is_box() || ty.is_region_ptr() => {
394401
// Handle wide pointers.

src/test/ui/consts/const-eval/union-ub-fat-ptr.rs renamed to src/test/ui/consts/const-eval/ub-wide-ptr.rs

+48-24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-linelength
12
#![allow(unused)]
23
#![allow(const_err)] // make sure we cannot allow away the errors tested here
34

@@ -28,7 +29,9 @@ struct BadSliceRepr {
2829
union SliceTransmute {
2930
repr: SliceRepr,
3031
bad: BadSliceRepr,
32+
addr: usize,
3133
slice: &'static [u8],
34+
raw_slice: *const [u8],
3235
str: &'static str,
3336
my_str: &'static MyStr,
3437
my_slice: &'static MySliceBool,
@@ -59,7 +62,9 @@ union DynTransmute {
5962
repr: DynRepr,
6063
repr2: DynRepr2,
6164
bad: BadDynRepr,
65+
addr: usize,
6266
rust: &'static dyn Trait,
67+
raw_rust: *const dyn Trait,
6368
}
6469

6570
trait Trait {}
@@ -72,39 +77,37 @@ struct MyStr(str);
7277
struct MySlice<T: ?Sized>(bool, T);
7378
type MySliceBool = MySlice<[bool]>;
7479

80+
// # str
7581
// OK
76-
const A: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
82+
const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str};
7783
// bad str
78-
const B: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
84+
const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str};
7985
//~^ ERROR it is undefined behavior to use this value
8086
// bad str
81-
const C: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
87+
const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str};
8288
//~^ ERROR it is undefined behavior to use this value
8389
// bad str in user-defined unsized type
84-
const C2: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
90+
const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str};
8591
//~^ ERROR it is undefined behavior to use this value
8692

87-
// OK
88-
const A2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
89-
// bad slice
90-
const B2: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
93+
// invalid UTF-8
94+
const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
9195
//~^ ERROR it is undefined behavior to use this value
92-
// bad slice
93-
const C3: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
96+
// invalid UTF-8 in user-defined str-like
97+
const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
9498
//~^ ERROR it is undefined behavior to use this value
9599

96-
// bad trait object
97-
const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
98-
//~^ ERROR it is undefined behavior to use this value
99-
// bad trait object
100-
const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
100+
// # slice
101+
// OK
102+
const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice};
103+
// bad slice: length uninit
104+
const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice};
101105
//~^ ERROR it is undefined behavior to use this value
102-
// bad trait object
103-
const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
106+
// bad slice: length too big
107+
const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice};
104108
//~^ ERROR it is undefined behavior to use this value
105-
106-
// bad data *inside* the trait object
107-
const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
109+
// bad slice: length not an int
110+
const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice};
108111
//~^ ERROR it is undefined behavior to use this value
109112

110113
// bad data *inside* the slice
@@ -120,12 +123,33 @@ const I2: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false
120123
const I3: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]);
121124
//~^ ERROR it is undefined behavior to use this value
122125

123-
// invalid UTF-8
124-
const J1: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str };
126+
// # raw slice
127+
const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok
128+
const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw
129+
const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice};
125130
//~^ ERROR it is undefined behavior to use this value
126-
// invalid UTF-8 in user-defined str-like
127-
const J2: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str };
131+
132+
// # trait object
133+
// bad trait object
134+
const D: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust};
135+
//~^ ERROR it is undefined behavior to use this value
136+
// bad trait object
137+
const E: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust};
138+
//~^ ERROR it is undefined behavior to use this value
139+
// bad trait object
140+
const F: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust};
141+
//~^ ERROR it is undefined behavior to use this value
142+
143+
// bad data *inside* the trait object
144+
const G: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl };
145+
//~^ ERROR it is undefined behavior to use this value
146+
147+
// # raw trait object
148+
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust};
149+
//~^ ERROR it is undefined behavior to use this value
150+
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust};
128151
//~^ ERROR it is undefined behavior to use this value
152+
const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw
129153

130154
fn main() {
131155
}

0 commit comments

Comments
 (0)