@@ -22,8 +22,8 @@ use crate::fluent_generated as fluent;
2222
2323use super :: {
2424 alloc_range, AllocBytes , AllocId , AllocMap , AllocRange , Allocation , CheckInAllocMsg ,
25- GlobalAlloc , InterpCx , InterpResult , Machine , MayLeak , Pointer , PointerArithmetic , Provenance ,
26- Scalar ,
25+ GlobalAlloc , InterpCx , InterpResult , Machine , MayLeak , Misalignment , Pointer ,
26+ PointerArithmetic , Provenance , Scalar ,
2727} ;
2828
2929#[ derive( Debug , PartialEq , Copy , Clone ) ]
@@ -372,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
372372 self . check_and_deref_ptr (
373373 ptr,
374374 size,
375- M :: enforce_alignment ( self ) . then_some ( align) ,
375+ align,
376376 CheckInAllocMsg :: MemoryAccessTest ,
377377 |alloc_id, offset, prov| {
378378 let ( size, align) = self
@@ -382,9 +382,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
382382 )
383383 }
384384
385- /// Check if the given pointer points to live memory of given `size` and `align`
386- /// (ignoring `M::enforce_alignment`). The caller can control the error message for the
387- /// out-of-bounds case.
385+ /// Check if the given pointer points to live memory of given `size` and `align`.
386+ /// The caller can control the error message for the out-of-bounds case.
388387 #[ inline( always) ]
389388 pub fn check_ptr_access_align (
390389 & self ,
@@ -393,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
393392 align : Align ,
394393 msg : CheckInAllocMsg ,
395394 ) -> InterpResult < ' tcx > {
396- self . check_and_deref_ptr ( ptr, size, Some ( align) , msg, |alloc_id, _, _| {
395+ self . check_and_deref_ptr ( ptr, size, align, msg, |alloc_id, _, _| {
397396 let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id, msg) ?;
398397 Ok ( ( size, align, ( ) ) )
399398 } ) ?;
@@ -402,15 +401,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
402401
403402 /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference
404403 /// to the allocation it points to. Supports both shared and mutable references, as the actual
405- /// checking is offloaded to a helper closure. `align` defines whether and which alignment check
406- /// is done.
404+ /// checking is offloaded to a helper closure.
407405 ///
408406 /// If this returns `None`, the size is 0; it can however return `Some` even for size 0.
409407 fn check_and_deref_ptr < T > (
410408 & self ,
411409 ptr : Pointer < Option < M :: Provenance > > ,
412410 size : Size ,
413- align : Option < Align > ,
411+ align : Align ,
414412 msg : CheckInAllocMsg ,
415413 alloc_size : impl FnOnce (
416414 AllocId ,
@@ -426,9 +424,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
426424 throw_ub ! ( DanglingIntPointer ( addr, msg) ) ;
427425 }
428426 // Must be aligned.
429- if let Some ( align) = align {
430- self . check_offset_align ( addr, align) ?;
431- }
427+ self . check_misalign ( Self :: offset_misalignment ( addr, align) ) ?;
432428 None
433429 }
434430 Ok ( ( alloc_id, offset, prov) ) => {
@@ -450,18 +446,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
450446 }
451447 // Test align. Check this last; if both bounds and alignment are violated
452448 // we want the error to be about the bounds.
453- if let Some ( align) = align {
454- if M :: use_addr_for_alignment_check ( self ) {
455- // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
456- self . check_offset_align ( ptr. addr ( ) . bytes ( ) , align) ?;
457- } else {
458- // Check allocation alignment and offset alignment.
459- if alloc_align. bytes ( ) < align. bytes ( ) {
460- throw_ub ! ( AlignmentCheckFailed { has: alloc_align, required: align } ) ;
461- }
462- self . check_offset_align ( offset. bytes ( ) , align) ?;
463- }
464- }
449+ self . check_misalign ( self . alloc_misalignment ( ptr, offset, align, alloc_align) ) ?;
465450
466451 // We can still be zero-sized in this branch, in which case we have to
467452 // return `None`.
@@ -470,16 +455,59 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
470455 } )
471456 }
472457
473- fn check_offset_align ( & self , offset : u64 , align : Align ) -> InterpResult < ' tcx > {
458+ #[ inline( always) ]
459+ pub ( super ) fn check_misalign ( & self , misaligned : Option < Misalignment > ) -> InterpResult < ' tcx > {
460+ if M :: enforce_alignment ( self ) {
461+ if let Some ( misaligned) = misaligned {
462+ throw_ub ! ( AlignmentCheckFailed ( misaligned) )
463+ }
464+ }
465+ Ok ( ( ) )
466+ }
467+
468+ #[ must_use]
469+ fn offset_misalignment ( offset : u64 , align : Align ) -> Option < Misalignment > {
474470 if offset % align. bytes ( ) == 0 {
475- Ok ( ( ) )
471+ None
476472 } else {
477473 // The biggest power of two through which `offset` is divisible.
478474 let offset_pow2 = 1 << offset. trailing_zeros ( ) ;
479- throw_ub ! ( AlignmentCheckFailed {
480- has: Align :: from_bytes( offset_pow2) . unwrap( ) ,
481- required: align
482- } ) ;
475+ Some ( Misalignment { has : Align :: from_bytes ( offset_pow2) . unwrap ( ) , required : align } )
476+ }
477+ }
478+
479+ #[ must_use]
480+ fn alloc_misalignment (
481+ & self ,
482+ ptr : Pointer < Option < M :: Provenance > > ,
483+ offset : Size ,
484+ align : Align ,
485+ alloc_align : Align ,
486+ ) -> Option < Misalignment > {
487+ if M :: use_addr_for_alignment_check ( self ) {
488+ // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
489+ Self :: offset_misalignment ( ptr. addr ( ) . bytes ( ) , align)
490+ } else {
491+ // Check allocation alignment and offset alignment.
492+ if alloc_align. bytes ( ) < align. bytes ( ) {
493+ Some ( Misalignment { has : alloc_align, required : align } )
494+ } else {
495+ Self :: offset_misalignment ( offset. bytes ( ) , align)
496+ }
497+ }
498+ }
499+
500+ pub ( super ) fn is_ptr_misaligned (
501+ & self ,
502+ ptr : Pointer < Option < M :: Provenance > > ,
503+ align : Align ,
504+ ) -> Option < Misalignment > {
505+ match self . ptr_try_get_alloc_id ( ptr) {
506+ Err ( addr) => Self :: offset_misalignment ( addr, align) ,
507+ Ok ( ( alloc_id, offset, _prov) ) => {
508+ let ( _size, alloc_align, _kind) = self . get_alloc_info ( alloc_id) ;
509+ self . alloc_misalignment ( ptr, offset, align, alloc_align)
510+ }
483511 }
484512 }
485513}
@@ -597,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
597625 let ptr_and_alloc = self . check_and_deref_ptr (
598626 ptr,
599627 size,
600- M :: enforce_alignment ( self ) . then_some ( align) ,
628+ align,
601629 CheckInAllocMsg :: MemoryAccessTest ,
602630 |alloc_id, offset, prov| {
603631 let alloc = self . get_alloc_raw ( alloc_id) ?;
0 commit comments