Skip to content

Commit

Permalink
more fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
brockelmore committed Jul 20, 2024
1 parent 1128db4 commit 46a5594
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 611 deletions.
4 changes: 4 additions & 0 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ struct Args {

#[clap(long)]
pub minimize_debug: Option<String>,

#[clap(long, default_value = "false")]
pub debug_stack: bool,
}

pub fn subscriber() {
Expand Down Expand Up @@ -243,6 +246,7 @@ fn main() {
root: Root::RemappingsDirectory(env::current_dir().unwrap()),
debug_panic: args.debug_panic || args.minimize_debug.is_some(),
minimize_debug: args.minimize_debug,
debug_stack: args.debug_stack,
..Default::default()
};

Expand Down
2 changes: 1 addition & 1 deletion crates/graph/src/nodes/var_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl VarNode {
let init = analyzer.parse_expr(arena, &expr, Some(parent));
let underlying = self.underlying(analyzer)?;
let target_ty = VarType::try_from_idx(analyzer, underlying.ty).unwrap();
let initer_ty = ContextVarNode::from(init).ty(analyzer)?.clone();
let initer_ty = VarType::try_from_idx(analyzer, init).unwrap();

let mut set = false;
if let Some(initer) = initer_ty.try_cast(&target_ty, analyzer)? {
Expand Down
2 changes: 1 addition & 1 deletion crates/graph/src/var_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ impl VarType {
(Self::Concrete(from), Self::BuiltIn(to, _)) => {
let from = from.underlying(analyzer)?.as_builtin();
let to = to.underlying(analyzer)?;
Ok(from.implicitly_castable_to(&to))
Ok(from.implicitly_castable_to(to))
}
(Self::BuiltIn(from, _), Self::Concrete(to)) => {
let from = from.underlying(analyzer)?;
Expand Down
2 changes: 2 additions & 0 deletions crates/pyrometer/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub struct Analyzer {
pub flattened: Vec<FlatExpr>,
pub expr_flag: Option<ExprFlag>,
pub current_asm_block: usize,
pub debug_stack: bool,
}

impl Default for Analyzer {
Expand Down Expand Up @@ -191,6 +192,7 @@ impl Default for Analyzer {
flattened: vec![],
expr_flag: None,
current_asm_block: 0,
debug_stack: false,
};
a.builtin_fn_inputs = builtin_fns::builtin_fns_inputs(&mut a);

Expand Down
4 changes: 4 additions & 0 deletions crates/pyrometer/src/analyzer_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,4 +581,8 @@ impl AnalyzerLike for Analyzer {
fn expr_stack_mut(&mut self) -> &mut Vec<FlatExpr> {
&mut self.flattened
}

fn debug_stack(&self) -> bool {
self.debug_stack
}
}
4 changes: 2 additions & 2 deletions crates/pyrometer/tests/test_data/function_calls.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ contract C is S1, S2 {
return 0;
}

function a(uint256 x) internal pure override(A, B) returns (uint) {
function a(uint256 x) internal pure override(S1, S2) returns (uint) {
return 50;
}
}
Expand All @@ -144,7 +144,7 @@ contract D is S2, S1 {
return 0;
}

function a(uint256 x) internal pure override(A, B) returns (uint) {
function a(uint256 x) internal pure override(S1, S2) returns (uint) {
return 50;
}
}
1 change: 1 addition & 0 deletions crates/shared/src/analyzer_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,5 @@ pub trait AnalyzerLike: GraphLike {
fn current_asm_block(&self) -> usize;
fn expr_stack(&self) -> &[Self::FlatExpr];
fn expr_stack_mut(&mut self) -> &mut Vec<Self::FlatExpr>;
fn debug_stack(&self) -> bool;
}
122 changes: 110 additions & 12 deletions crates/solc-expressions/src/context_builder/flattened.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use crate::{
ExprTyParser,
};
use graph::{
elem::{Elem, RangeOp},
elem::{Elem, RangeExpr, RangeOp},
nodes::{
Builtin, Concrete, ConcreteNode, Context, ContextNode, ContextVar, ContextVarNode,
ContractNode, ExprRet, FunctionNode, KilledKind, StructNode, YulFunction,
ContractNode, ExprRet, FunctionNode, KilledKind, StructNode, TmpConstruction, YulFunction,
},
AnalyzerBackend, ContextEdge, Edge, Node, TypeNode, VarType,
AnalyzerBackend, ContextEdge, Edge, Node, SolcRange, TypeNode, VarType,
};

use shared::{
Expand Down Expand Up @@ -922,7 +922,9 @@ pub trait Flatten:
ctx.peek_expr_flag(self)
);

// ctx.debug_expr_stack(self);
if self.debug_stack() {
let _ = ctx.debug_expr_stack(self);
}

match next {
Todo(loc, err_str) => Err(ExprErr::Todo(loc, err_str.to_string())),
Expand Down Expand Up @@ -955,9 +957,11 @@ pub trait Flatten:
Variable(..) => self.interp_var(arena, ctx, stack, next, parse_idx),
Assign(..) => self.interp_assign(arena, ctx, next),
List(_, _) => self.interp_list(ctx, stack, next, parse_idx),
This(_) => self.interp_this(ctx, next),
Delete(_) => self.interp_delete(ctx, next),

// Conditional
If { .. } => self.interp_if(arena, ctx, stack, next, parse_idx),
If { .. } => self.interp_if(arena, ctx, stack, next),
Requirement(..) => {
ctx.set_expr_flag(self, ExprFlag::Requirement);
Ok(())
Expand Down Expand Up @@ -998,7 +1002,6 @@ pub trait Flatten:
| BitwiseAnd(loc, ..)
| BitwiseXor(loc, ..)
| BitwiseOr(loc, ..) => self.interp_op(arena, ctx, next, loc, false),
BitwiseNot(..) => self.interp_bit_not(arena, ctx, next),
AssignAdd(loc, ..)
| AssignSubtract(loc, ..)
| AssignMultiply(loc, ..)
Expand All @@ -1009,6 +1012,7 @@ pub trait Flatten:
| AssignXor(loc, ..)
| AssignShiftLeft(loc, ..)
| AssignShiftRight(loc, ..) => self.interp_op(arena, ctx, next, loc, true),
BitwiseNot(..) => self.interp_bit_not(arena, ctx, next),
// Comparator
Not(..) => self.interp_not(arena, ctx, next),
Equal(loc) | NotEqual(loc) | Less(loc) | More(loc) | LessEqual(loc)
Expand All @@ -1029,17 +1033,15 @@ pub trait Flatten:
}

// Semi useless
Parameter(_, _, _) => Ok(()),
Super(..) => unreachable!(),
Parameter(_, _, _) => Ok(()),
Emit(loc) => {
let _ = ctx.pop_n_latest_exprs(1, loc, self).into_expr_err(loc)?;
Ok(())
}
Null(loc) => ctx.push_expr(ExprRet::Null, self).into_expr_err(loc),

// Todo
This(_) => todo!(),
Delete(_) => todo!(),
UnaryPlus(_) => todo!(),
Try { .. } => todo!(),

Expand Down Expand Up @@ -1089,6 +1091,56 @@ pub trait Flatten:
}
}

fn interp_delete(&mut self, ctx: ContextNode, next: FlatExpr) -> Result<(), ExprErr> {
let FlatExpr::Delete(loc) = next else {
unreachable!()
};

let to_delete = ctx
.pop_n_latest_exprs(1, loc, self)
.into_expr_err(loc)?
.swap_remove(0);

self.delete_match(ctx, to_delete, loc)
}

fn delete_match(
&mut self,
ctx: ContextNode,
to_delete: ExprRet,
loc: Loc,
) -> Result<(), ExprErr> {
match to_delete {
ExprRet::CtxKilled(kind) => ctx.kill(self, loc, kind).into_expr_err(loc),
ExprRet::Single(cvar) | ExprRet::SingleLiteral(cvar) => {
let mut new_var = self.advance_var_in_ctx(cvar.into(), loc, ctx).unwrap();
new_var.sol_delete_range(self).into_expr_err(loc)
}
ExprRet::Multi(inner) => inner
.into_iter()
.try_for_each(|i| self.delete_match(ctx, i, loc)),
ExprRet::Null => Ok(()),
}
}

fn interp_this(&mut self, ctx: ContextNode, next: FlatExpr) -> Result<(), ExprErr> {
let FlatExpr::This(loc) = next else {
unreachable!()
};

let var = ContextVar::new_from_contract(
loc,
ctx.associated_contract(self).into_expr_err(loc)?,
self,
)
.into_expr_err(loc)?;
let cvar = self.add_node(Node::ContextVar(var));
ctx.add_var(cvar.into(), self).into_expr_err(loc)?;
self.add_edge(cvar, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(cvar), self)
.into_expr_err(loc)
}

fn interp_test_command(
&mut self,
arena: &mut RangeArena<Elem<Concrete>>,
Expand Down Expand Up @@ -1370,7 +1422,6 @@ pub trait Flatten:
ctx: ContextNode,
stack: &mut Vec<FlatExpr>,
if_expr: FlatExpr,
parse_idx: usize,
) -> Result<(), ExprErr> {
let FlatExpr::If {
loc,
Expand Down Expand Up @@ -1409,6 +1460,7 @@ pub trait Flatten:
let false_killed = false_subctx.is_killed(self).into_expr_err(loc)?
|| false_subctx.unreachable(self, arena).into_expr_err(loc)?;

println!("true killed: {true_killed}, false_killed: {false_killed}");
match (true_killed, false_killed) {
(true, true) => {
// both have been killed, delete the child and dont process the bodies
Expand All @@ -1421,7 +1473,7 @@ pub trait Flatten:

// point the parse index of the parent ctx to the false body
ctx.underlying_mut(self).unwrap().parse_idx =
parse_idx + true_cond + false_cond + true_body;
ctx.parse_idx(self) + true_cond + false_cond + true_body;
for _ in 0..false_body {
self.interpret_step(arena, ctx, loc, stack)?;
}
Expand Down Expand Up @@ -1501,7 +1553,53 @@ pub trait Flatten:
self.handle_require_inner(arena, ctx, &lhs, &rhs, RangeOp::Gte, loc)
}
FlatExpr::Or(..) => {
self.handle_require_inner(arena, ctx, &lhs, &rhs, RangeOp::Or, loc)
let lhs = ContextVarNode::from(lhs.expect_single().into_expr_err(loc)?);
let rhs = ContextVarNode::from(rhs.expect_single().into_expr_err(loc)?);
let elem = Elem::Expr(RangeExpr::new(lhs.into(), RangeOp::Or, rhs.into()));
let range = SolcRange::new(elem.clone(), elem, vec![]);
let new_lhs_underlying = ContextVar {
loc: Some(loc),
name: format!(
"tmp{}({} {} {})",
ctx.new_tmp(self).into_expr_err(loc)?,
lhs.name(self).into_expr_err(loc)?,
RangeOp::Or.to_string(),
rhs.name(self).into_expr_err(loc)?
),
display_name: format!(
"({} {} {})",
lhs.display_name(self).into_expr_err(loc)?,
RangeOp::Or.to_string(),
rhs.display_name(self).into_expr_err(loc)?
),
storage: None,
is_tmp: true,
is_symbolic: lhs.is_symbolic(self).into_expr_err(loc)?
|| rhs.is_symbolic(self).into_expr_err(loc)?,
is_return: false,
tmp_of: Some(TmpConstruction::new(lhs, RangeOp::Or, Some(rhs))),
dep_on: {
let mut deps = lhs.dependent_on(self, true).into_expr_err(loc)?;
deps.extend(rhs.dependent_on(self, true).into_expr_err(loc)?);
Some(deps)
},
ty: VarType::BuiltIn(
self.builtin_or_add(Builtin::Bool).into(),
Some(range),
),
};
let or_var = ContextVarNode::from(self.add_node(new_lhs_underlying));
let node = self.add_concrete_var(ctx, Concrete::Bool(true), loc)?;
ctx.add_var(node, self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
self.handle_require_inner(
arena,
ctx,
&ExprRet::Single(or_var.into()),
&ExprRet::Single(node.into()),
RangeOp::Eq,
loc,
)
}
FlatExpr::And(..) => {
self.handle_require_inner(arena, ctx, &lhs, &rhs, RangeOp::And, loc)
Expand Down
6 changes: 3 additions & 3 deletions crates/solc-expressions/src/func_call/func_caller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ pub trait FuncCaller:
modifier_state: &Option<ModifierState>,
) -> Result<(), ExprErr> {
if !entry_call {
// if let Ok(true) = self.apply(arena, ctx, loc, func_node, params, inputs, &mut vec![]) {
// return Ok(());
// }
if let Ok(true) = self.apply(arena, ctx, loc, func_node, params, inputs, &mut vec![]) {
return Ok(());
}
}

// pseudocode:
Expand Down
35 changes: 5 additions & 30 deletions crates/solc-expressions/src/func_call/intrinsic_call/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,6 @@ pub trait AddressCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> +
fn address_call(&mut self, ctx: ContextNode, func_name: &str, loc: Loc) -> Result<(), ExprErr> {
match func_name {
"delegatecall" | "staticcall" | "call" => self.external_call(ctx, func_name, loc),
"code" => {
// TODO: try to be smarter based on the address input
let bn = self.builtin_or_add(Builtin::DynamicBytes);
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self).into_expr_err(loc)?;
let node = self.add_node(cvar);
ctx.add_var(node.into(), self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(node), self)
.into_expr_err(loc)
}
"codehash" => {
// TODO: try to be smarter based on the address input
let bn = self.builtin_or_add(Builtin::Bytes(32));
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self).into_expr_err(loc)?;
let node = self.add_node(cvar);
ctx.add_var(node.into(), self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(node), self)
.into_expr_err(loc)
}
"balance" => {
// TODO: try to be smarter based on the address input
let bn = self.builtin_or_add(Builtin::Uint(256));
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self).into_expr_err(loc)?;
let node = self.add_node(cvar);
ctx.add_var(node.into(), self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(node), self)
.into_expr_err(loc)
}
"send" => {
let bn = self.builtin_or_add(Builtin::Bool);
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self).into_expr_err(loc)?;
Expand All @@ -53,6 +23,11 @@ pub trait AddressCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> +
ctx.push_expr(ExprRet::Single(node), self)
.into_expr_err(loc)
}
"transfer" => {
// TODO: handle balance stuff. but otherwise, transfer does not
// produce a return value.
Ok(())
}
_ => Err(ExprErr::FunctionNotFound(
loc,
format!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub trait IntrinsicFuncCaller:
// abi
_ if name.starts_with("abi.") => self.abi_call_inner(ctx, name, inputs, loc),
// address
"delegatecall" | "staticcall" | "call" | "code" | "balance" => {
"delegatecall" | "staticcall" | "call" | "send" | "transfer" => {
self.address_call(ctx, name, loc)
}
// array
Expand Down
4 changes: 4 additions & 0 deletions crates/solc-expressions/src/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ pub trait Literal: AnalyzerBackend + Sized {
let range = split
.get(4)
.copied()?
.chars()
.filter(|c| !c.is_whitespace())
.collect::<String>();
let range = range
.trim_start_matches('[')
.trim_end_matches(']')
.split(',')
Expand Down
Loading

0 comments on commit 46a5594

Please sign in to comment.