@@ -105,29 +105,15 @@ const ZST_ALLOC_ID: AllocId = AllocId(0);
105
105
106
106
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
107
107
pub fn new ( layout : & ' a TargetDataLayout , max_memory : usize ) -> Self {
108
- let mut mem = Memory {
108
+ Memory {
109
109
alloc_map : HashMap :: new ( ) ,
110
110
functions : HashMap :: new ( ) ,
111
111
function_alloc_cache : HashMap :: new ( ) ,
112
112
next_id : AllocId ( 1 ) ,
113
113
layout : layout,
114
114
memory_size : max_memory,
115
115
memory_usage : 0 ,
116
- } ;
117
- // alloc id 0 is reserved for ZSTs, this is an optimization to prevent ZST
118
- // (e.g. function items, (), [], ...) from requiring memory
119
- let alloc = Allocation {
120
- bytes : Vec :: new ( ) ,
121
- relocations : BTreeMap :: new ( ) ,
122
- undef_mask : UndefMask :: new ( 0 ) ,
123
- align : 8 , // should be infinity?
124
- immutable : false , // must be mutable, because sometimes we "move out" of a ZST
125
- } ;
126
- mem. alloc_map . insert ( ZST_ALLOC_ID , alloc) ;
127
- // check that additional zst allocs work
128
- debug_assert ! ( mem. allocate( 0 , 1 ) . unwrap( ) . points_to_zst( ) ) ;
129
- debug_assert ! ( mem. get( ZST_ALLOC_ID ) . is_ok( ) ) ;
130
- mem
116
+ }
131
117
}
132
118
133
119
pub fn allocations ( & self ) -> :: std:: collections:: hash_map:: Iter < AllocId , Allocation > {
@@ -293,6 +279,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
293
279
Some ( alloc) => Ok ( alloc) ,
294
280
None => match self . functions . get ( & id) {
295
281
Some ( _) => Err ( EvalError :: DerefFunctionPointer ) ,
282
+ None if id == ZST_ALLOC_ID => Err ( EvalError :: ZstAllocAccess ) ,
296
283
None => Err ( EvalError :: DanglingPointerDeref ) ,
297
284
}
298
285
}
@@ -304,6 +291,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
304
291
Some ( alloc) => Ok ( alloc) ,
305
292
None => match self . functions . get ( & id) {
306
293
Some ( _) => Err ( EvalError :: DerefFunctionPointer ) ,
294
+ None if id == ZST_ALLOC_ID => Err ( EvalError :: ZstAllocAccess ) ,
307
295
None => Err ( EvalError :: DanglingPointerDeref ) ,
308
296
}
309
297
}
@@ -353,6 +341,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
353
341
while let Some ( id) = allocs_to_print. pop_front ( ) {
354
342
allocs_seen. insert ( id) ;
355
343
let mut msg = format ! ( "Alloc {:<5} " , format!( "{}:" , id) ) ;
344
+ if id == ZST_ALLOC_ID {
345
+ trace ! ( "{} zst allocation" , msg) ;
346
+ continue ;
347
+ }
356
348
let prefix_len = msg. len ( ) ;
357
349
let mut relocations = vec ! [ ] ;
358
350
@@ -406,6 +398,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
406
398
/// Byte accessors
407
399
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
408
400
fn get_bytes_unchecked ( & self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
401
+ if size == 0 {
402
+ return Ok ( & [ ] ) ;
403
+ }
409
404
let alloc = self . get ( ptr. alloc_id ) ?;
410
405
if ptr. offset + size > alloc. bytes . len ( ) {
411
406
return Err ( EvalError :: PointerOutOfBounds {
@@ -418,6 +413,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
418
413
}
419
414
420
415
fn get_bytes_unchecked_mut ( & mut self , ptr : Pointer , size : usize ) -> EvalResult < ' tcx , & mut [ u8 ] > {
416
+ if size == 0 {
417
+ return Ok ( & mut [ ] ) ;
418
+ }
421
419
let alloc = self . get_mut ( ptr. alloc_id ) ?;
422
420
if ptr. offset + size > alloc. bytes . len ( ) {
423
421
return Err ( EvalError :: PointerOutOfBounds {
@@ -430,6 +428,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
430
428
}
431
429
432
430
fn get_bytes ( & self , ptr : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , & [ u8 ] > {
431
+ if size == 0 {
432
+ return Ok ( & [ ] ) ;
433
+ }
433
434
self . check_align ( ptr, align) ?;
434
435
if self . relocations ( ptr, size) ?. count ( ) != 0 {
435
436
return Err ( EvalError :: ReadPointerAsBytes ) ;
@@ -439,6 +440,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
439
440
}
440
441
441
442
fn get_bytes_mut ( & mut self , ptr : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , & mut [ u8 ] > {
443
+ if size == 0 {
444
+ return Ok ( & mut [ ] ) ;
445
+ }
442
446
self . check_align ( ptr, align) ?;
443
447
self . clear_relocations ( ptr, size) ?;
444
448
self . mark_definedness ( ptr, size, true ) ?;
@@ -449,15 +453,17 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
449
453
/// Reading and writing
450
454
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
451
455
pub fn freeze ( & mut self , alloc_id : AllocId ) -> EvalResult < ' tcx , ( ) > {
452
- // Never freeze the zero-sized allocation. If you do that, then getting a mutable handle to
453
- // _any_ ZST becomes an error, since they all share the same allocation.
456
+ // It's not possible to freeze the zero-sized allocation, because it doesn't exist.
454
457
if alloc_id != ZST_ALLOC_ID {
455
458
self . get_mut ( alloc_id) ?. immutable = true ;
456
459
}
457
460
Ok ( ( ) )
458
461
}
459
462
460
463
pub fn copy ( & mut self , src : Pointer , dest : Pointer , size : usize , align : usize ) -> EvalResult < ' tcx , ( ) > {
464
+ if size == 0 {
465
+ return Ok ( ( ) ) ;
466
+ }
461
467
self . check_relocation_edges ( src, size) ?;
462
468
463
469
let src_bytes = self . get_bytes_unchecked ( src, size) ?. as_ptr ( ) ;
@@ -714,6 +720,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
714
720
pub fn mark_definedness ( & mut self , ptr : Pointer , size : usize , new_state : bool )
715
721
-> EvalResult < ' tcx , ( ) >
716
722
{
723
+ if size == 0 {
724
+ return Ok ( ( ) )
725
+ }
717
726
let mut alloc = self . get_mut ( ptr. alloc_id ) ?;
718
727
alloc. undef_mask . set_range ( ptr. offset , ptr. offset + size, new_state) ;
719
728
Ok ( ( ) )
0 commit comments