@@ -194,7 +194,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
194
194
}
195
195
196
196
let ptr = self . allocate ( bytes. len ( ) as u64 , 1 , Kind :: UninitializedStatic ) ?;
197
- self . write_bytes ( PrimVal :: Ptr ( ptr) , bytes) ?;
197
+ self . write_bytes ( ptr. into ( ) , bytes) ?;
198
198
self . mark_static_initalized ( ptr. alloc_id , Mutability :: Immutable ) ?;
199
199
self . literal_alloc_cache . insert ( bytes. to_vec ( ) , ptr. alloc_id ) ;
200
200
Ok ( ptr)
@@ -280,6 +280,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
280
280
self . layout . endian
281
281
}
282
282
283
+ /// Check that the pointer is aligned and non-NULL
283
284
pub fn check_align ( & self , ptr : Pointer , align : u64 ) -> EvalResult < ' tcx > {
284
285
let offset = match ptr. into_inner_primval ( ) {
285
286
PrimVal :: Ptr ( ptr) => {
@@ -532,13 +533,13 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
532
533
/// Byte accessors
533
534
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
534
535
fn get_bytes_unchecked ( & self , ptr : MemoryPointer , size : u64 , align : u64 ) -> EvalResult < ' tcx , & [ u8 ] > {
535
- if size == 0 {
536
- return Ok ( & [ ] ) ;
537
- }
538
- // FIXME: check alignment for zst memory accesses?
536
+ // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
539
537
if self . reads_are_aligned {
540
538
self . check_align ( ptr. into ( ) , align) ?;
541
539
}
540
+ if size == 0 {
541
+ return Ok ( & [ ] ) ;
542
+ }
542
543
self . check_bounds ( ptr. offset ( size, self . layout ) ?, true ) ?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
543
544
let alloc = self . get ( ptr. alloc_id ) ?;
544
545
assert_eq ! ( ptr. offset as usize as u64 , ptr. offset) ;
@@ -548,13 +549,13 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
548
549
}
549
550
550
551
fn get_bytes_unchecked_mut ( & mut self , ptr : MemoryPointer , size : u64 , align : u64 ) -> EvalResult < ' tcx , & mut [ u8 ] > {
551
- if size == 0 {
552
- return Ok ( & mut [ ] ) ;
553
- }
554
- // FIXME: check alignment for zst memory accesses?
552
+ // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
555
553
if self . writes_are_aligned {
556
554
self . check_align ( ptr. into ( ) , align) ?;
557
555
}
556
+ if size == 0 {
557
+ return Ok ( & mut [ ] ) ;
558
+ }
558
559
self . check_bounds ( ptr. offset ( size, self . layout ) ?, true ) ?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
559
560
let alloc = self . get_mut ( ptr. alloc_id ) ?;
560
561
assert_eq ! ( ptr. offset as usize as u64 , ptr. offset) ;
@@ -643,7 +644,13 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
643
644
644
645
pub fn copy ( & mut self , src : Pointer , dest : Pointer , size : u64 , align : u64 , nonoverlapping : bool ) -> EvalResult < ' tcx > {
645
646
if size == 0 {
646
- // TODO: Should we check for alignment here? (Also see write_bytes intrinsic)
647
+ // Empty accesses don't need to be valid pointers, but they should still be aligned
648
+ if self . reads_are_aligned {
649
+ self . check_align ( src, align) ?;
650
+ }
651
+ if self . writes_are_aligned {
652
+ self . check_align ( dest, align) ?;
653
+ }
647
654
return Ok ( ( ) ) ;
648
655
}
649
656
let src = src. to_ptr ( ) ?;
@@ -695,13 +702,21 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
695
702
696
703
pub fn read_bytes ( & self , ptr : Pointer , size : u64 ) -> EvalResult < ' tcx , & [ u8 ] > {
697
704
if size == 0 {
705
+ // Empty accesses don't need to be valid pointers, but they should still be non-NULL
706
+ if self . reads_are_aligned {
707
+ self . check_align ( ptr, 1 ) ?;
708
+ }
698
709
return Ok ( & [ ] ) ;
699
710
}
700
711
self . get_bytes ( ptr. to_ptr ( ) ?, size, 1 )
701
712
}
702
713
703
- pub fn write_bytes ( & mut self , ptr : PrimVal , src : & [ u8 ] ) -> EvalResult < ' tcx > {
714
+ pub fn write_bytes ( & mut self , ptr : Pointer , src : & [ u8 ] ) -> EvalResult < ' tcx > {
704
715
if src. is_empty ( ) {
716
+ // Empty accesses don't need to be valid pointers, but they should still be non-NULL
717
+ if self . writes_are_aligned {
718
+ self . check_align ( ptr, 1 ) ?;
719
+ }
705
720
return Ok ( ( ) ) ;
706
721
}
707
722
let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ?, src. len ( ) as u64 , 1 ) ?;
@@ -711,6 +726,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
711
726
712
727
pub fn write_repeat ( & mut self , ptr : Pointer , val : u8 , count : u64 ) -> EvalResult < ' tcx > {
713
728
if count == 0 {
729
+ // Empty accesses don't need to be valid pointers, but they should still be non-NULL
730
+ if self . writes_are_aligned {
731
+ self . check_align ( ptr, 1 ) ?;
732
+ }
714
733
return Ok ( ( ) ) ;
715
734
}
716
735
let bytes = self . get_bytes_mut ( ptr. to_ptr ( ) ?, count, 1 ) ?;
0 commit comments