diff options
| author | Ralf Jung <post@ralfj.de> | 2019-12-02 09:34:14 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-02 09:34:14 +0100 |
| commit | 313436807b7db2d6f31cf5b33fa556260eabda15 (patch) | |
| tree | bd881687881e13781ba751e271cfbb696d150310 | |
| parent | b7f8b77eec41b47f5cb49bce53dc34c7e87269c7 (diff) | |
| parent | 2869abacfa12ce3946234e5554d160fc932d933d (diff) | |
| download | rust-313436807b7db2d6f31cf5b33fa556260eabda15.tar.gz rust-313436807b7db2d6f31cf5b33fa556260eabda15.zip | |
Rollup merge of #66827 - RalfJung:miri-missing-ret-place, r=oli-obk
handle diverging functions forwarding their return place Fixes https://github.com/rust-lang/miri/issues/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
| -rw-r--r-- | src/librustc_mir/interpret/place.rs | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 5b263f76801..70d9836b6ff 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -651,20 +651,28 @@ where use rustc::mir::PlaceBase; let mut place_ty = match &place.base { - PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place { - Some(return_place) => { - // We use our layout to verify our assumption; caller will validate - // their layout on return. - PlaceTy { - place: *return_place, - layout: self.layout_of( - self.subst_from_frame_and_normalize_erasing_regions( - self.frame().body.return_ty() - ) - )?, - } + PlaceBase::Local(mir::RETURN_PLACE) => { + // `return_place` has the *caller* layout, but we want to use our + // `layout to verify our assumption. The caller will validate + // their layout on return. + PlaceTy { + place: match self.frame().return_place { + Some(p) => *p, + // Even if we don't have a return place, we sometimes need to + // create this place, but any attempt to read from / write to it + // (even a ZST read/write) needs to error, so let us make this + // a NULL place. + // + // FIXME: Ideally we'd make sure that the place projections also + // bail out. + None => Place::null(&*self), + }, + layout: self.layout_of( + self.subst_from_frame_and_normalize_erasing_regions( + self.frame().body.return_ty() + ) + )?, } - None => throw_unsup!(InvalidNullPointerUsage), }, PlaceBase::Local(local) => PlaceTy { // This works even for dead/uninitialized locals; we check further when writing @@ -791,8 +799,8 @@ where // to handle padding properly, which is only correct if we never look at this data with the // wrong type. - let ptr = match self.check_mplace_access(dest, None) - .expect("places should be checked on creation") + // Invalid places are a thing: the return place of a diverging function + let ptr = match self.check_mplace_access(dest, None)? { Some(ptr) => ptr, None => return Ok(()), // zero-sized access |
