@@ -307,53 +307,57 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
307
307
self . write_pointer ( offset_ptr, dest) ?;
308
308
}
309
309
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 ] ) ?;
312
312
313
313
// Special case: if both scalars are *equal integers*
314
314
// and not null, we pretend there is an allocation of size 0 right there,
315
315
// and their offset is 0. (There's never a valid object at null, making it an
316
316
// exception from the exception.)
317
317
// 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.
326
322
self . write_scalar ( Scalar :: from_machine_isize ( 0 , self ) , dest) ?;
327
- true
328
- } else {
329
- false
330
323
}
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) ?;
346
360
}
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) ?;
357
361
}
358
362
}
359
363
0 commit comments