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

Comment unsafe. Introduce pop_top #51

Merged
merged 1 commit into from
Feb 19, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions bins/revm-test/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ pub fn simple_example() {
fn main() {
println!("Hello, world!");
simple_example();
println!("end!");
}
1 change: 1 addition & 0 deletions bins/revme/src/debugger/ctrl/ctrl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ impl Controller {
}
}
}

///
impl<DB: Database> Inspector<DB> for Controller {
fn step(
Expand Down
2 changes: 2 additions & 0 deletions bins/revme/src/statetest/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
data: &mut EVMData<'_, DB>,
_is_static: bool,
) -> Return {
// Safety: casting. In analazis we are making this clame true that program counter will always
// point to bytecode of the contract.
let opcode = unsafe { *machine.program_counter };
let opcode_str = opcode::OPCODE_JUMPMAP[opcode as usize];

Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/db/web3db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl Web3DB {
}

/// internal utility function to call tokio feature and wait for output
fn block_on<F: std::future::Future>(&self, f: F) -> F::Output {
fn block_on<F: core::future::Future>(&self, f: F) -> F::Output {
match &self.runtime {
Some(runtime) => runtime.block_on(f),
None => futures::executor::block_on(f),
Expand Down
4 changes: 3 additions & 1 deletion crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
BerlinSpec, ByzantineSpec, Env, Inspector, IstanbulSpec, LatestSpec, Log, LondonSpec,
NoOpInspector, Return, Spec, SpecId, TransactOut,
};
use alloc::boxed::Box;
use alloc::{boxed::Box, vec::Vec};
use revm_precompiles::Precompiles;
/// Struct that takes Database and enabled transact to update state dirrectly to database.
/// additionaly it allows user to set all environment parameters.
Expand All @@ -23,6 +23,8 @@ use revm_precompiles::Precompiles;
/// want to update anything on it. It enabled `transact_ref` and `inspect_ref` functions
/// * Database+DatabaseCommit allow's dirrectly commiting changes of transaction. it enabled `transact_commit`
/// and `inspect_commit`

#[derive(Clone)]
pub struct EVM<DB> {
pub env: Env,
pub db: Option<DB>,
Expand Down
10 changes: 4 additions & 6 deletions crates/revm/src/instructions/i256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct I256(pub Sign, pub U256);

#[inline(always)]
pub fn i256_sign<const DO_TWO_COMPL: bool>(val: &mut U256) -> Sign {
if unsafe { val.0.get_unchecked(3) } & SIGN_BITMASK_U64 == 0 {
if val.0[3] & SIGN_BITMASK_U64 == 0 {
if val.is_zero() {
Sign::Zero
} else {
Expand All @@ -45,9 +45,7 @@ pub fn i256_sign<const DO_TWO_COMPL: bool>(val: &mut U256) -> Sign {

#[inline(always)]
fn u256_remove_sign(val: &mut U256) {
unsafe {
*val.0.get_unchecked_mut(3) = val.0.get_unchecked(3) & FLIPH_BITMASK_U64;
}
val.0[3] &= FLIPH_BITMASK_U64;
}

#[inline(always)]
Expand Down Expand Up @@ -438,11 +436,11 @@ mod tests {
let mut f = U256([1, 100, 1, 1]);
let mut s = U256([0, 0, 10, 0]);

let time = std::time::Instant::now();
//let time = std::time::Instant::now();
for i in 0..1_000_000 {
f.0[1] = i;
s.0[3] = div_u256::div_mod(f, s).0 .0[3];
}
println!("TIME:{:?}", time.elapsed());
//println!("TIME:{:?}", time.elapsed());
}
}
90 changes: 52 additions & 38 deletions crates/revm/src/instructions/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ macro_rules! pop_address {
return Return::StackUnderflow;
}
let mut temp = H256::zero();
// Safety: Length is checked above.
let $x1: H160 = {
unsafe {
$machine
Expand All @@ -93,6 +94,7 @@ macro_rules! pop_address {
}
let mut temp = H256::zero();
$x1: H160 = {
// Safety: Length is checked above.
unsafe {
$machine
.stack
Expand All @@ -103,6 +105,7 @@ macro_rules! pop_address {
};
$x2: H160 = {
temp = H256::zero();
// Safety: Length is checked above.
unsafe {
$machine
.stack
Expand All @@ -119,29 +122,57 @@ macro_rules! pop {
if $machine.stack.len() < 1 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let $x1 = unsafe { $machine.stack.pop_unsafe() };
};
( $machine:expr, $x1:ident, $x2:ident) => {
if $machine.stack.len() < 2 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let ($x1, $x2) = unsafe { $machine.stack.pop2_unsafe() };
};
( $machine:expr, $x1:ident, $x2:ident, $x3:ident) => {
if $machine.stack.len() < 3 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let ($x1, $x2, $x3) = unsafe { $machine.stack.pop3_unsafe() };
};

( $machine:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident) => {
if $machine.stack.len() < 4 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let ($x1, $x2, $x3, $x4) = unsafe { $machine.stack.pop4_unsafe() };
};
}

macro_rules! pop_top {
( $machine:expr, $x1:ident) => {
if $machine.stack.len() < 1 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let $x1 = unsafe { $machine.stack.top_unsafe() };
};
( $machine:expr, $x1:ident, $x2:ident) => {
if $machine.stack.len() < 2 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let ($x1, $x2) = unsafe { $machine.stack.pop_top_unsafe() };
};
( $machine:expr, $x1:ident, $x2:ident, $x3:ident) => {
if $machine.stack.len() < 3 {
return Return::StackUnderflow;
}
// Safety: Length is checked above.
let ($x1, $x2, $x3) = unsafe { $machine.stack.pop2_top_unsafe() };
};
}

macro_rules! push_h256 {
( $machine:expr, $( $x:expr ),* ) => (
$(
Expand All @@ -167,9 +198,8 @@ macro_rules! push {
macro_rules! op1_u256_fn {
( $machine:expr, $op:path ) => {{
//gas!($machine, $gas);
pop!($machine, op1);
let ret = $op(op1);
push!($machine, ret);
pop_top!($machine, op1);
*op1 = $op(*op1);

Return::Continue
}};
Expand All @@ -178,9 +208,9 @@ macro_rules! op1_u256_fn {
macro_rules! op2_u256_bool_ref {
( $machine:expr, $op:ident) => {{
//gas!($machine, $gas);
pop!($machine, op1, op2);
pop_top!($machine, op1, op2);
let ret = op1.$op(&op2);
push!($machine, if ret { U256::one() } else { U256::zero() });
*op2 = if ret { U256::one() } else { U256::zero() };

Return::Continue
}};
Expand All @@ -189,10 +219,8 @@ macro_rules! op2_u256_bool_ref {
macro_rules! op2_u256 {
( $machine:expr, $op:ident) => {{
//gas!($machine, $gas);
pop!($machine, op1, op2);
let ret = op1.$op(op2);
push!($machine, ret);

pop_top!($machine, op1, op2);
*op2 = op1.$op(*op2);
Return::Continue
}};
}
Expand All @@ -201,16 +229,16 @@ macro_rules! op2_u256_tuple {
( $machine:expr, $op:ident) => {{
//gas!($machine, $gas);

pop!($machine, op1, op2);
let (ret, ..) = op1.$op(op2);
push!($machine, ret);
pop_top!($machine, op1, op2);
let (ret, ..) = op1.$op(*op2);
*op2 = ret;

Return::Continue
}};
( $machine:expr, $op:ident ) => {{
pop!($machine, op1, op2);
pop_top!($machine, op1, op2);
let (ret, ..) = op1.$op(op2);
push!($machine, ret);
*op2 = ret;

Return::Continue
}};
Expand All @@ -220,9 +248,8 @@ macro_rules! op2_u256_fn {
( $machine:expr, $op:path ) => {{
//gas!($machine, $gas);

pop!($machine, op1, op2);
let ret = $op(op1, op2);
push!($machine, ret);
pop_top!($machine, op1, op2);
*op2 = $op(op1, *op2);

Return::Continue
}};
Expand All @@ -236,9 +263,8 @@ macro_rules! op3_u256_fn {
( $machine:expr, $op:path) => {{
//gas!($machine, $gas);

pop!($machine, op1, op2, op3);
let ret = $op(op1, op2, op3);
push!($machine, ret);
pop_top!($machine, op1, op2, op3);
*op3 = $op(op1, op2, *op3);

Return::Continue
}};
Expand All @@ -250,40 +276,28 @@ macro_rules! op3_u256_fn {

macro_rules! as_usize_saturated {
( $v:expr ) => {{
if unsafe {
*$v.0.get_unchecked(1) != 0
|| *$v.0.get_unchecked(2) != 0
|| *$v.0.get_unchecked(3) != 0
} {
if $v.0[1] != 0 || $v.0[2] != 0 || $v.0[3] != 0 {
usize::MAX
} else {
unsafe { *$v.0.get_unchecked(0) as usize }
$v.0[0] as usize
}
}};
}

macro_rules! as_usize_or_fail {
( $v:expr ) => {{
if unsafe {
*$v.0.get_unchecked(1) != 0
|| *$v.0.get_unchecked(2) != 0
|| *$v.0.get_unchecked(3) != 0
} {
if $v.0[1] != 0 || $v.0[2] != 0 || $v.0[3] != 0 {
return Return::OutOfGas;
}

unsafe { *$v.0.get_unchecked(0) as usize }
$v.0[0] as usize
}};

( $v:expr, $reason:expr ) => {{
if unsafe {
*$v.0.get_unchecked(1) != 0
|| *$v.0.get_unchecked(2) != 0
|| *$v.0.get_unchecked(3) != 0
} {
if $v.0[1] != 0 || $v.0[2] != 0 || $v.0[3] != 0 {
return $reason;
}

unsafe { *$v.0.get_unchecked(0) as usize }
$v.0[0] as usize
}};
}
10 changes: 9 additions & 1 deletion crates/revm/src/instructions/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub fn codecopy(machine: &mut Machine) -> Return {
let code_offset = as_usize_saturated!(code_offset);
memory_resize!(machine, memory_offset, len);

// Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it
machine
.memory
.set_data(memory_offset, code_offset, len, &machine.contract.code);
Expand Down Expand Up @@ -68,6 +69,7 @@ pub fn calldatacopy(machine: &mut Machine) -> Return {
let data_offset = as_usize_saturated!(data_offset);
memory_resize!(machine, memory_offset, len);

// Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it
machine
.memory
.set_data(memory_offset, data_offset, len, &machine.contract.input);
Expand Down Expand Up @@ -111,7 +113,7 @@ pub fn mstore8(machine: &mut Machine) -> Return {
let index = as_usize_or_fail!(index, Return::OutOfGas);
memory_resize!(machine, index, 1);
let value = (value.low_u32() & 0xff) as u8;
// SAFETY: we resized our memory two lines above.
// Safety: we resized our memory two lines above.
unsafe { machine.memory.set_byte(index, value) }
Return::Continue
}
Expand All @@ -123,6 +125,8 @@ pub fn jump(machine: &mut Machine) -> Return {
let dest = as_usize_or_fail!(dest, Return::InvalidJump);

if machine.contract.is_valid_jump(dest) {
// Safety: In analazis we are checking create our jump table and we do check above to be
// sure that jump is safe to execute.
machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) };
Return::Continue
} else {
Expand All @@ -138,6 +142,8 @@ pub fn jumpi(machine: &mut Machine) -> Return {
if !value.is_zero() {
let dest = as_usize_or_fail!(dest, Return::InvalidJump);
if machine.contract.is_valid_jump(dest) {
// Safety: In analazis we are checking if jump is valid destination and this if.
// make this unsafe block safe.
machine.program_counter = unsafe { machine.contract.code.as_ptr().add(dest) };
Return::Continue
} else {
Expand Down Expand Up @@ -172,6 +178,8 @@ pub fn push<const N: usize>(machine: &mut Machine) -> Return {
//gas!(machine, gas::VERYLOW);

let start = machine.program_counter;
// Safety: In Analazis we appended needed bytes for bytecode so that we are safe to just add without
// checking if it is out of bound. This makes both of our unsafes block safe to do.
let ret = machine
.stack
.push_slice::<N>(unsafe { core::slice::from_raw_parts(start, N) });
Expand Down
3 changes: 2 additions & 1 deletion crates/revm/src/instructions/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub fn extcodecopy<H: Host, SPEC: Spec>(machine: &mut Machine, host: &mut H) ->
let code_offset = min(as_usize_saturated!(code_offset), code.len());
memory_resize!(machine, memory_offset, len);

// Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it
machine
.memory
.set_data(memory_offset, code_offset, len, &code);
Expand Down Expand Up @@ -289,8 +290,8 @@ pub fn log<H: Host, SPEC: Spec>(machine: &mut Machine, n: u8, host: &mut H) -> R

let mut topics = Vec::with_capacity(n);
for _ in 0..(n) {
/*** SAFETY stack bounds already checked few lines above */
let mut t = H256::zero();
// Sefety: stack bounds already checked few lines above
unsafe { machine.stack.pop_unsafe().to_big_endian(t.as_bytes_mut()) };
topics.push(t);
}
Expand Down
3 changes: 1 addition & 2 deletions crates/revm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![allow(dead_code)]
//#![forbid(unsafe_code, unused_variables, unused_imports)]
//#![no_std] only blocker in auto_impl check: https://github.com/bluealloy/revm/issues/4
//#![no_std]

pub mod db;
mod evm;
Expand Down
4 changes: 4 additions & 0 deletions crates/revm/src/machine/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Machine {

/// Return a reference of the program counter.
pub fn program_counter(&self) -> usize {
// Sefety: this is just substraction of pointers, it is safe to do.
unsafe {
self.program_counter
.offset_from(self.contract.code.as_ptr()) as usize
Expand All @@ -186,6 +187,9 @@ impl Machine {
}
}
let opcode = unsafe { *self.program_counter };
// Safety: In analazis we are doing padding of bytecode so that we are sure that last.
// byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction
// it will do noop and just stop execution of this contract
self.program_counter = unsafe { self.program_counter.offset(1) };
ret = eval::<H, SPEC>(opcode, self, host);

Expand Down
Loading