Skip to content

Commit 0f8cd43

Browse files
committed
Auto merge of rust-lang#85599 - RalfJung:immut-allocs, r=oli-obk
fix deallocation of immutable allocations As part of rust-lang/miri#1814, I realized that we currently allow deallocating immutable allocations. This PR fixes that, and also adds some new APIs that are required to still support the existing Miri backtrace support. r? `@oli-obk`
2 parents 6e92fb4 + f9b36b4 commit 0f8cd43

File tree

9 files changed

+36
-19
lines changed

9 files changed

+36
-19
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use rustc_span::DUMMY_SP;
44

5+
use rustc_ast::Mutability;
56
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
67
use rustc_errors::ErrorReported;
78
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -175,6 +176,7 @@ pub(crate) fn codegen_const_value<'tcx>(
175176
let mut alloc = Allocation::from_bytes(
176177
std::iter::repeat(0).take(size.bytes_usize()).collect::<Vec<u8>>(),
177178
align,
179+
Mutability::Not,
178180
);
179181
alloc.write_scalar(fx, alloc_range(Size::ZERO, size), x.into()).unwrap();
180182
let alloc = fx.tcx.intern_const_alloc(alloc);

compiler/rustc_middle/src/mir/interpret/allocation.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,26 @@ impl AllocRange {
9999

100100
// The constructors are all without extra; the extra gets added by a machine hook later.
101101
impl<Tag> Allocation<Tag> {
102-
/// Creates a read-only allocation initialized by the given bytes
103-
pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
102+
/// Creates an allocation initialized by the given bytes
103+
pub fn from_bytes<'a>(
104+
slice: impl Into<Cow<'a, [u8]>>,
105+
align: Align,
106+
mutability: Mutability,
107+
) -> Self {
104108
let bytes = slice.into().into_owned();
105109
let size = Size::from_bytes(bytes.len());
106110
Self {
107111
bytes,
108112
relocations: Relocations::new(),
109113
init_mask: InitMask::new(size, true),
110114
align,
111-
mutability: Mutability::Not,
115+
mutability,
112116
extra: (),
113117
}
114118
}
115119

116-
pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
117-
Allocation::from_bytes(slice, Align::ONE)
120+
pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
121+
Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
118122
}
119123

120124
pub fn uninit(size: Size, align: Align) -> Self {

compiler/rustc_middle/src/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ impl<'tcx> TyCtxt<'tcx> {
10721072
/// Allocates a read-only byte or string literal for `mir::interpret`.
10731073
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
10741074
// Create an allocation that just contains these bytes.
1075-
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
1075+
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
10761076
let alloc = self.intern_const_alloc(alloc);
10771077
self.create_memory_alloc(alloc)
10781078
}

compiler/rustc_mir/src/const_eval/eval_queries.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ pub(super) fn op_to_const<'tcx>(
169169
(ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes())
170170
}
171171
Scalar::Int { .. } => (
172-
ecx.tcx
173-
.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
172+
ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
173+
b"" as &[u8],
174+
)),
174175
0,
175176
),
176177
};

compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::convert::TryFrom;
22

3+
use rustc_ast::Mutability;
34
use rustc_hir::lang_items::LangItem;
45
use rustc_middle::mir::TerminatorKind;
56
use rustc_middle::ty::subst::Subst;
@@ -79,7 +80,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
7980
line: u32,
8081
col: u32,
8182
) -> MPlaceTy<'tcx, M::PointerTag> {
82-
let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
83+
let file =
84+
self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not);
8385
let line = Scalar::from_u32(line);
8486
let col = Scalar::from_u32(col);
8587

compiler/rustc_mir/src/interpret/intrinsics/type_name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,6 @@ impl Write for AbsolutePathPrinter<'_> {
197197
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
198198
crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
199199
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
200-
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
200+
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
201201
tcx.intern_const_alloc(alloc)
202202
}

compiler/rustc_mir/src/interpret/memory.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
219219
pub fn allocate_bytes(
220220
&mut self,
221221
bytes: &[u8],
222+
align: Align,
222223
kind: MemoryKind<M::MemoryKind>,
224+
mutability: Mutability,
223225
) -> Pointer<M::PointerTag> {
224-
let alloc = Allocation::from_byte_aligned_bytes(bytes);
226+
let alloc = Allocation::from_bytes(bytes, align, mutability);
225227
self.allocate_with(alloc, kind)
226228
}
227229

@@ -321,6 +323,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
321323
}
322324
};
323325

326+
if alloc.mutability == Mutability::Not {
327+
throw_ub_format!("deallocating immutable allocation {}", ptr.alloc_id);
328+
}
324329
if alloc_kind != kind {
325330
throw_ub_format!(
326331
"deallocating {}, which is {} memory, using {} deallocation operation",
@@ -625,9 +630,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
625630
// Need to make a copy, even if `get_global_alloc` is able
626631
// to give us a cheap reference.
627632
let alloc = Self::get_global_alloc(memory_extra, tcx, id, /*is_write*/ true)?;
628-
if alloc.mutability == Mutability::Not {
629-
throw_ub!(WriteToReadOnly(id))
630-
}
631633
let kind = M::GLOBAL_KIND.expect(
632634
"I got a global allocation that I have to copy but the machine does \
633635
not expect that to happen",

compiler/rustc_mir/src/interpret/place.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::convert::TryFrom;
66
use std::fmt::Debug;
77
use std::hash::Hash;
88

9+
use rustc_ast::Mutability;
910
use rustc_macros::HashStable;
1011
use rustc_middle::mir;
1112
use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
@@ -1024,18 +1025,23 @@ where
10241025
MPlaceTy::from_aligned_ptr(ptr, layout)
10251026
}
10261027

1027-
/// Returns a wide MPlace.
1028+
/// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation.
10281029
pub fn allocate_str(
10291030
&mut self,
10301031
str: &str,
10311032
kind: MemoryKind<M::MemoryKind>,
1033+
mutbl: Mutability,
10321034
) -> MPlaceTy<'tcx, M::PointerTag> {
1033-
let ptr = self.memory.allocate_bytes(str.as_bytes(), kind);
1035+
let ptr = self.memory.allocate_bytes(str.as_bytes(), Align::ONE, kind, mutbl);
10341036
let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self);
10351037
let mplace =
10361038
MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) };
10371039

1038-
let layout = self.layout_of(self.tcx.mk_static_str()).unwrap();
1040+
let ty = self.tcx.mk_ref(
1041+
self.tcx.lifetimes.re_static,
1042+
ty::TypeAndMut { ty: self.tcx.types.str_, mutbl },
1043+
);
1044+
let layout = self.layout_of(ty).unwrap();
10391045
MPlaceTy { mplace, layout }
10401046
}
10411047

compiler/rustc_mir_build/src/thir/constant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ crate fn lit_to_const<'tcx>(
2525
let lit = match (lit, &ty.kind()) {
2626
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
2727
let s = s.as_str();
28-
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
28+
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
2929
let allocation = tcx.intern_const_alloc(allocation);
3030
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
3131
}
3232
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
3333
if matches!(inner_ty.kind(), ty::Slice(_)) =>
3434
{
35-
let allocation = Allocation::from_byte_aligned_bytes(data as &[u8]);
35+
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
3636
let allocation = tcx.intern_const_alloc(allocation);
3737
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
3838
}

0 commit comments

Comments
 (0)