Skip to content

Commit

Permalink
Intercept from_size_align(), alloc_zeroed(), and alloc(), allowing ba…
Browse files Browse the repository at this point in the history
…se64 example

to work without xargo.
  • Loading branch information
David Renshaw committed Jun 26, 2017
1 parent 314abfc commit 9c9b572
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 14 deletions.
23 changes: 10 additions & 13 deletions example/standalone/base64.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
// SEER lets us decode base64, given only an encoder function!

const BUFFER_LENGTH: usize = 1024;
// Seer lets us decode base64, given only an encoder function!

fn main() {
use std::io::Read;
let value_to_decode = b"aGVsbG8gd29ybGQh";

// We avoid heap allocations because they require liballoc to be compiled with MIR.
// See https://github.com/dwrensha/seer/issues/1
let mut data = [0u8; BUFFER_LENGTH];
let input_len = (value_to_decode.len() + 3) / 4 * 3;
std::io::stdin().read_exact(&mut data[..input_len]).unwrap();
let value_to_decode = "aGVsbG8gd29ybGQh";
let mut data: Vec<u8> = vec![0; (value_to_decode.len() + 3) / 4 * 3];
std::io::stdin().read_exact(&mut data[..]).unwrap();

let mut result = [0; BUFFER_LENGTH];
base64_encode(&data[..input_len], &mut result[..]);
let result = base64_encode(&data[..]);
if result.starts_with(value_to_decode) {
// This will panic on the input that encodes to `value_to_decode`.
panic!("we found it!");
}
}

// copied from rustc_serialize
fn base64_encode(input: &[u8], output: &mut [u8]) {
fn base64_encode(input: &[u8]) -> String {
static BYTES: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let mut result = String::new();
{
let len = input.len();
let output = unsafe { result.as_mut_vec() };
*output = vec![b'='; (len + 2) / 3 * 4];
let mod_len = len % 3;
{
let mut s_in = input[..len - mod_len].iter().map(|&x| x as u32);
Expand Down Expand Up @@ -60,4 +56,5 @@ fn base64_encode(input: &[u8], output: &mut [u8]) {
}
}
}
result
}
92 changes: 91 additions & 1 deletion src/terminator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let dest_ptr = self.force_allocation(lval)?.to_ptr();

// FIXME make this more robust
self.memory.write_uint(dest_ptr, 0, 8)?; // discriminant
self.memory.write_uint(dest_ptr, 0, 8)?; // discriminant = Ok
self.memory.write_uint(dest_ptr.offset(8), num_bytes, 8)?; // payload

self.goto_block(block);
Expand All @@ -569,6 +569,96 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
EvalError::Unimplemented(
"no abstract implementation for stdin.lock()".into()));
}
"alloc::allocator::Layout::from_size_align" => {
let (lval, block) = destination.expect("from_size_align() does not diverge");
let dest_ptr = self.force_allocation(lval)?.to_ptr();

let args_res: EvalResult<Vec<Value>> = arg_operands.iter()
.map(|arg| self.eval_operand(arg))
.collect();
let args = args_res?;

let usize = self.tcx.types.usize;
let size = self.value_to_primval(args[0], usize)?.to_u128()?;
let align = self.value_to_primval(args[1], usize)?.to_u128()?;

if !align.is_power_of_two() {
unimplemented!();
}

if size as usize > ::std::usize::MAX - (align as usize - 1) {
unimplemented!();
}

// FIXME make this more robust
self.memory.write_uint(dest_ptr, 1, 8)?; // discriminant = Some

// payload
self.memory.write_uint(dest_ptr.offset(8), size, 8)?;
self.memory.write_uint(dest_ptr.offset(16), align, 8)?;

self.goto_block(block);
return Ok(true);
}
"<alloc::heap::HeapAlloc as alloc::allocator::Alloc>::alloc_zeroed" => {
let (lval, block) = destination.expect("alloc_zeroed() does not diverge");
let dest_ptr = self.force_allocation(lval)?.to_ptr();

let args_res: EvalResult<Vec<Value>> = arg_operands.iter()
.map(|arg| self.eval_operand(arg))
.collect();
let args = args_res?;

let (size, align) = match args[1] {
Value::ByRef(ptr) => {
(self.memory.read_uint(ptr, 8)?.to_u64()?,
self.memory.read_uint(ptr.offset(8), 8)?.to_u64()?)
}
Value::ByValPair(_size, _align) => {
unimplemented!()
}
Value::ByVal(_) => unreachable!(),
};

let ptr = self.memory.allocate(size, align)?;
self.memory.write_repeat(ptr, 0, size)?;

self.memory.write_uint(dest_ptr, 0, 8)?; // discriminant = Ok
self.memory.write_ptr(dest_ptr.offset(8), ptr)?;

self.goto_block(block);
return Ok(true);
}

"<alloc::heap::HeapAlloc as alloc::allocator::Alloc>::alloc" => {
let (lval, block) = destination.expect("alloc() does not diverge");
let dest_ptr = self.force_allocation(lval)?.to_ptr();

let args_res: EvalResult<Vec<Value>> = arg_operands.iter()
.map(|arg| self.eval_operand(arg))
.collect();
let args = args_res?;

let (size, align) = match args[1] {
Value::ByRef(ptr) => {
(self.memory.read_uint(ptr, 8)?.to_u64()?,
self.memory.read_uint(ptr.offset(8), 8)?.to_u64()?)
}
Value::ByValPair(_size, _align) => {
unimplemented!()
}
Value::ByVal(_) => unreachable!(),
};

let ptr = self.memory.allocate(size, align)?;

self.memory.write_uint(dest_ptr, 0, 8)?; // discriminant = Ok
self.memory.write_ptr(dest_ptr.offset(8), ptr)?;

self.goto_block(block);
return Ok(true);
}

_ => (),
}
}
Expand Down

0 comments on commit 9c9b572

Please sign in to comment.