Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retagging: Recurse into compound values #526

Merged
merged 18 commits into from
Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 28 additions & 30 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
}

"free" => {
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation, no tag
let ptr = self.read_scalar(args[0])?.not_undef()?;
if !ptr.is_null_ptr(self) {
self.memory_mut().deallocate(
ptr.to_ptr()?.with_default_tag(),
ptr.to_ptr()?,
None,
MiriMemoryKind::C.into(),
)?;
Expand Down Expand Up @@ -179,7 +179,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
self.write_scalar(Scalar::Ptr(ptr), dest)?;
}
"__rust_dealloc" => {
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
let ptr = self.read_scalar(args[0])?.to_ptr()?;
let old_size = self.read_scalar(args[1])?.to_usize(self)?;
let align = self.read_scalar(args[2])?.to_usize(self)?;
if old_size == 0 {
Expand All @@ -189,13 +189,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
self.memory_mut().deallocate(
ptr.with_default_tag(),
ptr,
Some((Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap())),
MiriMemoryKind::Rust.into(),
)?;
}
"__rust_realloc" => {
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
let ptr = self.read_scalar(args[0])?.to_ptr()?;
let old_size = self.read_scalar(args[1])?.to_usize(self)?;
let align = self.read_scalar(args[2])?.to_usize(self)?;
let new_size = self.read_scalar(args[3])?.to_usize(self)?;
Expand All @@ -206,7 +206,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let new_ptr = self.memory_mut().reallocate(
ptr.with_default_tag(),
ptr,
Size::from_bytes(old_size),
Align::from_bytes(align, align).unwrap(),
Size::from_bytes(new_size),
Expand Down Expand Up @@ -238,8 +238,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

"dlsym" => {
let _handle = self.read_scalar(args[0])?;
let symbol = self.read_scalar(args[1])?.to_ptr()?.erase_tag();
let symbol_name = self.memory().read_c_str(symbol.with_default_tag())?;
let symbol = self.read_scalar(args[1])?.to_ptr()?;
let symbol_name = self.memory().read_c_str(symbol)?;
let err = format!("bad c unicode symbol: {:?}", symbol_name);
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
return err!(Unimplemented(format!(
Expand Down Expand Up @@ -292,13 +292,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
return err!(MachineError("the evaluated program panicked".to_string())),

"memcmp" => {
let left = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let right = self.read_scalar(args[1])?.not_undef()?.erase_tag(); // raw ptr operation
let left = self.read_scalar(args[0])?.not_undef()?;
let right = self.read_scalar(args[1])?.not_undef()?;
let n = Size::from_bytes(self.read_scalar(args[2])?.to_usize(self)?);

let result = {
let left_bytes = self.memory().read_bytes(left.with_default_tag(), n)?;
let right_bytes = self.memory().read_bytes(right.with_default_tag(), n)?;
let left_bytes = self.memory().read_bytes(left, n)?;
let right_bytes = self.memory().read_bytes(right, n)?;

use std::cmp::Ordering::*;
match left_bytes.cmp(right_bytes) {
Expand All @@ -315,8 +315,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
}

"memrchr" => {
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let ptr = ptr.with_default_tag();
let ptr = self.read_scalar(args[0])?.not_undef()?;
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
let num = self.read_scalar(args[2])?.to_usize(self)?;
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?
Expand All @@ -330,8 +329,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
}

"memchr" => {
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let ptr = ptr.with_default_tag();
let ptr = self.read_scalar(args[0])?.not_undef()?;
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
let num = self.read_scalar(args[2])?.to_usize(self)?;
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?.iter().position(
Expand All @@ -347,8 +345,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

"getenv" => {
let result = {
let name_ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation
let name = self.memory().read_c_str(name_ptr.with_default_tag())?;
let name_ptr = self.read_scalar(args[0])?.to_ptr()?;
let name = self.memory().read_c_str(name_ptr)?;
match self.machine.env_vars.get(name) {
Some(&var) => Scalar::Ptr(var),
None => Scalar::ptr_null(&*self.tcx),
Expand All @@ -360,10 +358,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
"unsetenv" => {
let mut success = None;
{
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let name_ptr = self.read_scalar(args[0])?.not_undef()?;
if !name_ptr.is_null_ptr(self) {
let name = self.memory().read_c_str(name_ptr.to_ptr()?
.with_default_tag())?.to_owned();
)?.to_owned();
if !name.is_empty() && !name.contains(&b'=') {
success = Some(self.machine.env_vars.remove(&name));
}
Expand All @@ -382,11 +380,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
"setenv" => {
let mut new = None;
{
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let value_ptr = self.read_scalar(args[1])?.to_ptr()?.erase_tag(); // raw ptr operation
let value = self.memory().read_c_str(value_ptr.with_default_tag())?;
let name_ptr = self.read_scalar(args[0])?.not_undef()?;
let value_ptr = self.read_scalar(args[1])?.to_ptr()?;
let value = self.memory().read_c_str(value_ptr)?;
if !name_ptr.is_null_ptr(self) {
let name = self.memory().read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
let name = self.memory().read_c_str(name_ptr.to_ptr()?)?;
if !name.is_empty() && !name.contains(&b'=') {
new = Some((name.to_owned(), value.to_owned()));
}
Expand Down Expand Up @@ -417,14 +415,14 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

"write" => {
let fd = self.read_scalar(args[0])?.to_bytes()?;
let buf = self.read_scalar(args[1])?.not_undef()?.erase_tag();
let buf = self.read_scalar(args[1])?.not_undef()?;
let n = self.read_scalar(args[2])?.to_bytes()? as u64;
trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
let result = if fd == 1 || fd == 2 {
// stdout/stderr
use std::io::{self, Write};

let buf_cont = self.memory().read_bytes(buf.with_default_tag(), Size::from_bytes(n))?;
let buf_cont = self.memory().read_bytes(buf, Size::from_bytes(n))?;
let res = if fd == 1 {
io::stdout().write(buf_cont)
} else {
Expand All @@ -445,8 +443,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
}

"strlen" => {
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag();
let n = self.memory().read_c_str(ptr.with_default_tag())?.len();
let ptr = self.read_scalar(args[0])?.to_ptr()?;
let n = self.memory().read_c_str(ptr)?.len();
self.write_scalar(Scalar::from_uint(n as u64, dest.layout.size), dest)?;
}

Expand Down Expand Up @@ -492,7 +490,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

// Hook pthread calls that go to the thread-local storage memory subsystem
"pthread_key_create" => {
let key_ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation
let key_ptr = self.read_scalar(args[0])?.to_ptr()?;

// Extract the function type out of the signature (that seems easier than constructing it ourselves...)
let dtor = match self.read_scalar(args[1])?.not_undef()? {
Expand All @@ -515,7 +513,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
return err!(OutOfTls);
}
self.memory_mut().write_scalar(
key_ptr.with_default_tag(),
key_ptr,
key_layout.align,
Scalar::from_uint(key, key_layout.size).into(),
key_layout.size,
Expand Down
8 changes: 5 additions & 3 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,10 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
unsafe_cell_action: F,
}

impl<'ecx, 'a, 'mir, 'tcx, F> ValueVisitor<'a, 'mir, 'tcx, Evaluator<'tcx>>
for UnsafeCellVisitor<'ecx, 'a, 'mir, 'tcx, F>
impl<'ecx, 'a, 'mir, 'tcx, F>
ValueVisitor<'a, 'mir, 'tcx, Evaluator<'tcx>>
for
UnsafeCellVisitor<'ecx, 'a, 'mir, 'tcx, F>
where
F: FnMut(MPlaceTy<'tcx, Borrow>) -> EvalResult<'tcx>
{
Expand Down Expand Up @@ -230,7 +232,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
}

// We should never get to a primitive, but always short-circuit somewhere above
fn visit_primitive(&mut self, _val: ImmTy<'tcx, Borrow>) -> EvalResult<'tcx>
fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Borrow>) -> EvalResult<'tcx>
{
bug!("We should always short-circit before coming to a primitive")
}
Expand Down
10 changes: 5 additions & 5 deletions src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
let count = self.read_scalar(args[2])?.to_usize(self)?;
let elem_align = elem_layout.align;
// erase tags: this is a raw ptr operation
let src = self.read_scalar(args[0])?.not_undef()?.erase_tag();
let dest = self.read_scalar(args[1])?.not_undef()?.erase_tag();
let src = self.read_scalar(args[0])?.not_undef()?;
let dest = self.read_scalar(args[1])?.not_undef()?;
self.memory_mut().copy(
src.with_default_tag(),
src,
elem_align,
dest.with_default_tag(),
dest,
elem_align,
Size::from_bytes(count * elem_size),
intrinsic_name.ends_with("_nonoverlapping"),
Expand Down Expand Up @@ -436,7 +436,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
let ty = substs.type_at(0);
let ty_layout = self.layout_of(ty)?;
let val_byte = self.read_scalar(args[1])?.to_u8()?;
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag().with_default_tag();
let ptr = self.read_scalar(args[0])?.not_undef()?;
let count = self.read_scalar(args[2])?.to_usize(self)?;
self.memory().check_align(ptr, ty_layout.align)?;
self.memory_mut().write_repeat(ptr, val_byte, ty_layout.size * count)?;
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,9 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
// No tracking
Ok(place.ptr)
} else {
let ptr = place.ptr.to_ptr()?; // assert this is not a scalar
let tag = ecx.tag_dereference(place, size, mutability.into())?;
Ok(Scalar::Ptr(Pointer::new_with_tag(ptr.alloc_id, ptr.offset, tag)))
ecx.ptr_dereference(place, size, mutability.into())?;
// We never change the pointer
Ok(place.ptr)
}
}

Expand Down
Loading