@@ -7,7 +7,7 @@ use super::{
7
7
8
8
use crate :: ty:: layout:: { Size , Align } ;
9
9
use syntax:: ast:: Mutability ;
10
- use std:: iter;
10
+ use std:: { iter, fmt :: { self , Display } } ;
11
11
use crate :: mir;
12
12
use std:: ops:: { Deref , DerefMut } ;
13
13
use rustc_data_structures:: sorted_map:: SortedMap ;
@@ -22,6 +22,44 @@ pub enum InboundsCheck {
22
22
MaybeDead ,
23
23
}
24
24
25
+ /// Used by `check_in_alloc` to indicate whether the pointer needs to be just inbounds
26
+ /// or also inbounds of a *live* allocation.
27
+ #[ derive( Debug , Copy , Clone , RustcEncodable , RustcDecodable , HashStable ) ]
28
+ pub enum CheckInAllocMsg {
29
+ ReadCStr ,
30
+ CheckBytes ,
31
+ WriteBytes ,
32
+ WriteRepeat ,
33
+ ReadScalar ,
34
+ WriteScalar ,
35
+ SlicePatCoveredByConst ,
36
+ ReadDiscriminant ,
37
+ CheckAlign ,
38
+ ReadBytes ,
39
+ CopyRepeatedly ,
40
+ CheckBounds ,
41
+ }
42
+
43
+ impl Display for CheckInAllocMsg {
44
+
45
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
46
+ write ! ( f, "{}" , match * self {
47
+ CheckInAllocMsg :: ReadCStr => "read C str" ,
48
+ CheckInAllocMsg :: CheckBytes => "check bytes" ,
49
+ CheckInAllocMsg :: WriteBytes => "write bytes" ,
50
+ CheckInAllocMsg :: WriteRepeat => "write repeat" ,
51
+ CheckInAllocMsg :: ReadScalar => "read scalar" ,
52
+ CheckInAllocMsg :: WriteScalar => "write scalar" ,
53
+ CheckInAllocMsg :: SlicePatCoveredByConst => "slice pat covered by const" ,
54
+ CheckInAllocMsg :: ReadDiscriminant => "read discriminant" ,
55
+ CheckInAllocMsg :: CheckAlign => "check align" ,
56
+ CheckInAllocMsg :: ReadBytes => "read bytes" ,
57
+ CheckInAllocMsg :: CopyRepeatedly => "copy repeatedly" ,
58
+ CheckInAllocMsg :: CheckBounds => "check bounds" ,
59
+ } )
60
+ }
61
+ }
62
+
25
63
#[ derive( Clone , Debug , Eq , PartialEq , PartialOrd , Ord , Hash , RustcEncodable , RustcDecodable ) ]
26
64
pub struct Allocation < Tag =( ) , Extra =( ) > {
27
65
/// The actual bytes of the allocation.
@@ -140,9 +178,10 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
140
178
fn check_bounds_ptr (
141
179
& self ,
142
180
ptr : Pointer < Tag > ,
181
+ msg : CheckInAllocMsg ,
143
182
) -> EvalResult < ' tcx > {
144
183
let allocation_size = self . bytes . len ( ) as u64 ;
145
- ptr. check_in_alloc ( Size :: from_bytes ( allocation_size) , InboundsCheck :: Live )
184
+ ptr. check_in_alloc ( Size :: from_bytes ( allocation_size) , msg )
146
185
}
147
186
148
187
/// Checks if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
@@ -152,9 +191,10 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
152
191
cx : & impl HasDataLayout ,
153
192
ptr : Pointer < Tag > ,
154
193
size : Size ,
194
+ msg : CheckInAllocMsg ,
155
195
) -> EvalResult < ' tcx > {
156
196
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
157
- self . check_bounds_ptr ( ptr. offset ( size, cx) ?)
197
+ self . check_bounds_ptr ( ptr. offset ( size, cx) ?, msg )
158
198
}
159
199
}
160
200
@@ -173,11 +213,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
173
213
ptr : Pointer < Tag > ,
174
214
size : Size ,
175
215
check_defined_and_ptr : bool ,
216
+ msg : CheckInAllocMsg ,
176
217
) -> EvalResult < ' tcx , & [ u8 ] >
177
218
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
178
219
where Extra : AllocationExtra < Tag , MemoryExtra >
179
220
{
180
- self . check_bounds ( cx, ptr, size) ?;
221
+ self . check_bounds ( cx, ptr, size, msg ) ?;
181
222
182
223
if check_defined_and_ptr {
183
224
self . check_defined ( ptr, size) ?;
@@ -201,11 +242,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
201
242
cx : & impl HasDataLayout ,
202
243
ptr : Pointer < Tag > ,
203
244
size : Size ,
245
+ msg : CheckInAllocMsg ,
204
246
) -> EvalResult < ' tcx , & [ u8 ] >
205
247
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
206
248
where Extra : AllocationExtra < Tag , MemoryExtra >
207
249
{
208
- self . get_bytes_internal ( cx, ptr, size, true )
250
+ self . get_bytes_internal ( cx, ptr, size, true , msg )
209
251
}
210
252
211
253
/// It is the caller's responsibility to handle undefined and pointer bytes.
@@ -216,11 +258,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
216
258
cx : & impl HasDataLayout ,
217
259
ptr : Pointer < Tag > ,
218
260
size : Size ,
261
+ msg : CheckInAllocMsg ,
219
262
) -> EvalResult < ' tcx , & [ u8 ] >
220
263
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
221
264
where Extra : AllocationExtra < Tag , MemoryExtra >
222
265
{
223
- self . get_bytes_internal ( cx, ptr, size, false )
266
+ self . get_bytes_internal ( cx, ptr, size, false , msg )
224
267
}
225
268
226
269
/// Just calling this already marks everything as defined and removes relocations,
@@ -230,12 +273,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
230
273
cx : & impl HasDataLayout ,
231
274
ptr : Pointer < Tag > ,
232
275
size : Size ,
276
+ msg : CheckInAllocMsg ,
233
277
) -> EvalResult < ' tcx , & mut [ u8 ] >
234
278
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
235
279
where Extra : AllocationExtra < Tag , MemoryExtra >
236
280
{
237
281
assert_ne ! ( size. bytes( ) , 0 , "0-sized accesses should never even get a `Pointer`" ) ;
238
- self . check_bounds ( cx, ptr, size) ?;
282
+ self . check_bounds ( cx, ptr, size, msg ) ?;
239
283
240
284
self . mark_definedness ( ptr, size, true ) ?;
241
285
self . clear_relocations ( cx, ptr, size) ?;
@@ -269,7 +313,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
269
313
// Go through `get_bytes` for checks and AllocationExtra hooks.
270
314
// We read the null, so we include it in the request, but we want it removed
271
315
// from the result!
272
- Ok ( & self . get_bytes ( cx, ptr, size_with_null) ?[ ..size] )
316
+ Ok ( & self . get_bytes ( cx, ptr, size_with_null, CheckInAllocMsg :: ReadCStr ) ?[ ..size] )
273
317
}
274
318
None => err ! ( UnterminatedCString ( ptr. erase_tag( ) ) ) ,
275
319
}
@@ -289,7 +333,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
289
333
where Extra : AllocationExtra < Tag , MemoryExtra >
290
334
{
291
335
// Check bounds and relocations on the edges
292
- self . get_bytes_with_undef_and_ptr ( cx, ptr, size) ?;
336
+ self . get_bytes_with_undef_and_ptr ( cx, ptr, size, CheckInAllocMsg :: CheckBytes ) ?;
293
337
// Check undef and ptr
294
338
if !allow_ptr_and_undef {
295
339
self . check_defined ( ptr, size) ?;
@@ -310,7 +354,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
310
354
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
311
355
where Extra : AllocationExtra < Tag , MemoryExtra >
312
356
{
313
- let bytes = self . get_bytes_mut ( cx, ptr, Size :: from_bytes ( src. len ( ) as u64 ) ) ?;
357
+ let bytes = self . get_bytes_mut ( cx, ptr, Size :: from_bytes ( src. len ( ) as u64 ) , CheckInAllocMsg :: WriteBytes ) ?;
314
358
bytes. clone_from_slice ( src) ;
315
359
Ok ( ( ) )
316
360
}
@@ -326,7 +370,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
326
370
// FIXME: Working around https://github.com/rust-lang/rust/issues/56209
327
371
where Extra : AllocationExtra < Tag , MemoryExtra >
328
372
{
329
- let bytes = self . get_bytes_mut ( cx, ptr, count) ?;
373
+ let bytes = self . get_bytes_mut ( cx, ptr, count, CheckInAllocMsg :: WriteRepeat ) ?;
330
374
for b in bytes {
331
375
* b = val;
332
376
}
@@ -351,7 +395,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
351
395
where Extra : AllocationExtra < Tag , MemoryExtra >
352
396
{
353
397
// get_bytes_unchecked tests relocation edges
354
- let bytes = self . get_bytes_with_undef_and_ptr ( cx, ptr, size) ?;
398
+ let bytes = self . get_bytes_with_undef_and_ptr ( cx, ptr, size, CheckInAllocMsg :: ReadScalar ) ?;
355
399
// Undef check happens *after* we established that the alignment is correct.
356
400
// We must not return Ok() for unaligned pointers!
357
401
if self . check_defined ( ptr, size) . is_err ( ) {
@@ -428,7 +472,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
428
472
} ;
429
473
430
474
let endian = cx. data_layout ( ) . endian ;
431
- let dst = self . get_bytes_mut ( cx, ptr, type_size) ?;
475
+ let dst = self . get_bytes_mut ( cx, ptr, type_size, CheckInAllocMsg :: WriteScalar ) ?;
432
476
write_target_uint ( endian, dst, bytes) . unwrap ( ) ;
433
477
434
478
// See if we have to also write a relocation
0 commit comments