1
+ //! The memory subsystem.
2
+ //!
3
+ //! Generally, we use `Pointer` to denote memory addresses. However, some operations
4
+ //! have a "size"-like parameter, and they take `Scalar` for the address because
5
+ //! if the size is 0, then the pointer can also be a (properly aligned, non-NULL)
6
+ //! integer. It is crucial that these operations call `check_align` *before*
7
+ //! short-circuiting the empty case!
8
+
1
9
use std:: collections:: VecDeque ;
2
10
use std:: hash:: { Hash , Hasher } ;
3
11
use std:: ptr;
@@ -16,6 +24,7 @@ use syntax::ast::Mutability;
16
24
17
25
use super :: { EvalContext , Machine } ;
18
26
27
+
19
28
////////////////////////////////////////////////////////////////////////////////
20
29
// Allocations and pointers
21
30
////////////////////////////////////////////////////////////////////////////////
@@ -256,7 +265,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
256
265
self . tcx . data_layout . endian
257
266
}
258
267
259
- /// Check that the pointer is aligned AND non-NULL.
268
+ /// Check that the pointer is aligned AND non-NULL. This supports scalars
269
+ /// for the benefit of other parts of miri that need to check alignment even for ZST.
260
270
pub fn check_align ( & self , ptr : Scalar , required_align : Align ) -> EvalResult < ' tcx > {
261
271
// Check non-NULL/Undef, extract offset
262
272
let ( offset, alloc_align) = match ptr {
@@ -632,10 +642,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
632
642
length : u64 ,
633
643
nonoverlapping : bool ,
634
644
) -> EvalResult < ' tcx > {
635
- // Empty accesses don't need to be valid pointers, but they should still be aligned
636
- self . check_align ( src, src_align) ?;
637
- self . check_align ( dest, dest_align) ?;
638
645
if size. bytes ( ) == 0 {
646
+ // Nothing to do for ZST, other than checking alignment and non-NULLness.
647
+ self . check_align ( src, src_align) ?;
648
+ self . check_align ( dest, dest_align) ?;
639
649
return Ok ( ( ) ) ;
640
650
}
641
651
let src = src. to_ptr ( ) ?;
@@ -661,6 +671,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
661
671
new_relocations
662
672
} ;
663
673
674
+ // This also checks alignment.
664
675
let src_bytes = self . get_bytes_unchecked ( src, size, src_align) ?. as_ptr ( ) ;
665
676
let dest_bytes = self . get_bytes_mut ( dest, size * length, dest_align) ?. as_mut_ptr ( ) ;
666
677
@@ -718,8 +729,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
718
729
pub fn read_bytes ( & self , ptr : Scalar , size : Size ) -> EvalResult < ' tcx , & [ u8 ] > {
719
730
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
720
731
let align = Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ;
721
- self . check_align ( ptr, align) ?;
722
732
if size. bytes ( ) == 0 {
733
+ self . check_align ( ptr, align) ?;
723
734
return Ok ( & [ ] ) ;
724
735
}
725
736
self . get_bytes ( ptr. to_ptr ( ) ?, size, align)
@@ -728,8 +739,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
728
739
pub fn write_bytes ( & mut self , ptr : Scalar , src : & [ u8 ] ) -> EvalResult < ' tcx > {
729
740
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
730
741
let align = Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ;
731
- self . check_align ( ptr, align) ?;
732
742
if src. is_empty ( ) {
743
+ self . check_align ( ptr, align) ?;
733
744
return Ok ( ( ) ) ;
734
745
}
735
746
let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ?, Size :: from_bytes ( src. len ( ) as u64 ) , align) ?;
@@ -740,8 +751,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
740
751
pub fn write_repeat ( & mut self , ptr : Scalar , val : u8 , count : Size ) -> EvalResult < ' tcx > {
741
752
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
742
753
let align = Align :: from_bytes ( 1 , 1 ) . unwrap ( ) ;
743
- self . check_align ( ptr, align) ?;
744
754
if count. bytes ( ) == 0 {
755
+ self . check_align ( ptr, align) ?;
745
756
return Ok ( ( ) ) ;
746
757
}
747
758
let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ?, count, align) ?;
0 commit comments