X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fintptrcast.rs;h=188ff94861bdd194a223f092f5c24149c276b725;hb=296ba8b1c84f65d123fa5b35f6f2e47e73710b08;hp=059d8217fabb4e235e07d85f01fd409380a5e044;hpb=02bba3f53130b1ed389bf38f873fdf58315ede37;p=rust.git diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 059d8217fab..188ff94861b 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -1,14 +1,14 @@ use std::cell::RefCell; use std::cmp::max; -use std::collections::{hash_map::Entry, HashMap}; +use std::collections::hash_map::Entry; +use log::trace; use rand::Rng; -use rustc::ty::layout::HasDataLayout; -use rustc_mir::interpret::{AllocCheck, AllocId, InterpResult, Memory, Pointer, PointerArithmetic}; -use rustc_target::abi::Size; +use rustc_data_structures::fx::FxHashMap; +use rustc_target::abi::{Size, HasDataLayout}; -use crate::{Evaluator, Tag, STACK_ADDR}; +use crate::*; pub type MemoryExtra = RefCell; @@ -21,7 +21,7 @@ pub struct GlobalState { /// `AllocExtra` because function pointers also have a base address, and /// they do not have an `AllocExtra`. /// This is the inverse of `int_to_ptr_map`. - pub base_addr: HashMap, + pub base_addr: FxHashMap, /// This is used as a memory address when a new pointer is casted to an integer. It /// is always larger than any address that was previously made part of a block. pub next_base_addr: u64, @@ -31,7 +31,7 @@ impl Default for GlobalState { fn default() -> Self { GlobalState { int_to_ptr_map: Vec::default(), - base_addr: HashMap::default(), + base_addr: FxHashMap::default(), next_base_addr: STACK_ADDR, } } @@ -40,15 +40,13 @@ fn default() -> Self { impl<'mir, 'tcx> GlobalState { pub fn int_to_ptr( int: u64, - memory: &Memory<'mir, 'tcx, Evaluator<'tcx>>, + memory: &Memory<'mir, 'tcx, Evaluator<'mir, 'tcx>>, ) -> InterpResult<'tcx, Pointer> { - if int == 0 { - throw_unsup!(InvalidNullPointerUsage); - } - let global_state = memory.extra.intptrcast.borrow(); let pos = global_state.int_to_ptr_map.binary_search_by_key(&int, |(addr, _)| *addr); + // The int must be in-bounds after being cast to a pointer, so we error + // with `CheckInAllocMsg::InboundsTest`. Ok(match pos { Ok(pos) => { let (_, alloc_id) = global_state.int_to_ptr_map[pos]; @@ -56,7 +54,7 @@ pub fn int_to_ptr( // zero. The pointer is untagged because it was created from a cast Pointer::new_with_tag(alloc_id, Size::from_bytes(0), Tag::Untagged) } - Err(0) => throw_unsup!(DanglingPointerDeref), + Err(0) => throw_ub!(DanglingIntPointer(int, CheckInAllocMsg::InboundsTest)), Err(pos) => { // This is the largest of the adresses smaller than `int`, // i.e. the greatest lower bound (glb) @@ -68,7 +66,7 @@ pub fn int_to_ptr( // This pointer is untagged because it was created from a cast Pointer::new_with_tag(alloc_id, Size::from_bytes(offset), Tag::Untagged) } else { - throw_unsup!(DanglingPointerDeref) + throw_ub!(DanglingIntPointer(int, CheckInAllocMsg::InboundsTest)) } } }) @@ -76,16 +74,17 @@ pub fn int_to_ptr( pub fn ptr_to_int( ptr: Pointer, - memory: &Memory<'mir, 'tcx, Evaluator<'tcx>>, + memory: &Memory<'mir, 'tcx, Evaluator<'mir, 'tcx>>, ) -> InterpResult<'tcx, u64> { let mut global_state = memory.extra.intptrcast.borrow_mut(); let global_state = &mut *global_state; + let id = ptr.alloc_id; // There is nothing wrong with a raw pointer being cast to an integer only after // it became dangling. Hence `MaybeDead`. - let (size, align) = memory.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)?; + let (size, align) = memory.get_size_and_align(id, AllocCheck::MaybeDead)?; - let base_addr = match global_state.base_addr.entry(ptr.alloc_id) { + let base_addr = match global_state.base_addr.entry(id) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { // This allocation does not have a base address yet, pick one. @@ -102,7 +101,7 @@ pub fn ptr_to_int( trace!( "Assigning base address {:#x} to allocation {:?} (slack: {}, align: {})", base_addr, - ptr.alloc_id, + id, slack, align.bytes(), ); @@ -112,7 +111,7 @@ pub fn ptr_to_int( global_state.next_base_addr = base_addr.checked_add(max(size.bytes(), 1)).unwrap(); // Given that `next_base_addr` increases in each allocation, pushing the // corresponding tuple keeps `int_to_ptr_map` sorted - global_state.int_to_ptr_map.push((base_addr, ptr.alloc_id)); + global_state.int_to_ptr_map.push((base_addr, id)); base_addr }