Skip to content

Commit 30a2ae6

Browse files
committed
interpret: get_alloc_info: also return mutability
1 parent 62bb2ac commit 30a2ae6

File tree

9 files changed

+34
-23
lines changed

9 files changed

+34
-23
lines changed

Diff for: compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ fn report_validation_error<'tcx>(
472472
backtrace.print_backtrace();
473473

474474
let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
475-
let (size, align, _) = ecx.get_alloc_info(alloc_id);
475+
let (size, align, ..) = ecx.get_alloc_info(alloc_id);
476476
let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes };
477477

478478
crate::const_eval::report(

Diff for: compiler/rustc_const_eval/src/interpret/memory.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
524524
match self.ptr_try_get_alloc_id(ptr, 0) {
525525
Err(addr) => is_offset_misaligned(addr, align),
526526
Ok((alloc_id, offset, _prov)) => {
527-
let (_size, alloc_align, kind) = self.get_alloc_info(alloc_id);
527+
let (_size, alloc_align, kind, _mutbl) = self.get_alloc_info(alloc_id);
528528
if let Some(misalign) =
529529
M::alignment_check(self, alloc_id, alloc_align, kind, offset, align)
530530
{
@@ -818,19 +818,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
818818

819819
/// Obtain the size and alignment of an allocation, even if that allocation has
820820
/// been deallocated.
821-
pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) {
821+
pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind, Mutability) {
822822
// # Regular allocations
823823
// Don't use `self.get_raw` here as that will
824824
// a) cause cycles in case `id` refers to a static
825825
// b) duplicate a global's allocation in miri
826826
if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
827-
return (alloc.size(), alloc.align, AllocKind::LiveData);
827+
return (alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability);
828828
}
829829

830830
// # Function pointers
831831
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
832832
if self.get_fn_alloc(id).is_some() {
833-
return (Size::ZERO, Align::ONE, AllocKind::Function);
833+
return (Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not);
834834
}
835835

836836
// # Statics
@@ -842,17 +842,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
842842
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
843843
assert!(!self.tcx.is_thread_local_static(def_id));
844844

845-
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else {
845+
let DefKind::Static { nested, mutability, .. } = self.tcx.def_kind(def_id) else {
846846
bug!("GlobalAlloc::Static is not a static")
847847
};
848848

849-
let (size, align) = if nested {
849+
let (size, align, mutability) = if nested {
850850
// Nested anonymous statics are untyped, so let's get their
851851
// size and alignment from the allocation itself. This always
852852
// succeeds, as the query is fed at DefId creation time, so no
853853
// evaluation actually occurs.
854854
let alloc = self.tcx.eval_static_initializer(def_id).unwrap();
855-
(alloc.0.size(), alloc.0.align)
855+
(alloc.0.size(), alloc.0.align, alloc.0.mutability)
856856
} else {
857857
// Use size and align of the type for everything else. We need
858858
// to do that to
@@ -865,22 +865,33 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
865865
.expect("statics should not have generic parameters");
866866
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
867867
assert!(layout.is_sized());
868-
(layout.size, layout.align.abi)
868+
let mutability = match mutability {
869+
Mutability::Not if !ty.is_freeze(*self.tcx, ParamEnv::empty()) => {
870+
Mutability::Not
871+
}
872+
_ => Mutability::Mut,
873+
};
874+
(layout.size, layout.align.abi, mutability)
869875
};
870-
(size, align, AllocKind::LiveData)
876+
(size, align, AllocKind::LiveData, mutability)
871877
}
872878
Some(GlobalAlloc::Memory(alloc)) => {
873879
// Need to duplicate the logic here, because the global allocations have
874880
// different associated types than the interpreter-local ones.
875881
let alloc = alloc.inner();
876-
(alloc.size(), alloc.align, AllocKind::LiveData)
882+
(alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability)
877883
}
878884
Some(GlobalAlloc::Function { .. }) => {
879885
bug!("We already checked function pointers above")
880886
}
881887
Some(GlobalAlloc::VTable(..)) => {
882888
// No data to be accessed here. But vtables are pointer-aligned.
883-
return (Size::ZERO, self.tcx.data_layout.pointer_align.abi, AllocKind::VTable);
889+
return (
890+
Size::ZERO,
891+
self.tcx.data_layout.pointer_align.abi,
892+
AllocKind::VTable,
893+
Mutability::Not,
894+
);
884895
}
885896
// The rest must be dead.
886897
None => {
@@ -891,7 +902,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
891902
.dead_alloc_map
892903
.get(&id)
893904
.expect("deallocated pointers should all be recorded in `dead_alloc_map`");
894-
(size, align, AllocKind::Dead)
905+
(size, align, AllocKind::Dead, Mutability::Not)
895906
}
896907
}
897908
}
@@ -902,7 +913,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
902913
id: AllocId,
903914
msg: CheckInAllocMsg,
904915
) -> InterpResult<'tcx, (Size, Align)> {
905-
let (size, align, kind) = self.get_alloc_info(id);
916+
let (size, align, kind, _mutbl) = self.get_alloc_info(id);
906917
if matches!(kind, AllocKind::Dead) {
907918
throw_ub!(PointerUseAfterFree(id, msg))
908919
}
@@ -1458,7 +1469,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14581469
let ptr = scalar.to_pointer(self)?;
14591470
match self.ptr_try_get_alloc_id(ptr, 0) {
14601471
Ok((alloc_id, offset, _)) => {
1461-
let (size, _align, _kind) = self.get_alloc_info(alloc_id);
1472+
let (size, _align, _kind, _mutbl) = self.get_alloc_info(alloc_id);
14621473
// If the pointer is out-of-bounds, it may be null.
14631474
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
14641475
offset > size

Diff for: compiler/rustc_const_eval/src/interpret/validity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
594594
}
595595

596596
// Dangling and Mutability check.
597-
let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
597+
let (size, _align, alloc_kind, _mutbl) = self.ecx.get_alloc_info(alloc_id);
598598
if alloc_kind == AllocKind::Dead {
599599
// This can happen for zero-sized references. We can't have *any* references to
600600
// non-existing allocations in const-eval though, interning rejects them all as

Diff for: src/tools/miri/src/alloc_addresses/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
157157
) -> InterpResult<'tcx, u64> {
158158
let ecx = self.eval_context_ref();
159159
let mut rng = ecx.machine.rng.borrow_mut();
160-
let (size, align, kind) = ecx.get_alloc_info(alloc_id);
160+
let (size, align, kind, _mutbl) = ecx.get_alloc_info(alloc_id);
161161
// This is either called immediately after allocation (and then cached), or when
162162
// adjusting `tcx` pointers (which never get freed). So assert that we are looking
163163
// at a live allocation. This also ensures that we never re-assign an address to an

Diff for: src/tools/miri/src/borrow_tracker/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
363363
// If it does exist, then we have the guarantee that the
364364
// pointer is readable, and the implicit read access inserted
365365
// will never cause UB on the pointer itself.
366-
let (_, _, kind) = this.get_alloc_info(*alloc_id);
366+
let (_, _, kind, _mutbl) = this.get_alloc_info(*alloc_id);
367367
if matches!(kind, AllocKind::LiveData) {
368368
let alloc_extra = this.get_alloc_extra(*alloc_id)?; // can still fail for `extern static`
369369
let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap();

Diff for: src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
626626
return interp_ok(())
627627
};
628628

629-
let (_size, _align, alloc_kind) = this.get_alloc_info(alloc_id);
629+
let (_size, _align, alloc_kind, _mutbl) = this.get_alloc_info(alloc_id);
630630
match alloc_kind {
631631
AllocKind::LiveData => {
632632
// This should have alloc_extra data, but `get_alloc_extra` can still fail
@@ -1017,7 +1017,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10171017
// Function pointers and dead objects don't have an alloc_extra so we ignore them.
10181018
// This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks.
10191019
// NOT using `get_alloc_extra_mut` since this might be a read-only allocation!
1020-
let (_size, _align, kind) = this.get_alloc_info(alloc_id);
1020+
let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id);
10211021
match kind {
10221022
AllocKind::LiveData => {
10231023
// This should have alloc_extra data, but `get_alloc_extra` can still fail

Diff for: src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
538538
// Function pointers and dead objects don't have an alloc_extra so we ignore them.
539539
// This is okay because accessing them is UB anyway, no need for any Tree Borrows checks.
540540
// NOT using `get_alloc_extra_mut` since this might be a read-only allocation!
541-
let (_size, _align, kind) = this.get_alloc_info(alloc_id);
541+
let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id);
542542
match kind {
543543
AllocKind::LiveData => {
544544
// This should have alloc_extra data, but `get_alloc_extra` can still fail

Diff for: src/tools/miri/src/machine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
11251125
let Provenance::Concrete { alloc_id, .. } = ptr.provenance else {
11261126
panic!("extern_statics cannot contain wildcards")
11271127
};
1128-
let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id);
1128+
let (shim_size, shim_align, _kind, _mutbl) = ecx.get_alloc_info(alloc_id);
11291129
let def_ty = ecx.tcx.type_of(def_id).instantiate_identity();
11301130
let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap();
11311131
if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align {

Diff for: src/tools/miri/src/shims/foreign_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
409409
);
410410
}
411411
if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr, 0) {
412-
let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id);
412+
let (_size, alloc_align, _kind, _mutbl) = this.get_alloc_info(alloc_id);
413413
// If the newly promised alignment is bigger than the native alignment of this
414414
// allocation, and bigger than the previously promised alignment, then set it.
415415
if align > alloc_align

0 commit comments

Comments
 (0)