@@ -11,7 +11,7 @@ use std::hash::Hash;
1111
1212use super :: {
1313 GlobalAlloc , InterpResult ,
14- OpTy , Machine , InterpCx , ValueVisitor , MPlaceTy ,
14+ Scalar , OpTy , Machine , InterpCx , ValueVisitor , MPlaceTy ,
1515} ;
1616
1717macro_rules! throw_validation_failure {
@@ -250,6 +250,47 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
250250 self . path . truncate ( path_len) ;
251251 Ok ( ( ) )
252252 }
253+
254+ fn check_wide_ptr_meta (
255+ & mut self ,
256+ meta : Option < Scalar < M :: PointerTag > > ,
257+ pointee : TyLayout < ' tcx > ,
258+ ) -> InterpResult < ' tcx > {
259+ let tail = self . ecx . tcx . struct_tail_erasing_lifetimes ( pointee. ty , self . ecx . param_env ) ;
260+ match tail. sty {
261+ ty:: Dynamic ( ..) => {
262+ let vtable = meta. unwrap ( ) ;
263+ try_validation ! (
264+ self . ecx. memory. check_ptr_access(
265+ vtable,
266+ 3 * self . ecx. tcx. data_layout. pointer_size, // drop, size, align
267+ self . ecx. tcx. data_layout. pointer_align. abi,
268+ ) ,
269+ "dangling or unaligned vtable pointer in wide pointer or too small vtable" ,
270+ self . path
271+ ) ;
272+ try_validation ! ( self . ecx. read_drop_type_from_vtable( vtable) ,
273+ "invalid drop fn in vtable" , self . path) ;
274+ try_validation ! ( self . ecx. read_size_and_align_from_vtable( vtable) ,
275+ "invalid size or align in vtable" , self . path) ;
276+ // FIXME: More checks for the vtable.
277+ }
278+ ty:: Slice ( ..) | ty:: Str => {
279+ let _len = try_validation ! ( meta. unwrap( ) . to_usize( self . ecx) ,
280+ "non-integer slice length in wide pointer" , self . path) ;
281+ // We do not check that `len * elem_size <= isize::MAX`:
282+ // that is only required for references, and there it falls out of the
283+ // "dereferencable" check performed by Stacked Borrows.
284+ }
285+ ty:: Foreign ( ..) => {
286+ // Unsized, but not wide.
287+ }
288+ _ =>
289+ bug ! ( "Unexpected unsized type tail: {:?}" , tail) ,
290+ }
291+
292+ Ok ( ( ) )
293+ }
253294}
254295
255296impl < ' rt , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > ValueVisitor < ' mir , ' tcx , M >
@@ -341,56 +382,34 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
341382 }
342383 }
343384 ty:: RawPtr ( ..) => {
385+ // Check pointer part.
344386 if self . ref_tracking_for_consts . is_some ( ) {
345387 // Integers/floats in CTFE: For consistency with integers, we do not
346388 // accept undef.
347389 let _ptr = try_validation ! ( value. to_scalar_ptr( ) ,
348390 "undefined address in raw pointer" , self . path) ;
349- let _meta = try_validation ! ( value. to_meta( ) ,
350- "uninitialized data in raw fat pointer metadata" , self . path) ;
351391 } else {
352392 // Remain consistent with `usize`: Accept anything.
353393 }
394+
395+ // Check metadata.
396+ let meta = try_validation ! ( value. to_meta( ) ,
397+ "uninitialized data in wide pointer metadata" , self . path) ;
398+ let layout = self . ecx . layout_of ( value. layout . ty . builtin_deref ( true ) . unwrap ( ) . ty ) ?;
399+ if layout. is_unsized ( ) {
400+ self . check_wide_ptr_meta ( meta, layout) ?;
401+ }
354402 }
355403 _ if ty. is_box ( ) || ty. is_region_ptr ( ) => {
356- // Handle fat pointers.
404+ // Handle wide pointers.
357405 // Check metadata early, for better diagnostics
358406 let ptr = try_validation ! ( value. to_scalar_ptr( ) ,
359407 "undefined address in pointer" , self . path) ;
360408 let meta = try_validation ! ( value. to_meta( ) ,
361- "uninitialized data in fat pointer metadata" , self . path) ;
409+ "uninitialized data in wide pointer metadata" , self . path) ;
362410 let layout = self . ecx . layout_of ( value. layout . ty . builtin_deref ( true ) . unwrap ( ) . ty ) ?;
363411 if layout. is_unsized ( ) {
364- let tail = self . ecx . tcx . struct_tail_erasing_lifetimes ( layout. ty ,
365- self . ecx . param_env ) ;
366- match tail. sty {
367- ty:: Dynamic ( ..) => {
368- let vtable = meta. unwrap ( ) ;
369- try_validation ! (
370- self . ecx. memory. check_ptr_access(
371- vtable,
372- 3 * self . ecx. tcx. data_layout. pointer_size, // drop, size, align
373- self . ecx. tcx. data_layout. pointer_align. abi,
374- ) ,
375- "dangling or unaligned vtable pointer or too small vtable" ,
376- self . path
377- ) ;
378- try_validation ! ( self . ecx. read_drop_type_from_vtable( vtable) ,
379- "invalid drop fn in vtable" , self . path) ;
380- try_validation ! ( self . ecx. read_size_and_align_from_vtable( vtable) ,
381- "invalid size or align in vtable" , self . path) ;
382- // FIXME: More checks for the vtable.
383- }
384- ty:: Slice ( ..) | ty:: Str => {
385- try_validation ! ( meta. unwrap( ) . to_usize( self . ecx) ,
386- "non-integer slice length in fat pointer" , self . path) ;
387- }
388- ty:: Foreign ( ..) => {
389- // Unsized, but not fat.
390- }
391- _ =>
392- bug ! ( "Unexpected unsized type tail: {:?}" , tail) ,
393- }
412+ self . check_wide_ptr_meta ( meta, layout) ?;
394413 }
395414 // Make sure this is dereferencable and all.
396415 let ( size, align) = self . ecx . size_and_align_of ( meta, layout) ?
0 commit comments