Skip to content

Commit

Permalink
lint
Browse files Browse the repository at this point in the history
  • Loading branch information
brockelmore committed Dec 11, 2023
1 parent 955dc68 commit c328bcd
Show file tree
Hide file tree
Showing 12 changed files with 955 additions and 1,009 deletions.
210 changes: 96 additions & 114 deletions crates/solc-expressions/src/func_call/intrinsic_call/abi.rs
Original file line number Diff line number Diff line change
@@ -1,128 +1,110 @@
use crate::{
ContextBuilder, ExprErr, IntoExprErr,
};
use crate::{ContextBuilder, ExprErr, IntoExprErr};

use graph::{
nodes::{
Builtin, ContextNode, ContextVar, ExprRet,
},
nodes::{Builtin, ContextNode, ContextVar, ExprRet},
AnalyzerBackend, ContextEdge, Edge, Node,
};

use solang_parser::pt::{Expression, Loc};

impl<T> AbiCaller for T where T: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {}
pub trait AbiCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {
fn abi_call(&mut self, func_name: String, input_exprs: &[Expression], loc: Loc, ctx: ContextNode) -> Result<(), ExprErr> {
fn abi_call(
&mut self,
func_name: String,
input_exprs: &[Expression],
loc: Loc,
ctx: ContextNode,
) -> Result<(), ExprErr> {
match &*func_name {
"abi.decode" => {
// we skip the first because that is what is being decoded.
// TODO: check if we have a concrete bytes value
fn match_decode(
ctx: ContextNode,
loc: &Loc,
ret: ExprRet,
analyzer: &mut impl AnalyzerBackend,
) -> Result<(), ExprErr> {
match ret {
ExprRet::Single(expect_builtin) => {
match analyzer.node(expect_builtin) {
Node::Builtin(_) => {
let var = ContextVar::new_from_builtin(
*loc,
expect_builtin.into(),
analyzer,
)
.into_expr_err(*loc)?;
let node = analyzer.add_node(Node::ContextVar(var));
ctx.add_var(node.into(), analyzer)
.into_expr_err(*loc)?;
analyzer.add_edge(
node,
ctx,
Edge::Context(ContextEdge::Variable),
);
ctx.push_expr(ExprRet::Single(node), analyzer)
.into_expr_err(*loc)?;
Ok(())
}
Node::ContextVar(cvar) => {
let bn = analyzer
.builtin_or_add(
cvar.ty
.as_builtin(analyzer)
.into_expr_err(*loc)?,
)
.into();
let var = ContextVar::new_from_builtin(
*loc, bn, analyzer,
)
.into_expr_err(*loc)?;
let node = analyzer.add_node(Node::ContextVar(var));
ctx.add_var(node.into(), analyzer)
.into_expr_err(*loc)?;
analyzer.add_edge(
node,
ctx,
Edge::Context(ContextEdge::Variable),
);
ctx.push_expr(ExprRet::Single(node), analyzer)
.into_expr_err(*loc)?;
Ok(())
}
e => todo!("Unhandled type in abi.decode: {e:?}"),
}
}
ExprRet::Multi(inner) => inner.iter().try_for_each(|i| {
match_decode(ctx, loc, i.clone(), analyzer)
}),
ExprRet::CtxKilled(kind) => {
ctx.kill(analyzer, *loc, kind).into_expr_err(*loc)
}
e => panic!("This is invalid solidity: {:?}", e),
}
}
self.parse_ctx_expr(&input_exprs[1], ctx)?;
self.apply_to_edges(ctx, loc, &|analyzer, ctx, loc| {
let Some(ret) =
ctx.pop_expr_latest(loc, analyzer).into_expr_err(loc)?
else {
return Err(ExprErr::NoRhs(
loc,
"abi.decode was not given the types for decoding"
.to_string(),
));
};
if matches!(ret, ExprRet::CtxKilled(_)) {
ctx.push_expr(ret, analyzer).into_expr_err(loc)?;
return Ok(());
}
match_decode(ctx, &loc, ret, analyzer)
})
}
"abi.encode"
| "abi.encodePacked"
| "abi.encodeCall"
| "abi.encodeWithSignature"
| "abi.encodeWithSelector" => {
// currently we dont support concrete abi encoding, TODO
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(Node::ContextVar(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)?;
Ok(())
}
_ => Err(ExprErr::FunctionNotFound(
"abi.decode" => {
// we skip the first because that is what is being decoded.
// TODO: check if we have a concrete bytes value
fn match_decode(
ctx: ContextNode,
loc: &Loc,
ret: ExprRet,
analyzer: &mut impl AnalyzerBackend,
) -> Result<(), ExprErr> {
match ret {
ExprRet::Single(expect_builtin) => match analyzer.node(expect_builtin) {
Node::Builtin(_) => {
let var = ContextVar::new_from_builtin(
*loc,
expect_builtin.into(),
analyzer,
)
.into_expr_err(*loc)?;
let node = analyzer.add_node(Node::ContextVar(var));
ctx.add_var(node.into(), analyzer).into_expr_err(*loc)?;
analyzer.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(node), analyzer)
.into_expr_err(*loc)?;
Ok(())
}
Node::ContextVar(cvar) => {
let bn = analyzer
.builtin_or_add(
cvar.ty.as_builtin(analyzer).into_expr_err(*loc)?,
)
.into();
let var = ContextVar::new_from_builtin(*loc, bn, analyzer)
.into_expr_err(*loc)?;
let node = analyzer.add_node(Node::ContextVar(var));
ctx.add_var(node.into(), analyzer).into_expr_err(*loc)?;
analyzer.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(ExprRet::Single(node), analyzer)
.into_expr_err(*loc)?;
Ok(())
}
e => todo!("Unhandled type in abi.decode: {e:?}"),
},
ExprRet::Multi(inner) => inner
.iter()
.try_for_each(|i| match_decode(ctx, loc, i.clone(), analyzer)),
ExprRet::CtxKilled(kind) => {
ctx.kill(analyzer, *loc, kind).into_expr_err(*loc)
}
e => panic!("This is invalid solidity: {:?}", e),
}
}
self.parse_ctx_expr(&input_exprs[1], ctx)?;
self.apply_to_edges(ctx, loc, &|analyzer, ctx, loc| {
let Some(ret) = ctx.pop_expr_latest(loc, analyzer).into_expr_err(loc)? else {
return Err(ExprErr::NoRhs(
loc,
"abi.decode was not given the types for decoding".to_string(),
));
};
if matches!(ret, ExprRet::CtxKilled(_)) {
ctx.push_expr(ret, analyzer).into_expr_err(loc)?;
return Ok(());
}
match_decode(ctx, &loc, ret, analyzer)
})
}
"abi.encode"
| "abi.encodePacked"
| "abi.encodeCall"
| "abi.encodeWithSignature"
| "abi.encodeWithSelector" => {
// currently we dont support concrete abi encoding, TODO
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(Node::ContextVar(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)?;
Ok(())
}
_ => Err(ExprErr::FunctionNotFound(
loc,
format!(
"Could not find abi function: \"{func_name}\", context: {}",
ctx.path(self),
)
))
}
}
}
),
)),
}
}
}
124 changes: 60 additions & 64 deletions crates/solc-expressions/src/func_call/intrinsic_call/address.rs
Original file line number Diff line number Diff line change
@@ -1,79 +1,75 @@
use crate::{
ExprErr, IntoExprErr,
};
use crate::{ExprErr, IntoExprErr};

use graph::{
nodes::{
Builtin, ContextNode, ContextVar, ExprRet,
},
nodes::{Builtin, ContextNode, ContextVar, ExprRet},
AnalyzerBackend, ContextEdge, Edge, Node,
};

use solang_parser::pt::{Expression, Loc};

impl<T> AddressCaller for T where T: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {}
pub trait AddressCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {
fn address_call(&mut self, func_name: String, _input_exprs: &[Expression], loc: Loc, ctx: ContextNode) -> Result<(), ExprErr> {
fn address_call(
&mut self,
func_name: String,
_input_exprs: &[Expression],
loc: Loc,
ctx: ContextNode,
) -> Result<(), ExprErr> {
match &*func_name {
"delegatecall" | "staticcall" | "call" => {
// TODO: Check if we have the code for the address
// if we dont, model it as a unrestricted call that can make other calls
ctx.pop_expr_latest(loc, self).into_expr_err(loc)?;
// TODO: try to be smarter based on the address input
let booln = self.builtin_or_add(Builtin::Bool);
let bool_cvar = ContextVar::new_from_builtin(loc, booln.into(), self)
.into_expr_err(loc)?;
let bool_node = self.add_node(Node::ContextVar(bool_cvar));
ctx.add_var(bool_node.into(), self).into_expr_err(loc)?;
self.add_edge(bool_node, ctx, Edge::Context(ContextEdge::Variable));
"delegatecall" | "staticcall" | "call" => {
// TODO: Check if we have the code for the address
// if we dont, model it as a unrestricted call that can make other calls
ctx.pop_expr_latest(loc, self).into_expr_err(loc)?;
// TODO: try to be smarter based on the address input
let booln = self.builtin_or_add(Builtin::Bool);
let bool_cvar =
ContextVar::new_from_builtin(loc, booln.into(), self).into_expr_err(loc)?;
let bool_node = self.add_node(Node::ContextVar(bool_cvar));
ctx.add_var(bool_node.into(), self).into_expr_err(loc)?;
self.add_edge(bool_node, ctx, Edge::Context(ContextEdge::Variable));

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(Node::ContextVar(cvar));
ctx.add_var(node.into(), self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(
ExprRet::Multi(vec![
ExprRet::Single(bool_node),
ExprRet::Single(node),
]),
self,
)
.into_expr_err(loc)?;
Ok(())
}
"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(Node::ContextVar(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)?;
Ok(())
}
"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(Node::ContextVar(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)?;
Ok(())
}
_ => Err(ExprErr::FunctionNotFound(
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(Node::ContextVar(cvar));
ctx.add_var(node.into(), self).into_expr_err(loc)?;
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable));
ctx.push_expr(
ExprRet::Multi(vec![ExprRet::Single(bool_node), ExprRet::Single(node)]),
self,
)
.into_expr_err(loc)?;
Ok(())
}
"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(Node::ContextVar(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)?;
Ok(())
}
"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(Node::ContextVar(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)?;
Ok(())
}
_ => Err(ExprErr::FunctionNotFound(
loc,
format!(
"Could not find builtin address function: \"{func_name}\", context: {}",
ctx.path(self),
)
))
}
}
}
),
)),
}
}
}
Loading

0 comments on commit c328bcd

Please sign in to comment.