Skip to content

Commit e76633b

Browse files
authored
Rollup merge of rust-lang#66827 - RalfJung:miri-missing-ret-place, r=oli-obk
handle diverging functions forwarding their return place Fixes rust-lang/miri#1075: the shim around diverging closures turned into function pointers actually "obtains" a return place inside a diverging function, but just uses it as the return place for a diverging callee. Handle this by using NULL places. This is kind of a hack as it breaks our invariant that all places are dereferencable, but we'd eventually let raw pointers break that anyway I assume so that seems fine. r? @oli-obk
2 parents ba7aa4c + 2869aba commit e76633b

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

src/librustc_mir/interpret/place.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -651,20 +651,28 @@ where
651651
use rustc::mir::PlaceBase;
652652

653653
let mut place_ty = match &place.base {
654-
PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
655-
Some(return_place) => {
656-
// We use our layout to verify our assumption; caller will validate
657-
// their layout on return.
658-
PlaceTy {
659-
place: *return_place,
660-
layout: self.layout_of(
661-
self.subst_from_frame_and_normalize_erasing_regions(
662-
self.frame().body.return_ty()
663-
)
664-
)?,
665-
}
654+
PlaceBase::Local(mir::RETURN_PLACE) => {
655+
// `return_place` has the *caller* layout, but we want to use our
656+
// `layout to verify our assumption. The caller will validate
657+
// their layout on return.
658+
PlaceTy {
659+
place: match self.frame().return_place {
660+
Some(p) => *p,
661+
// Even if we don't have a return place, we sometimes need to
662+
// create this place, but any attempt to read from / write to it
663+
// (even a ZST read/write) needs to error, so let us make this
664+
// a NULL place.
665+
//
666+
// FIXME: Ideally we'd make sure that the place projections also
667+
// bail out.
668+
None => Place::null(&*self),
669+
},
670+
layout: self.layout_of(
671+
self.subst_from_frame_and_normalize_erasing_regions(
672+
self.frame().body.return_ty()
673+
)
674+
)?,
666675
}
667-
None => throw_unsup!(InvalidNullPointerUsage),
668676
},
669677
PlaceBase::Local(local) => PlaceTy {
670678
// This works even for dead/uninitialized locals; we check further when writing
@@ -791,8 +799,8 @@ where
791799
// to handle padding properly, which is only correct if we never look at this data with the
792800
// wrong type.
793801

794-
let ptr = match self.check_mplace_access(dest, None)
795-
.expect("places should be checked on creation")
802+
// Invalid places are a thing: the return place of a diverging function
803+
let ptr = match self.check_mplace_access(dest, None)?
796804
{
797805
Some(ptr) => ptr,
798806
None => return Ok(()), // zero-sized access

0 commit comments

Comments
 (0)