@@ -111,6 +111,78 @@ impl<Tag, Extra: Default> Allocation<Tag, Extra> {
111
111
112
112
impl < ' tcx > :: serialize:: UseSpecializedDecodable for & ' tcx Allocation { }
113
113
114
+ /// Various correctness checks for `Pointer`s
115
+ impl < ' tcx , Tag : Copy , Extra > Allocation < Tag , Extra > {
116
+ /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
117
+ /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
118
+ pub fn check_align (
119
+ & self ,
120
+ ptr : Pointer < Tag > ,
121
+ required_align : Align
122
+ ) -> EvalResult < ' tcx > {
123
+ // Check non-NULL/Undef, extract offset
124
+
125
+ // check this is not NULL -- which we can ensure only if this is in-bounds
126
+ let size = Size :: from_bytes ( self . bytes . len ( ) as u64 ) ;
127
+ if ptr. offset > size {
128
+ return err ! ( PointerOutOfBounds {
129
+ ptr: ptr. erase_tag( ) ,
130
+ access: true ,
131
+ allocation_size: size,
132
+ } ) ;
133
+ } ;
134
+ // Check alignment
135
+ if self . align . abi ( ) < required_align. abi ( ) {
136
+ return err ! ( AlignmentCheckFailed {
137
+ has: self . align,
138
+ required: required_align,
139
+ } ) ;
140
+ }
141
+ let offset = ptr. offset . bytes ( ) ;
142
+ if offset % required_align. abi ( ) == 0 {
143
+ Ok ( ( ) )
144
+ } else {
145
+ let has = offset % required_align. abi ( ) ;
146
+ err ! ( AlignmentCheckFailed {
147
+ has: Align :: from_bytes( has, has) . unwrap( ) ,
148
+ required: required_align,
149
+ } )
150
+ }
151
+ }
152
+
153
+ /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
154
+ /// of an allocation (i.e., at the first *inaccessible* location) *is* considered
155
+ /// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used
156
+ /// for the error message.
157
+ /// If you want to check bounds before doing a memory access, be sure to
158
+ /// check the pointer one past the end of your access, then everything will
159
+ /// work out exactly.
160
+ pub fn check_bounds_ptr ( & self , ptr : Pointer < Tag > , access : bool ) -> EvalResult < ' tcx > {
161
+ let allocation_size = self . bytes . len ( ) as u64 ;
162
+ if ptr. offset . bytes ( ) > allocation_size {
163
+ return err ! ( PointerOutOfBounds {
164
+ ptr: ptr. erase_tag( ) ,
165
+ access,
166
+ allocation_size: Size :: from_bytes( allocation_size) ,
167
+ } ) ;
168
+ }
169
+ Ok ( ( ) )
170
+ }
171
+
172
+ /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
173
+ #[ inline( always) ]
174
+ pub fn check_bounds (
175
+ & self ,
176
+ cx : impl HasDataLayout ,
177
+ ptr : Pointer < Tag > ,
178
+ size : Size ,
179
+ access : bool
180
+ ) -> EvalResult < ' tcx > {
181
+ // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
182
+ self . check_bounds_ptr ( ptr. offset ( size, cx) ?, access)
183
+ }
184
+ }
185
+
114
186
/// Byte accessors
115
187
impl < ' tcx , Tag : Copy , Extra : AllocationExtra < Tag > > Allocation < Tag , Extra > {
116
188
/// The last argument controls whether we error out when there are undefined
@@ -527,78 +599,6 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
527
599
}
528
600
}
529
601
530
- impl < ' tcx , Tag : Copy , Extra > Allocation < Tag , Extra > {
531
- /// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
532
- /// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
533
- pub fn check_align (
534
- & self ,
535
- ptr : Pointer < Tag > ,
536
- required_align : Align
537
- ) -> EvalResult < ' tcx > {
538
- // Check non-NULL/Undef, extract offset
539
-
540
- // check this is not NULL -- which we can ensure only if this is in-bounds
541
- let size = Size :: from_bytes ( self . bytes . len ( ) as u64 ) ;
542
- if ptr. offset > size {
543
- return err ! ( PointerOutOfBounds {
544
- ptr: ptr. erase_tag( ) ,
545
- access: true ,
546
- allocation_size: size,
547
- } ) ;
548
- } ;
549
- // Check alignment
550
- if self . align . abi ( ) < required_align. abi ( ) {
551
- return err ! ( AlignmentCheckFailed {
552
- has: self . align,
553
- required: required_align,
554
- } ) ;
555
- }
556
- let offset = ptr. offset . bytes ( ) ;
557
- if offset % required_align. abi ( ) == 0 {
558
- Ok ( ( ) )
559
- } else {
560
- let has = offset % required_align. abi ( ) ;
561
- err ! ( AlignmentCheckFailed {
562
- has: Align :: from_bytes( has, has) . unwrap( ) ,
563
- required: required_align,
564
- } )
565
- }
566
- }
567
-
568
- /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
569
- /// of an allocation (i.e., at the first *inaccessible* location) *is* considered
570
- /// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used
571
- /// for the error message.
572
- /// If you want to check bounds before doing a memory access, be sure to
573
- /// check the pointer one past the end of your access, then everything will
574
- /// work out exactly.
575
- pub fn check_bounds_ptr ( & self , ptr : Pointer < Tag > , access : bool ) -> EvalResult < ' tcx > {
576
- let allocation_size = self . bytes . len ( ) as u64 ;
577
- if ptr. offset . bytes ( ) > allocation_size {
578
- return err ! ( PointerOutOfBounds {
579
- ptr: ptr. erase_tag( ) ,
580
- access,
581
- allocation_size: Size :: from_bytes( allocation_size) ,
582
- } ) ;
583
- }
584
- Ok ( ( ) )
585
- }
586
-
587
- /// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
588
- #[ inline( always) ]
589
- pub fn check_bounds (
590
- & self ,
591
- cx : impl HasDataLayout ,
592
- ptr : Pointer < Tag > ,
593
- size : Size ,
594
- access : bool
595
- ) -> EvalResult < ' tcx > {
596
- // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
597
- self . check_bounds_ptr ( ptr. offset ( size, cx) ?, access)
598
- }
599
- }
600
-
601
-
602
602
#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord , Hash , Debug , RustcEncodable , RustcDecodable ) ]
603
603
pub struct Relocations < Tag =( ) , Id =AllocId > ( SortedMap < Size , ( Tag , Id ) > ) ;
604
604
0 commit comments