Skip to content

Commit fd3a291

Browse files
committed
Implement intptrcast methods
1 parent 285e9a6 commit fd3a291

File tree

4 files changed

+179
-59
lines changed

4 files changed

+179
-59
lines changed

src/intptrcast.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::cell::RefCell;
2+
3+
use rustc::mir::interpret::AllocId;
4+
5+
pub type MemoryState = RefCell<GlobalState>;
6+
7+
#[derive(Clone, Debug)]
8+
pub struct GlobalState {
9+
pub vec: Vec<(u64, AllocId)>,
10+
pub addr: u64,
11+
}
12+
13+
impl Default for GlobalState {
14+
fn default() -> Self {
15+
GlobalState {
16+
vec: Vec::default(),
17+
addr: 2u64.pow(16)
18+
}
19+
}
20+
}

src/lib.rs

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ mod tls;
2020
mod range_map;
2121
mod mono_hash_map;
2222
mod stacked_borrows;
23+
mod intptrcast;
24+
mod memory;
2325

2426
use std::collections::HashMap;
2527
use std::borrow::Cow;
28+
use std::cell::RefCell;
2629
use std::rc::Rc;
2730

2831
use rand::rngs::StdRng;
@@ -48,6 +51,7 @@ use crate::range_map::RangeMap;
4851
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
4952
use crate::mono_hash_map::MonoHashMap;
5053
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt};
54+
use crate::memory::AllocExtra;
5155

5256
// Used by priroda.
5357
pub use crate::stacked_borrows::{Tag, Permission, Stack, Stacks, Item};
@@ -206,6 +210,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
206210
}
207211
}
208212

213+
ecx.memory_mut().extra.seed = config.seed.clone();
214+
209215
assert!(args.next().is_none(), "start lang item has more arguments than expected");
210216

211217
Ok(ecx)
@@ -386,8 +392,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
386392
type MemoryKinds = MiriMemoryKind;
387393

388394
type FrameExtra = stacked_borrows::CallId;
389-
type MemoryExtra = stacked_borrows::MemoryState;
390-
type AllocExtra = stacked_borrows::Stacks;
395+
type MemoryExtra = memory::MemoryState;
396+
type AllocExtra = memory::AllocExtra;
391397
type PointerTag = Tag;
392398

393399
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
@@ -515,14 +521,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
515521
let (extra, base_tag) = Stacks::new_allocation(
516522
id,
517523
Size::from_bytes(alloc.bytes.len() as u64),
518-
Rc::clone(&memory.extra),
524+
Rc::clone(&memory.extra.stacked),
519525
kind,
520526
);
521527
if kind != MiriMemoryKind::Static.into() {
522528
assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
523529
// Now we can rely on the inner pointers being static, too.
524530
}
525-
let mut memory_extra = memory.extra.borrow_mut();
531+
let mut memory_extra = memory.extra.stacked.borrow_mut();
526532
let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
527533
bytes: alloc.bytes,
528534
relocations: Relocations::from_presorted(
@@ -535,7 +541,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
535541
undef_mask: alloc.undef_mask,
536542
align: alloc.align,
537543
mutability: alloc.mutability,
538-
extra,
544+
extra: AllocExtra {
545+
stacks: extra,
546+
base_addr: RefCell::new(None),
547+
},
539548
};
540549
(Cow::Owned(alloc), base_tag)
541550
}
@@ -545,7 +554,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
545554
id: AllocId,
546555
memory: &Memory<'mir, 'tcx, Self>,
547556
) -> Self::PointerTag {
548-
memory.extra.borrow_mut().static_base_ptr(id)
557+
memory.extra.stacked.borrow_mut().static_base_ptr(id)
549558
}
550559

551560
#[inline(always)]
@@ -570,14 +579,84 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
570579
fn stack_push(
571580
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
572581
) -> InterpResult<'tcx, stacked_borrows::CallId> {
573-
Ok(ecx.memory().extra.borrow_mut().new_call())
582+
Ok(ecx.memory().extra.stacked.borrow_mut().new_call())
574583
}
575584

576585
#[inline(always)]
577586
fn stack_pop(
578587
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
579588
extra: stacked_borrows::CallId,
580589
) -> InterpResult<'tcx> {
581-
Ok(ecx.memory().extra.borrow_mut().end_call(extra))
590+
Ok(ecx.memory().extra.stacked.borrow_mut().end_call(extra))
591+
}
592+
593+
fn int_to_ptr(
594+
int: u64,
595+
memory: &Memory<'mir, 'tcx, Self>,
596+
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
597+
if int == 0 {
598+
return err!(InvalidNullPointerUsage);
599+
}
600+
601+
if memory.extra.seed.is_none() {
602+
return err!(ReadBytesAsPointer);
603+
}
604+
605+
let extra = memory.extra.intptrcast.borrow();
606+
607+
match extra.vec.binary_search_by_key(&int, |(int, _)| *int) {
608+
Ok(pos) => {
609+
let (_, alloc_id) = extra.vec[pos];
610+
Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(0), Tag::Untagged))
611+
}
612+
Err(pos) => {
613+
if pos > 0 {
614+
let (glb, alloc_id) = extra.vec[pos - 1];
615+
let offset = int - glb;
616+
if offset <= memory.get(alloc_id)?.bytes.len() as u64 {
617+
Ok(Pointer::new_with_tag(alloc_id, Size::from_bytes(offset), Tag::Untagged))
618+
} else {
619+
return err!(DanglingPointerDeref);
620+
}
621+
} else {
622+
return err!(DanglingPointerDeref);
623+
}
624+
}
625+
}
626+
}
627+
628+
fn ptr_to_int(
629+
ptr: Pointer<Self::PointerTag>,
630+
memory: &Memory<'mir, 'tcx, Self>,
631+
) -> InterpResult<'tcx, u64> {
632+
if memory.extra.seed.is_none() {
633+
return err!(ReadPointerAsBytes);
634+
}
635+
636+
let mut extra = memory.extra.intptrcast.borrow_mut();
637+
638+
let alloc = memory.get(ptr.alloc_id)?;
639+
640+
let base_addr = match alloc.extra.base_addr.borrow().clone() {
641+
Some(base_addr) => base_addr,
642+
None => {
643+
let base_addr = extra.addr;
644+
extra.addr += alloc.bytes.len() as u64;
645+
646+
*alloc.extra.base_addr.borrow_mut() = Some(base_addr);
647+
648+
let elem = (base_addr, ptr.alloc_id);
649+
650+
if let Err(pos) = extra.vec.binary_search(&elem) {
651+
extra.vec.insert(pos, elem);
652+
} else {
653+
return err!(Unreachable);
654+
}
655+
656+
base_addr
657+
}
658+
};
659+
660+
Ok(base_addr + ptr.offset.bytes())
582661
}
583662
}

src/memory.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::cell::RefCell;
2+
3+
use rustc_mir::interpret::{Pointer, Allocation, AllocationExtra, InterpResult};
4+
use rustc_target::abi::Size;
5+
6+
use crate::{stacked_borrows, intptrcast};
7+
use crate::stacked_borrows::{Tag, AccessKind};
8+
9+
#[derive(Default, Clone, Debug)]
10+
pub struct MemoryState {
11+
pub stacked: stacked_borrows::MemoryState,
12+
pub intptrcast: intptrcast::MemoryState,
13+
pub seed: Option<u64>,
14+
}
15+
16+
#[derive(Debug, Clone,)]
17+
pub struct AllocExtra {
18+
pub stacks: stacked_borrows::Stacks,
19+
pub base_addr: RefCell<Option<u64>>,
20+
}
21+
22+
impl AllocationExtra<Tag> for AllocExtra {
23+
#[inline(always)]
24+
fn memory_read<'tcx>(
25+
alloc: &Allocation<Tag, AllocExtra>,
26+
ptr: Pointer<Tag>,
27+
size: Size,
28+
) -> InterpResult<'tcx> {
29+
trace!("read access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
30+
alloc.extra.stacks.for_each(ptr, size, |stack, global| {
31+
stack.access(AccessKind::Read, ptr.tag, global)?;
32+
Ok(())
33+
})
34+
}
35+
36+
#[inline(always)]
37+
fn memory_written<'tcx>(
38+
alloc: &mut Allocation<Tag, AllocExtra>,
39+
ptr: Pointer<Tag>,
40+
size: Size,
41+
) -> InterpResult<'tcx> {
42+
trace!("write access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
43+
alloc.extra.stacks.for_each(ptr, size, |stack, global| {
44+
stack.access(AccessKind::Write, ptr.tag, global)?;
45+
Ok(())
46+
})
47+
}
48+
49+
#[inline(always)]
50+
fn memory_deallocated<'tcx>(
51+
alloc: &mut Allocation<Tag, AllocExtra>,
52+
ptr: Pointer<Tag>,
53+
size: Size,
54+
) -> InterpResult<'tcx> {
55+
trace!("deallocation with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
56+
alloc.extra.stacks.for_each(ptr, size, |stack, global| {
57+
stack.dealloc(ptr.tag, global)
58+
})
59+
}
60+
}

src/stacked_borrows.rs

Lines changed: 12 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc::mir::RetagKind;
1010

1111
use crate::{
1212
InterpResult, InterpError, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
13-
MemoryKind, MiriMemoryKind, RangeMap, Allocation, AllocationExtra, AllocId, CheckInAllocMsg,
14-
Pointer, Immediate, ImmTy, PlaceTy, MPlaceTy,
13+
MemoryKind, MiriMemoryKind, RangeMap, AllocId, CheckInAllocMsg, Pointer, Immediate, ImmTy,
14+
PlaceTy, MPlaceTy,
1515
};
1616

1717
pub type PtrId = NonZeroU64;
@@ -286,7 +286,7 @@ impl<'tcx> Stack {
286286

287287
/// Test if a memory `access` using pointer tagged `tag` is granted.
288288
/// If yes, return the index of the item that granted it.
289-
fn access(
289+
pub(crate) fn access(
290290
&mut self,
291291
access: AccessKind,
292292
tag: Tag,
@@ -336,7 +336,7 @@ impl<'tcx> Stack {
336336

337337
/// Deallocate a location: Like a write access, but also there must be no
338338
/// active protectors at all because we will remove all items.
339-
fn dealloc(
339+
pub(crate) fn dealloc(
340340
&mut self,
341341
tag: Tag,
342342
global: &GlobalState,
@@ -429,14 +429,15 @@ impl<'tcx> Stacks {
429429
let stack = Stack {
430430
borrows: vec![item],
431431
};
432+
432433
Stacks {
433434
stacks: RefCell::new(RangeMap::new(size, stack)),
434-
global: extra,
435+
global: extra,
435436
}
436437
}
437438

438439
/// Call `f` on every stack in the range.
439-
fn for_each(
440+
pub(crate) fn for_each(
440441
&self,
441442
ptr: Pointer<Tag>,
442443
size: Size,
@@ -456,7 +457,7 @@ impl Stacks {
456457
pub fn new_allocation(
457458
id: AllocId,
458459
size: Size,
459-
extra: MemoryState,
460+
extra: MemoryState,
460461
kind: MemoryKind<MiriMemoryKind>,
461462
) -> (Self, Tag) {
462463
let (tag, perm) = match kind {
@@ -477,46 +478,6 @@ impl Stacks {
477478
}
478479
}
479480

480-
impl AllocationExtra<Tag> for Stacks {
481-
#[inline(always)]
482-
fn memory_read<'tcx>(
483-
alloc: &Allocation<Tag, Stacks>,
484-
ptr: Pointer<Tag>,
485-
size: Size,
486-
) -> InterpResult<'tcx> {
487-
trace!("read access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
488-
alloc.extra.for_each(ptr, size, |stack, global| {
489-
stack.access(AccessKind::Read, ptr.tag, global)?;
490-
Ok(())
491-
})
492-
}
493-
494-
#[inline(always)]
495-
fn memory_written<'tcx>(
496-
alloc: &mut Allocation<Tag, Stacks>,
497-
ptr: Pointer<Tag>,
498-
size: Size,
499-
) -> InterpResult<'tcx> {
500-
trace!("write access with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
501-
alloc.extra.for_each(ptr, size, |stack, global| {
502-
stack.access(AccessKind::Write, ptr.tag, global)?;
503-
Ok(())
504-
})
505-
}
506-
507-
#[inline(always)]
508-
fn memory_deallocated<'tcx>(
509-
alloc: &mut Allocation<Tag, Stacks>,
510-
ptr: Pointer<Tag>,
511-
size: Size,
512-
) -> InterpResult<'tcx> {
513-
trace!("deallocation with tag {:?}: {:?}, size {}", ptr.tag, ptr.erase_tag(), size.bytes());
514-
alloc.extra.for_each(ptr, size, |stack, global| {
515-
stack.dealloc(ptr.tag, global)
516-
})
517-
}
518-
}
519-
520481
/// Retagging/reborrowing. There is some policy in here, such as which permissions
521482
/// to grant for which references, and when to add protectors.
522483
impl<'mir, 'tcx> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@@ -553,14 +514,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
553514
// We are only ever `SharedReadOnly` inside the frozen bits.
554515
let perm = if frozen { Permission::SharedReadOnly } else { Permission::SharedReadWrite };
555516
let item = Item { perm, tag: new_tag, protector };
556-
alloc.extra.for_each(cur_ptr, size, |stack, global| {
517+
alloc.extra.stacks.for_each(cur_ptr, size, |stack, global| {
557518
stack.grant(cur_ptr.tag, item, global)
558519
})
559520
});
560521
}
561522
};
562523
let item = Item { perm, tag: new_tag, protector };
563-
alloc.extra.for_each(ptr, size, |stack, global| {
524+
alloc.extra.stacks.for_each(ptr, size, |stack, global| {
564525
stack.grant(ptr.tag, item, global)
565526
})
566527
}
@@ -587,7 +548,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
587548
// Compute new borrow.
588549
let new_tag = match kind {
589550
RefKind::Raw { .. } => Tag::Untagged,
590-
_ => Tag::Tagged(this.memory().extra.borrow_mut().new_ptr()),
551+
_ => Tag::Tagged(this.memory().extra.stacked.borrow_mut().new_ptr()),
591552
};
592553

593554
// Reborrow.
@@ -621,7 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
621582
ty::RawPtr(tym) if kind == RetagKind::Raw =>
622583
Some((RefKind::Raw { mutable: tym.mutbl == MutMutable }, false)),
623584
// Boxes do not get a protector: protectors reflect that references outlive the call
624-
// they were passed in to; that's just not the case for boxes.
585+
// they were passed in to; that's just not the case for boxes.
625586
ty::Adt(..) if ty.is_box() => Some((RefKind::Unique { two_phase: false }, false)),
626587
_ => None,
627588
}

0 commit comments

Comments
 (0)