Skip to content

Commit 5922a19

Browse files
authored
Rollup merge of rust-lang#63076 - RalfJung:miri-fn-ptr-alloc-size, r=oli-obk
Miri: fix determining size of an "extra function" allocation Fixes [a bug](rust-lang/miri#862) introduced by rust-lang#62982. Best reviewed commit-by-commit. r? @oli-obk
2 parents b52a95d + 0e602f1 commit 5922a19

File tree

2 files changed

+53
-39
lines changed

2 files changed

+53
-39
lines changed

src/librustc_mir/interpret/machine.rs

+10
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ pub trait AllocMap<K: Hash + Eq, V> {
5454
k: K,
5555
vacant: impl FnOnce() -> Result<V, E>
5656
) -> Result<&mut V, E>;
57+
58+
/// Read-only lookup.
59+
fn get(&self, k: K) -> Option<&V> {
60+
self.get_or(k, || Err(())).ok()
61+
}
62+
63+
/// Mutable lookup.
64+
fn get_mut(&mut self, k: K) -> Option<&mut V> {
65+
self.get_mut_or(k, || Err(())).ok()
66+
}
5767
}
5868

5969
/// Methods of this trait signifies a point where CTFE evaluation would fail

src/librustc_mir/interpret/memory.rs

+43-39
Original file line numberDiff line numberDiff line change
@@ -535,48 +535,52 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
535535
id: AllocId,
536536
liveness: AllocCheck,
537537
) -> InterpResult<'static, (Size, Align)> {
538+
// # Regular allocations
538539
// Don't use `self.get` here as that will
539540
// a) cause cycles in case `id` refers to a static
540541
// b) duplicate a static's allocation in miri
541-
match self.alloc_map.get_or(id, || Err(())) {
542-
Ok((_, alloc)) => Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
543-
Err(()) => {
544-
// Not a local allocation, check the global `tcx.alloc_map`.
545-
546-
// Can't do this in the match argument, we may get cycle errors since the lock would
547-
// be held throughout the match.
548-
let alloc = self.tcx.alloc_map.lock().get(id);
549-
match alloc {
550-
Some(GlobalAlloc::Static(did)) => {
551-
// Use size and align of the type.
552-
let ty = self.tcx.type_of(did);
553-
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
554-
Ok((layout.size, layout.align.abi))
555-
},
556-
Some(GlobalAlloc::Memory(alloc)) =>
557-
// Need to duplicate the logic here, because the global allocations have
558-
// different associated types than the interpreter-local ones.
559-
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
560-
Some(GlobalAlloc::Function(_)) => {
561-
if let AllocCheck::Dereferencable = liveness {
562-
// The caller requested no function pointers.
563-
err!(DerefFunctionPointer)
564-
} else {
565-
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
566-
}
567-
},
568-
// The rest must be dead.
569-
None => if let AllocCheck::MaybeDead = liveness {
570-
// Deallocated pointers are allowed, we should be able to find
571-
// them in the map.
572-
Ok(*self.dead_alloc_map.get(&id)
573-
.expect("deallocated pointers should all be recorded in \
574-
`dead_alloc_map`"))
575-
} else {
576-
err!(DanglingPointerDeref)
577-
},
578-
}
579-
}
542+
if let Some((_, alloc)) = self.alloc_map.get(id) {
543+
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
544+
}
545+
546+
// # Function pointers
547+
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
548+
if let Ok(_) = self.get_fn_alloc(id) {
549+
return if let AllocCheck::Dereferencable = liveness {
550+
// The caller requested no function pointers.
551+
err!(DerefFunctionPointer)
552+
} else {
553+
Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
554+
};
555+
}
556+
557+
// # Statics
558+
// Can't do this in the match argument, we may get cycle errors since the lock would
559+
// be held throughout the match.
560+
let alloc = self.tcx.alloc_map.lock().get(id);
561+
match alloc {
562+
Some(GlobalAlloc::Static(did)) => {
563+
// Use size and align of the type.
564+
let ty = self.tcx.type_of(did);
565+
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
566+
Ok((layout.size, layout.align.abi))
567+
},
568+
Some(GlobalAlloc::Memory(alloc)) =>
569+
// Need to duplicate the logic here, because the global allocations have
570+
// different associated types than the interpreter-local ones.
571+
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
572+
Some(GlobalAlloc::Function(_)) =>
573+
bug!("We already checked function pointers above"),
574+
// The rest must be dead.
575+
None => if let AllocCheck::MaybeDead = liveness {
576+
// Deallocated pointers are allowed, we should be able to find
577+
// them in the map.
578+
Ok(*self.dead_alloc_map.get(&id)
579+
.expect("deallocated pointers should all be recorded in \
580+
`dead_alloc_map`"))
581+
} else {
582+
err!(DanglingPointerDeref)
583+
},
580584
}
581585
}
582586

0 commit comments

Comments
 (0)