Skip to content

Commit c3d392f

Browse files
committed
fix validating fat raw pointers
1 parent 49999e9 commit c3d392f

File tree

1 file changed

+25
-18
lines changed

1 file changed

+25
-18
lines changed

src/librustc_mir/interpret/validity.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
226226
// Validate all fields
227227
match dest.layout.fields {
228228
// primitives are unions with zero fields
229+
// FIXME: Use some other indicator instead, like `layout.abi`.
229230
layout::FieldPlacement::Union(0) => {
230231
match dest.layout.abi {
231232
// nothing to do, whatever the pointer points to, it is never going to be read
@@ -277,41 +278,47 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
277278
}
278279
},
279280
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
280-
// fat pointers need special treatment
281-
match dest.layout.ty.builtin_deref(false).map(|tam| &tam.ty.sty) {
281+
// Fat pointers need special treatment.
282+
match dest.layout.ty.builtin_deref(true).map(|tam| &tam.ty.sty) {
282283
| Some(ty::TyStr)
283284
| Some(ty::TySlice(_)) => {
284-
// check the length (for nicer error messages)
285+
// check the length (for nicer error messages); must be valid even
286+
// for a raw pointer.
285287
let len_mplace = self.mplace_field(dest, 1)?;
286288
let len = self.read_scalar(len_mplace.into())?;
287289
let len = match len.to_bits(len_mplace.layout.size) {
288290
Err(_) => return validation_failure!("length is not a valid integer", path),
289291
Ok(len) => len as u64,
290292
};
291-
// get the fat ptr, and recursively check it
292-
let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
293-
assert_eq!(ptr.extra, PlaceExtra::Length(len));
294-
let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
295-
if seen.insert(unpacked_ptr) {
296-
todo.push((unpacked_ptr, path_clone_and_deref(path)));
293+
// for safe ptrs, get the fat ptr, and recursively check it
294+
if !dest.layout.ty.is_unsafe_ptr() {
295+
let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
296+
assert_eq!(ptr.extra, PlaceExtra::Length(len));
297+
let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
298+
if seen.insert(unpacked_ptr) {
299+
todo.push((unpacked_ptr, path_clone_and_deref(path)));
300+
}
297301
}
298302
},
299303
Some(ty::TyDynamic(..)) => {
300-
// check the vtable (for nicer error messages)
304+
// check the vtable (for nicer error messages); must be valid even for a
305+
// raw ptr.
301306
let vtable = self.read_scalar(self.mplace_field(dest, 1)?.into())?;
302307
let vtable = match vtable.to_ptr() {
303308
Err(_) => return validation_failure!("vtable address is not a pointer", path),
304309
Ok(vtable) => vtable,
305310
};
306-
// get the fat ptr, and recursively check it
307-
let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
308-
assert_eq!(ptr.extra, PlaceExtra::Vtable(vtable));
309-
let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
310-
if seen.insert(unpacked_ptr) {
311-
todo.push((unpacked_ptr, path_clone_and_deref(path)));
311+
// for safe ptrs, get the fat ptr, and recursively check it
312+
if !dest.layout.ty.is_unsafe_ptr() {
313+
let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
314+
assert_eq!(ptr.extra, PlaceExtra::Vtable(vtable));
315+
let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
316+
if seen.insert(unpacked_ptr) {
317+
todo.push((unpacked_ptr, path_clone_and_deref(path)));
318+
}
319+
// FIXME: More checks for the vtable... making sure it is exactly
320+
// the one one would expect for this type.
312321
}
313-
// FIXME: More checks for the vtable... making sure it is exactly
314-
// the one one would expect for this type.
315322
},
316323
Some(ty) =>
317324
bug!("Unexpected fat pointer target type {:?}", ty),

0 commit comments

Comments
 (0)