@@ -38,20 +38,20 @@ macro_rules! throw_validation_failure {
38
38
}
39
39
40
40
/// Returns a validation failure for any Err value of $e.
41
- // FIXME: Replace all usages of try_validation ! with try_validation_pat !.
42
- macro_rules! try_validation {
41
+ // FIXME: Replace all usages of try_validation_catchall ! with try_validation !.
42
+ macro_rules! try_validation_catchall {
43
43
( $e: expr, $what: expr, $where: expr $( , $expected: expr ) ?) => { {
44
- try_validation_pat !( $e, $where, {
44
+ try_validation !( $e, $where,
45
45
_ => { "{}" , $what } $( expected { "{}" , $expected } ) ?,
46
- } )
46
+ )
47
47
} } ;
48
48
}
49
49
/// Like try_validation, but will throw a validation error if any of the patterns in $p are
50
50
/// matched. Other errors are passed back to the caller, unchanged. This lets you use the patterns
51
51
/// as a kind of validation blacklist:
52
52
///
53
53
/// ```
54
- /// let v = try_validation_pat !(some_fn(), some_path, {
54
+ /// let v = try_validation !(some_fn(), some_path, {
55
55
/// Foo | Bar | Baz => { "some failure" },
56
56
/// });
57
57
/// // Failures that match $p are thrown up as validation errors, but other errors are passed back
@@ -61,7 +61,7 @@ macro_rules! try_validation {
61
61
/// An additional expected parameter can also be added to the failure message:
62
62
///
63
63
/// ```
64
- /// let v = try_validation_pat !(some_fn(), some_path, {
64
+ /// let v = try_validation !(some_fn(), some_path, {
65
65
/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" },
66
66
/// });
67
67
/// ```
@@ -70,14 +70,15 @@ macro_rules! try_validation {
70
70
/// the format string in directly:
71
71
///
72
72
/// ```
73
- /// let v = try_validation_pat !(some_fn(), some_path, {
73
+ /// let v = try_validation !(some_fn(), some_path, {
74
74
/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value },
75
75
/// });
76
76
/// ```
77
77
///
78
- macro_rules! try_validation_pat {
79
- ( $e: expr, $where: expr, { $( $p: pat ) |+ =>
80
- { $( $what_fmt: expr ) ,+ } $( expected { $( $expected_fmt: expr ) ,+ } ) ? $( , ) ?} ) => { {
78
+ macro_rules! try_validation {
79
+ ( $e: expr, $where: expr,
80
+ $( $p: pat ) |+ => { $( $what_fmt: expr ) ,+ } $( expected { $( $expected_fmt: expr ) ,+ } ) ? $( , ) ?
81
+ ) => { {
81
82
match $e {
82
83
Ok ( x) => x,
83
84
// We catch the error and turn it into a validation failure. We are okay with
@@ -303,21 +304,28 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
303
304
match tail. kind {
304
305
ty:: Dynamic ( ..) => {
305
306
let vtable = meta. unwrap_meta ( ) ;
307
+ // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
306
308
try_validation ! (
307
- self . ecx. memory. check_ptr_access (
309
+ self . ecx. memory. check_ptr_access_align (
308
310
vtable,
309
311
3 * self . ecx. tcx. data_layout. pointer_size, // drop, size, align
310
- self . ecx. tcx. data_layout. pointer_align. abi,
312
+ Some ( self . ecx. tcx. data_layout. pointer_align. abi) ,
313
+ CheckInAllocMsg :: InboundsTest ,
311
314
) ,
312
- "dangling or unaligned vtable pointer in wide pointer or too small vtable" ,
313
- self . path
315
+ self . path,
316
+ err_ub!( PointerOutOfBounds { .. } ) |
317
+ err_ub!( AlignmentCheckFailed { .. } ) |
318
+ err_ub!( DanglingIntPointer ( ..) ) |
319
+ err_unsup!( ReadBytesAsPointer ) => {
320
+ "dangling or unaligned vtable pointer in wide pointer or too small vtable"
321
+ } ,
314
322
) ;
315
- try_validation ! (
323
+ try_validation_catchall ! (
316
324
self . ecx. read_drop_type_from_vtable( vtable) ,
317
325
"invalid drop fn in vtable" ,
318
326
self . path
319
327
) ;
320
- try_validation ! (
328
+ try_validation_catchall ! (
321
329
self . ecx. read_size_and_align_from_vtable( vtable) ,
322
330
"invalid size or align in vtable" ,
323
331
self . path
@@ -327,8 +335,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
327
335
ty:: Slice ( ..) | ty:: Str => {
328
336
let _len = try_validation ! (
329
337
meta. unwrap_meta( ) . to_machine_usize( self . ecx) ,
330
- "non-integer slice length in wide pointer" ,
331
- self . path
338
+ self . path ,
339
+ err_unsup! ( ReadPointerAsBytes ) => { "non-integer slice length in wide pointer" } ,
332
340
) ;
333
341
// We do not check that `len * elem_size <= isize::MAX`:
334
342
// that is only required for references, and there it falls out of the
@@ -354,8 +362,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
354
362
// Check metadata early, for better diagnostics
355
363
let place = try_validation ! (
356
364
self . ecx. ref_to_mplace( value) ,
357
- format_args! ( "uninitialized {}" , kind ) ,
358
- self . path
365
+ self . path ,
366
+ err_ub! ( InvalidUndefBytes ( .. ) ) => { "uninitialized {}" , kind } ,
359
367
) ;
360
368
if place. layout . is_unsized ( ) {
361
369
self . check_wide_ptr_meta ( place. meta , place. layout ) ?;
@@ -376,6 +384,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
376
384
// alignment and size determined by the layout (size will be 0,
377
385
// alignment should take attributes into account).
378
386
. unwrap_or_else ( || ( place. layout . size , place. layout . align . abi ) ) ;
387
+ // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
379
388
let ptr: Option < _ > = match self . ecx . memory . check_ptr_access_align (
380
389
place. ptr ,
381
390
size,
@@ -489,12 +498,20 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
489
498
match ty. kind {
490
499
ty:: Bool => {
491
500
let value = self . ecx . read_scalar ( value) ?;
492
- try_validation ! ( value. to_bool( ) , value, self . path, "a boolean" ) ;
501
+ try_validation ! (
502
+ value. to_bool( ) ,
503
+ self . path,
504
+ err_ub!( InvalidBool ( ..) ) => { "{}" , value } expected { "a boolean" } ,
505
+ ) ;
493
506
Ok ( true )
494
507
}
495
508
ty:: Char => {
496
509
let value = self . ecx . read_scalar ( value) ?;
497
- try_validation ! ( value. to_char( ) , value, self . path, "a valid unicode codepoint" ) ;
510
+ try_validation ! (
511
+ value. to_char( ) ,
512
+ self . path,
513
+ err_ub!( InvalidChar ( ..) ) => { "{}" , value } expected { "a valid unicode codepoint" } ,
514
+ ) ;
498
515
Ok ( true )
499
516
}
500
517
ty:: Float ( _) | ty:: Int ( _) | ty:: Uint ( _) => {
@@ -521,9 +538,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
521
538
// We are conservative with undef for integers, but try to
522
539
// actually enforce the strict rules for raw pointers (mostly because
523
540
// that lets us re-use `ref_to_mplace`).
524
- let place = try_validation_pat ! ( self . ecx. ref_to_mplace( self . ecx. read_immediate( value) ?) , self . path, {
541
+ let place = try_validation ! (
542
+ self . ecx. ref_to_mplace( self . ecx. read_immediate( value) ?) ,
543
+ self . path,
525
544
err_ub!( InvalidUndefBytes ( ..) ) => { "uninitialized raw pointer" } ,
526
- } ) ;
545
+ ) ;
527
546
if place. layout . is_unsized ( ) {
528
547
self . check_wide_ptr_meta ( place. meta , place. layout ) ?;
529
548
}
@@ -539,7 +558,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
539
558
}
540
559
ty:: FnPtr ( _sig) => {
541
560
let value = self . ecx . read_scalar ( value) ?;
542
- let _fn = try_validation ! (
561
+ let _fn = try_validation_catchall ! (
543
562
value. not_undef( ) . and_then( |ptr| self . ecx. memory. get_fn( ptr) ) ,
544
563
value,
545
564
self . path,
@@ -598,9 +617,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
598
617
// At least one value is excluded. Get the bits.
599
618
let value = try_validation ! (
600
619
value. not_undef( ) ,
601
- value,
602
620
self . path,
603
- format_args!( "something {}" , wrapping_range_format( valid_range, max_hi) , )
621
+ err_ub!( InvalidUndefBytes ( ..) ) => { "{}" , value }
622
+ expected { "something {}" , wrapping_range_format( valid_range, max_hi) } ,
604
623
) ;
605
624
let bits = match value. to_bits_or_ptr ( op. layout . size , self . ecx ) {
606
625
Err ( ptr) => {
@@ -761,8 +780,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
761
780
let mplace = op. assert_mem_place ( self . ecx ) ; // strings are never immediate
762
781
try_validation ! (
763
782
self . ecx. read_str( mplace) ,
764
- "uninitialized or non-UTF-8 data in str" ,
765
- self . path
783
+ self . path ,
784
+ err_ub! ( InvalidStr ( .. ) ) => { "uninitialized or non-UTF-8 data in str" } ,
766
785
) ;
767
786
}
768
787
ty:: Array ( tys, ..) | ty:: Slice ( tys)
0 commit comments