]> git.lizzy.rs Git - rust.git/blobdiff - src/intptrcast.rs
make use of get_alloc_info
[rust.git] / src / intptrcast.rs
index c92954a218ca2dbfad50bd7232757390bd452a99..0ef5b08f9e40fe6917efa1c236d61898fbbb2823 100644 (file)
@@ -5,6 +5,7 @@
 use rand::Rng;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_span::Span;
 use rustc_target::abi::{HasDataLayout, Size};
 
 use crate::*;
@@ -75,23 +76,21 @@ fn alloc_id_from_addr(ecx: &MiriEvalContext<'mir, 'tcx>, addr: u64) -> Option<Al
                 // This never overflows because `addr >= glb`
                 let offset = addr - glb;
                 // If the offset exceeds the size of the allocation, don't use this `alloc_id`.
-
-                if offset
-                    <= ecx
-                        .get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead)
-                        .unwrap()
-                        .0
-                        .bytes()
-                {
-                    Some(alloc_id)
-                } else {
-                    None
-                }
+                let size = ecx.get_alloc_info(alloc_id).0;
+                if offset <= size.bytes() { Some(alloc_id) } else { None }
             }
         }?;
 
-        // We only use this provenance if it has been exposed.
-        if global_state.exposed.contains(&alloc_id) { Some(alloc_id) } else { None }
+        // We only use this provenance if it has been exposed, *and* is still live.
+        if global_state.exposed.contains(&alloc_id) {
+            let (_size, _align, kind) = ecx.get_alloc_info(alloc_id);
+            match kind {
+                AllocKind::LiveData | AllocKind::Function => return Some(alloc_id),
+                AllocKind::Dead => {}
+            }
+        }
+
+        None
     }
 
     pub fn expose_ptr(ecx: &mut MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId, sb: SbTag) {
@@ -132,12 +131,18 @@ pub fn ptr_from_addr_cast(
 
         match global_state.provenance_mode {
             ProvenanceMode::Default => {
-                // The first time this happens, print a warning.
-                use std::sync::atomic::{AtomicBool, Ordering};
-                static FIRST_WARNING: AtomicBool = AtomicBool::new(true);
-                if FIRST_WARNING.swap(false, Ordering::Relaxed) {
-                    register_diagnostic(NonHaltingDiagnostic::Int2Ptr);
+                // The first time this happens at a particular location, print a warning.
+                thread_local! {
+                    // `Span` is non-`Send`, so we use a thread-local instead.
+                    static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();
                 }
+                PAST_WARNINGS.with_borrow_mut(|past_warnings| {
+                    let first = past_warnings.is_empty();
+                    if past_warnings.insert(ecx.cur_span()) {
+                        // Newly inserted, so first time we see this span.
+                        register_diagnostic(NonHaltingDiagnostic::Int2Ptr { details: first });
+                    }
+                });
             }
             ProvenanceMode::Strict => {
                 throw_unsup_format!(
@@ -159,9 +164,8 @@ fn alloc_base_addr(ecx: &MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId) -> u64
             Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
                 // There is nothing wrong with a raw pointer being cast to an integer only after
-                // it became dangling.  Hence `MaybeDead`.
-                let (size, align) =
-                    ecx.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead).unwrap();
+                // it became dangling.  Hence we allow dead allocations.
+                let (size, align, _kind) = ecx.get_alloc_info(alloc_id);
 
                 // This allocation does not have a base address yet, pick one.
                 // Leave some space to the previous allocation, to give it some chance to be less aligned.
@@ -207,7 +211,7 @@ pub fn rel_ptr_to_addr(ecx: &MiriEvalContext<'mir, 'tcx>, ptr: Pointer<AllocId>)
         dl.overflowing_offset(base_addr, offset.bytes()).0
     }
 
-    /// When pointer is used for a memory access, this computes where in which allocation the
+    /// When a pointer is used for a memory access, this computes where in which allocation the
     /// access is going.
     pub fn abs_ptr_to_rel(
         ecx: &MiriEvalContext<'mir, 'tcx>,