@@ -226,6 +226,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
226
226
// Validate all fields
227
227
match dest. layout . fields {
228
228
// primitives are unions with zero fields
229
+ // FIXME: Use some other indicator instead, like `layout.abi`.
229
230
layout:: FieldPlacement :: Union ( 0 ) => {
230
231
match dest. layout . abi {
231
232
// 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> {
277
278
}
278
279
} ,
279
280
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 ) {
282
283
| Some ( ty:: TyStr )
283
284
| 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.
285
287
let len_mplace = self . mplace_field ( dest, 1 ) ?;
286
288
let len = self . read_scalar ( len_mplace. into ( ) ) ?;
287
289
let len = match len. to_bits ( len_mplace. layout . size ) {
288
290
Err ( _) => return validation_failure ! ( "length is not a valid integer" , path) ,
289
291
Ok ( len) => len as u64 ,
290
292
} ;
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
+ }
297
301
}
298
302
} ,
299
303
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.
301
306
let vtable = self . read_scalar ( self . mplace_field ( dest, 1 ) ?. into ( ) ) ?;
302
307
let vtable = match vtable. to_ptr ( ) {
303
308
Err ( _) => return validation_failure ! ( "vtable address is not a pointer" , path) ,
304
309
Ok ( vtable) => vtable,
305
310
} ;
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.
312
321
}
313
- // FIXME: More checks for the vtable... making sure it is exactly
314
- // the one one would expect for this type.
315
322
} ,
316
323
Some ( ty) =>
317
324
bug ! ( "Unexpected fat pointer target type {:?}" , ty) ,
0 commit comments