@@ -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