@@ -11,7 +11,7 @@ use std::hash::Hash;
11
11
12
12
use super :: {
13
13
GlobalAlloc , InterpResult ,
14
- OpTy , Machine , InterpCx , ValueVisitor , MPlaceTy ,
14
+ Scalar , OpTy , Machine , InterpCx , ValueVisitor , MPlaceTy ,
15
15
} ;
16
16
17
17
macro_rules! throw_validation_failure {
@@ -250,6 +250,47 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
250
250
self . path . truncate ( path_len) ;
251
251
Ok ( ( ) )
252
252
}
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
+ }
253
294
}
254
295
255
296
impl < ' 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>
341
382
}
342
383
}
343
384
ty:: RawPtr ( ..) => {
385
+ // Check pointer part.
344
386
if self . ref_tracking_for_consts . is_some ( ) {
345
387
// Integers/floats in CTFE: For consistency with integers, we do not
346
388
// accept undef.
347
389
let _ptr = try_validation ! ( value. to_scalar_ptr( ) ,
348
390
"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) ;
351
391
} else {
352
392
// Remain consistent with `usize`: Accept anything.
353
393
}
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
+ }
354
402
}
355
403
_ if ty. is_box ( ) || ty. is_region_ptr ( ) => {
356
- // Handle fat pointers.
404
+ // Handle wide pointers.
357
405
// Check metadata early, for better diagnostics
358
406
let ptr = try_validation ! ( value. to_scalar_ptr( ) ,
359
407
"undefined address in pointer" , self . path) ;
360
408
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) ;
362
410
let layout = self . ecx . layout_of ( value. layout . ty . builtin_deref ( true ) . unwrap ( ) . ty ) ?;
363
411
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) ?;
394
413
}
395
414
// Make sure this is dereferencable and all.
396
415
let ( size, align) = self . ecx . size_and_align_of ( meta, layout) ?
0 commit comments