@@ -38,20 +38,20 @@ macro_rules! throw_validation_failure {
3838}
3939
4040/// 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 {
4343 ( $e: expr, $what: expr, $where: expr $( , $expected: expr ) ?) => { {
44- try_validation_pat !( $e, $where, {
44+ try_validation !( $e, $where,
4545 _ => { "{}" , $what } $( expected { "{}" , $expected } ) ?,
46- } )
46+ )
4747 } } ;
4848}
4949/// Like try_validation, but will throw a validation error if any of the patterns in $p are
5050/// matched. Other errors are passed back to the caller, unchanged. This lets you use the patterns
5151/// as a kind of validation blacklist:
5252///
5353/// ```
54- /// let v = try_validation_pat !(some_fn(), some_path, {
54+ /// let v = try_validation !(some_fn(), some_path, {
5555/// Foo | Bar | Baz => { "some failure" },
5656/// });
5757/// // Failures that match $p are thrown up as validation errors, but other errors are passed back
@@ -61,7 +61,7 @@ macro_rules! try_validation {
6161/// An additional expected parameter can also be added to the failure message:
6262///
6363/// ```
64- /// let v = try_validation_pat !(some_fn(), some_path, {
64+ /// let v = try_validation !(some_fn(), some_path, {
6565/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" },
6666/// });
6767/// ```
@@ -70,14 +70,15 @@ macro_rules! try_validation {
7070/// the format string in directly:
7171///
7272/// ```
73- /// let v = try_validation_pat !(some_fn(), some_path, {
73+ /// let v = try_validation !(some_fn(), some_path, {
7474/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value },
7575/// });
7676/// ```
7777///
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+ ) => { {
8182 match $e {
8283 Ok ( x) => x,
8384 // 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, '
303304 match tail. kind {
304305 ty:: Dynamic ( ..) => {
305306 let vtable = meta. unwrap_meta ( ) ;
307+ // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
306308 try_validation ! (
307- self . ecx. memory. check_ptr_access (
309+ self . ecx. memory. check_ptr_access_align (
308310 vtable,
309311 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 ,
311314 ) ,
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+ } ,
314322 ) ;
315- try_validation ! (
323+ try_validation_catchall ! (
316324 self . ecx. read_drop_type_from_vtable( vtable) ,
317325 "invalid drop fn in vtable" ,
318326 self . path
319327 ) ;
320- try_validation ! (
328+ try_validation_catchall ! (
321329 self . ecx. read_size_and_align_from_vtable( vtable) ,
322330 "invalid size or align in vtable" ,
323331 self . path
@@ -327,8 +335,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
327335 ty:: Slice ( ..) | ty:: Str => {
328336 let _len = try_validation ! (
329337 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" } ,
332340 ) ;
333341 // We do not check that `len * elem_size <= isize::MAX`:
334342 // 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, '
354362 // Check metadata early, for better diagnostics
355363 let place = try_validation ! (
356364 self . ecx. ref_to_mplace( value) ,
357- format_args! ( "uninitialized {}" , kind ) ,
358- self . path
365+ self . path ,
366+ err_ub! ( InvalidUndefBytes ( .. ) ) => { "uninitialized {}" , kind } ,
359367 ) ;
360368 if place. layout . is_unsized ( ) {
361369 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, '
376384 // alignment and size determined by the layout (size will be 0,
377385 // alignment should take attributes into account).
378386 . unwrap_or_else ( || ( place. layout . size , place. layout . align . abi ) ) ;
387+ // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
379388 let ptr: Option < _ > = match self . ecx . memory . check_ptr_access_align (
380389 place. ptr ,
381390 size,
@@ -489,12 +498,20 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
489498 match ty. kind {
490499 ty:: Bool => {
491500 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+ ) ;
493506 Ok ( true )
494507 }
495508 ty:: Char => {
496509 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+ ) ;
498515 Ok ( true )
499516 }
500517 ty:: Float ( _) | ty:: Int ( _) | ty:: Uint ( _) => {
@@ -521,9 +538,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
521538 // We are conservative with undef for integers, but try to
522539 // actually enforce the strict rules for raw pointers (mostly because
523540 // 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,
525544 err_ub!( InvalidUndefBytes ( ..) ) => { "uninitialized raw pointer" } ,
526- } ) ;
545+ ) ;
527546 if place. layout . is_unsized ( ) {
528547 self . check_wide_ptr_meta ( place. meta , place. layout ) ?;
529548 }
@@ -539,7 +558,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
539558 }
540559 ty:: FnPtr ( _sig) => {
541560 let value = self . ecx . read_scalar ( value) ?;
542- let _fn = try_validation ! (
561+ let _fn = try_validation_catchall ! (
543562 value. not_undef( ) . and_then( |ptr| self . ecx. memory. get_fn( ptr) ) ,
544563 value,
545564 self . path,
@@ -598,9 +617,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
598617 // At least one value is excluded. Get the bits.
599618 let value = try_validation ! (
600619 value. not_undef( ) ,
601- value,
602620 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) } ,
604623 ) ;
605624 let bits = match value. to_bits_or_ptr ( op. layout . size , self . ecx ) {
606625 Err ( ptr) => {
@@ -761,8 +780,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
761780 let mplace = op. assert_mem_place ( self . ecx ) ; // strings are never immediate
762781 try_validation ! (
763782 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" } ,
766785 ) ;
767786 }
768787 ty:: Array ( tys, ..) | ty:: Slice ( tys)
0 commit comments