@@ -307,53 +307,57 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
307307 self . write_pointer ( offset_ptr, dest) ?;
308308 }
309309 sym:: ptr_offset_from => {
310- let a = self . read_immediate ( & args[ 0 ] ) ? . to_scalar ( ) ?;
311- let b = self . read_immediate ( & args[ 1 ] ) ? . to_scalar ( ) ?;
310+ let a = self . read_pointer ( & args[ 0 ] ) ?;
311+ let b = self . read_pointer ( & args[ 1 ] ) ?;
312312
313313 // Special case: if both scalars are *equal integers*
314314 // and not null, we pretend there is an allocation of size 0 right there,
315315 // and their offset is 0. (There's never a valid object at null, making it an
316316 // exception from the exception.)
317317 // This is the dual to the special exception for offset-by-0
318- // in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
319- //
320- // Control flow is weird because we cannot early-return (to reach the
321- // `go_to_block` at the end).
322- let done = if let ( Ok ( a) , Ok ( b) ) = ( a. try_to_int ( ) , b. try_to_int ( ) ) {
323- let a = a. try_to_machine_usize ( * self . tcx ) . unwrap ( ) ;
324- let b = b. try_to_machine_usize ( * self . tcx ) . unwrap ( ) ;
325- if a == b && a != 0 {
318+ // in the inbounds pointer offset operation (see `ptr_offset_inbounds` below).
319+ match ( self . memory . ptr_try_get_alloc ( a) , self . memory . ptr_try_get_alloc ( b) ) {
320+ ( Err ( a) , Err ( b) ) if a == b && a != 0 => {
321+ // Both are the same non-null integer.
326322 self . write_scalar ( Scalar :: from_machine_isize ( 0 , self ) , dest) ?;
327- true
328- } else {
329- false
330323 }
331- } else {
332- false
333- } ;
334-
335- if !done {
336- // General case: we need two pointers.
337- let a = self . scalar_to_ptr ( a) ;
338- let b = self . scalar_to_ptr ( b) ;
339- let ( a_alloc_id, a_offset, _) = self . memory . ptr_get_alloc ( a) ?;
340- let ( b_alloc_id, b_offset, _) = self . memory . ptr_get_alloc ( b) ?;
341- if a_alloc_id != b_alloc_id {
342- throw_ub_format ! (
343- "ptr_offset_from cannot compute offset of pointers into different \
344- allocations.",
345- ) ;
324+ ( Err ( offset) , _) | ( _, Err ( offset) ) => {
325+ throw_ub ! ( DanglingIntPointer ( offset, CheckInAllocMsg :: OffsetFromTest ) ) ;
326+ }
327+ ( Ok ( ( a_alloc_id, a_offset, _) ) , Ok ( ( b_alloc_id, b_offset, _) ) ) => {
328+ // Both are pointers. They must be into the same allocation.
329+ if a_alloc_id != b_alloc_id {
330+ throw_ub_format ! (
331+ "ptr_offset_from cannot compute offset of pointers into different \
332+ allocations.",
333+ ) ;
334+ }
335+ // And they must both be valid for zero-sized accesses ("in-bounds or one past the end").
336+ self . memory . check_ptr_access_align (
337+ a,
338+ Size :: ZERO ,
339+ Align :: ONE ,
340+ CheckInAllocMsg :: OffsetFromTest ,
341+ ) ?;
342+ self . memory . check_ptr_access_align (
343+ b,
344+ Size :: ZERO ,
345+ Align :: ONE ,
346+ CheckInAllocMsg :: OffsetFromTest ,
347+ ) ?;
348+
349+ // Compute offset.
350+ let usize_layout = self . layout_of ( self . tcx . types . usize ) ?;
351+ let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
352+ let a_offset = ImmTy :: from_uint ( a_offset. bytes ( ) , usize_layout) ;
353+ let b_offset = ImmTy :: from_uint ( b_offset. bytes ( ) , usize_layout) ;
354+ let ( val, _overflowed, _ty) =
355+ self . overflowing_binary_op ( BinOp :: Sub , & a_offset, & b_offset) ?;
356+ let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
357+ let val = ImmTy :: from_scalar ( val, isize_layout) ;
358+ let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
359+ self . exact_div ( & val, & size, dest) ?;
346360 }
347- let usize_layout = self . layout_of ( self . tcx . types . usize ) ?;
348- let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
349- let a_offset = ImmTy :: from_uint ( a_offset. bytes ( ) , usize_layout) ;
350- let b_offset = ImmTy :: from_uint ( b_offset. bytes ( ) , usize_layout) ;
351- let ( val, _overflowed, _ty) =
352- self . overflowing_binary_op ( BinOp :: Sub , & a_offset, & b_offset) ?;
353- let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
354- let val = ImmTy :: from_scalar ( val, isize_layout) ;
355- let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
356- self . exact_div ( & val, & size, dest) ?;
357361 }
358362 }
359363
0 commit comments