Skip to content

Commit

Permalink
Change storagelocation to include block and msg + fix benches
Browse files Browse the repository at this point in the history
  • Loading branch information
brockelmore committed Dec 8, 2023
1 parent 357d1c9 commit 3d1b17a
Show file tree
Hide file tree
Showing 20 changed files with 516 additions and 42 deletions.
378 changes: 371 additions & 7 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ petgraph = "0.6.2"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

# [dev-dependencies]
# criterion = { version = "0.4"} # benching

# [workspace]
# members = ["cli", "shared"]

Expand Down
6 changes: 5 additions & 1 deletion crates/analyzers/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::{FunctionVarsBoundAnalysis, LocSpan, LocStrSpan, ReportConfig, VarBou
use graph::{
nodes::ContextNode, range_string::ToRangeString, GraphBackend, Range, RangeEval, SolcRange,
};
use shared::StorageLocation;

use ariadne::{Color, Fmt, Label, Span};
use solang_parser::pt::StorageLocation;
use std::collections::{BTreeMap, BTreeSet};

pub static MIN_COLOR: Color = Color::Fixed(111);
Expand Down Expand Up @@ -171,6 +171,8 @@ impl From<AnalysisItem> for Label<LocStrSpan> {
Some(StorageLocation::Memory(..)) => Color::Blue,
Some(StorageLocation::Storage(..)) => Color::Green,
Some(StorageLocation::Calldata(..)) => Color::White,
Some(StorageLocation::Block(..)) => Color::Magenta,
Some(StorageLocation::Msg(..)) => Color::Cyan,
None => Color::Cyan,
},
val.order,
Expand All @@ -185,6 +187,8 @@ impl From<AnalysisItem> for Label<LocStrSpan> {
Some(StorageLocation::Memory(..)) => "Memory var ",
Some(StorageLocation::Storage(..)) => "Storage var ",
Some(StorageLocation::Calldata(..)) => "Calldata var ",
Some(StorageLocation::Block(..)) => "Block var ",
Some(StorageLocation::Msg(..)) => "Msg var ",
None => "",
},
val.name,
Expand Down
4 changes: 2 additions & 2 deletions crates/analyzers/src/var_analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use graph::{
nodes::{ContextNode, ContextVarNode, KilledKind},
AnalyzerBackend, GraphBackend, Range, SolcRange,
};
use shared::Search;
use shared::{StorageLocation, Search};

use std::collections::BTreeSet;

use solang_parser::pt::{CodeLocation, StorageLocation};
use solang_parser::pt::CodeLocation;
use std::collections::BTreeMap;

mod report_display;
Expand Down
4 changes: 2 additions & 2 deletions crates/graph/src/nodes/context/var/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use crate::{
AsDotStr, ContextEdge, Edge, GraphBackend, GraphError, Node,
};

use shared::{NodeIdx, Search};
use shared::{NodeIdx, Search, StorageLocation};

use petgraph::{visit::EdgeRef, Direction};
use solang_parser::pt::{Loc, StorageLocation};
use solang_parser::pt::Loc;

use std::collections::BTreeMap;

Expand Down
22 changes: 19 additions & 3 deletions crates/graph/src/nodes/context/var/typing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use crate::{
AnalyzerBackend, ContextEdge, Edge, GraphBackend, GraphError, Node, VarType,
};

use shared::Search;
use shared::{StorageLocation, Search};

use petgraph::Direction;
use solang_parser::pt::{Loc, StorageLocation};
use solang_parser::pt::Loc;

impl ContextVarNode {
pub fn ty<'a>(&self, analyzer: &'a impl GraphBackend) -> Result<&'a VarType, GraphError> {
Expand Down Expand Up @@ -66,6 +66,8 @@ impl ContextVarNode {

Ok((global_first.is_storage(analyzer)?
|| global_first.is_calldata_input(analyzer)
|| global_first.is_msg(analyzer)?
|| global_first.is_block(analyzer)?
|| (
// if its a function input, and we are evaluating the function
// as a standalone (i.e. its internal, but we are treating it like its external)
Expand All @@ -84,7 +86,7 @@ impl ContextVarNode {
}

pub fn is_controllable(&self, analyzer: &impl GraphBackend) -> Result<bool, GraphError> {
if self.is_storage_or_calldata_input(analyzer)? {
if self.is_storage_or_calldata_input(analyzer)? || self.is_msg(analyzer)? || self.is_block(analyzer)? {
Ok(true)
} else if let Some(tmp) = self.tmp_of(analyzer)? {
let rhs_controllable = if let Some(rhs) = tmp.rhs {
Expand All @@ -107,6 +109,20 @@ impl ContextVarNode {
.any(|edge| Edge::Context(ContextEdge::CalldataVariable) == *edge.weight())
}

pub fn is_msg(&self, analyzer: &impl GraphBackend) -> Result<bool, GraphError> {
Ok(matches!(
self.underlying(analyzer)?.storage,
Some(StorageLocation::Msg(..))
))
}

pub fn is_block(&self, analyzer: &impl GraphBackend) -> Result<bool, GraphError> {
Ok(matches!(
self.underlying(analyzer)?.storage,
Some(StorageLocation::Block(..))
))
}

pub fn is_func_input(&self, analyzer: &impl GraphBackend) -> bool {
let first = self.first_version(analyzer);
analyzer
Expand Down
4 changes: 2 additions & 2 deletions crates/graph/src/nodes/context/var/underlying.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use crate::{
};

use crate::range::elem::*;
use shared::NodeIdx;
use shared::{StorageLocation, NodeIdx};

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

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContextVar {
Expand Down
8 changes: 4 additions & 4 deletions crates/graph/src/nodes/func_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crate::{
VarType,
};

use shared::{NodeIdx, Search};
use shared::{NodeIdx, Search, StorageLocation};

use petgraph::{visit::EdgeRef, Direction};
use solang_parser::{
helpers::CodeLocation,
pt::{
Base, Expression, FunctionAttribute, FunctionDefinition, FunctionTy, Identifier, Loc,
Parameter, ParameterList, Statement, StorageLocation, Type, VariableDefinition, Visibility,
Parameter, ParameterList, Statement, Type, VariableDefinition, Visibility,
},
};
use std::collections::BTreeMap;
Expand Down Expand Up @@ -785,7 +785,7 @@ impl FunctionParam {
loc: param.loc,
ty: analyzer.parse_expr(&param.ty, None),
order,
storage: param.storage,
storage: if let Some(s) = param.storage { Some(s.into()) } else { None },
name: param.name,
}
}
Expand Down Expand Up @@ -875,7 +875,7 @@ impl FunctionReturn {
FunctionReturn {
loc: param.loc,
ty: analyzer.parse_expr(&param.ty, None),
storage: param.storage,
storage: if let Some(s) = param.storage { Some(s.into()) } else { None },
name: param.name,
}
}
Expand Down
30 changes: 28 additions & 2 deletions crates/graph/src/range/elem/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ impl RangeExpr<Concrete> {
if SINGLETON_EQ_OPS.contains(&self.op) {
let mut new_self = self.clone();
new_self.uncache();
new_self.op = new_self.op.logical_inverse().unwrap();
new_self.op = new_self.op.logical_inverse()?;
Some(new_self)
} else {
// non-singleton, i.e. AND or OR
let mut new_self = self.clone();
new_self.uncache();
new_self.op = new_self.op.inverse().unwrap();
new_self.op = new_self.op.inverse()?;
if let Some(new_lhs) = new_self.inverse_if_boolean() {
*new_self.lhs = Elem::Expr(new_lhs);
}
Expand Down Expand Up @@ -220,6 +220,32 @@ fn collapse(l: Elem<Concrete>, op: RangeOp, r: Elem<Concrete>) -> MaybeCollapsed
let y = expr.rhs;
let z = c;
match (expr.op, op) {
(RangeOp::Sub(false), RangeOp::Min) => {
// min{x - y, z}
// if x <= z, then x - y will be the minimum if y >= 0
if matches!(x.range_ord(&z), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Less))
&& matches!(y.range_ord(&zero), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Greater)) {
MaybeCollapsed::Collapsed(l)
} else {
MaybeCollapsed::Not(l, r)
}
}
(RangeOp::Add(false), RangeOp::Max) => {
// max{x + y, z}
// if x >= z, then x + y will be the maximum if y >= 0
// or if y >= z, then x + y will be the maximum if x >= 0
if (
matches!(x.range_ord(&z), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Greater))
&& matches!(y.range_ord(&zero), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Greater))
) || (
matches!(y.range_ord(&z), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Greater))
&& matches!(x.range_ord(&zero), Some(std::cmp::Ordering::Equal) | Some(std::cmp::Ordering::Greater))
) {
MaybeCollapsed::Collapsed(l)
} else {
MaybeCollapsed::Not(l, r)
}
}
(RangeOp::Eq, RangeOp::Eq) => {
// ((x == y) == z)
// can skip if x and z eq
Expand Down
12 changes: 11 additions & 1 deletion crates/pyrometer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,14 @@ ethers-core.workspace = true
ariadne.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
serde_json = "1"
serde_json = "1"




[dev-dependencies]
criterion = { version = "0.4"} # benching

[[bench]]
name = "parse"
harness = false
File renamed without changes.
File renamed without changes
10 changes: 4 additions & 6 deletions benches/parse.rs → crates/pyrometer/benches/parse.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use pyrometer::Analyzer;
use pyrometer::{Analyzer, SourcePath};
use std::path::PathBuf;

use std::env::{self};
Expand Down Expand Up @@ -73,9 +73,7 @@ fn bench(c: &mut Criterion) {
/// * `path` - A `PathBuf` representing the path to the source code file.
/// * `sol` - A string containing the Solidity source code.
fn parse(path: &PathBuf, sol: String) {
let mut analyzer = Analyzer {
root: path.clone(),
..Default::default()
};
let (_maybe_entry, mut _all_sources) = analyzer.parse(&sol, &path, true);
let mut analyzer = Analyzer::default();
let current_path = SourcePath::SolidityFile(path.clone());
let _maybe_entry = analyzer.parse(&sol, &current_path, true);
}
4 changes: 2 additions & 2 deletions crates/pyrometer/src/builtin_fns.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use graph::nodes::{Builtin, Function, FunctionParam, FunctionReturn};
use shared::{AnalyzerLike, GraphLike};
use shared::{AnalyzerLike, GraphLike, StorageLocation};

use solang_parser::pt::{FunctionAttribute, Identifier, Loc, StorageLocation, Visibility};
use solang_parser::pt::{FunctionAttribute, Identifier, Loc, Visibility};

use std::collections::HashMap;

Expand Down
38 changes: 38 additions & 0 deletions crates/shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,41 @@ mod search;
pub use analyzer_like::*;
pub use graph_like::*;
pub use search::*;


#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum StorageLocation {
Memory(solang_parser::pt::Loc),
Storage(solang_parser::pt::Loc),
Calldata(solang_parser::pt::Loc),
Block(solang_parser::pt::Loc),
Msg(solang_parser::pt::Loc),
}

impl std::fmt::Display for StorageLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Memory(_) => write!(f, "memory"),
Self::Storage(_) => write!(f, "storage"),
Self::Calldata(_) => write!(f, "calldata"),
Self::Block(_) => write!(f, "block"),
Self::Msg(_) => write!(f, "msg"),
}
}
}

impl From<solang_parser::pt::StorageLocation> for StorageLocation {
fn from(sl: solang_parser::pt::StorageLocation) -> Self {
match sl {
solang_parser::pt::StorageLocation::Memory(m) =>{
StorageLocation::Memory(m)
}
solang_parser::pt::StorageLocation::Storage(m) =>{
StorageLocation::Storage(m)
}
solang_parser::pt::StorageLocation::Calldata(m) =>{
StorageLocation::Calldata(m)
}
}
}
}
4 changes: 2 additions & 2 deletions crates/solc-expressions/src/context_builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ pub trait ContextBuilder:
loc: Some(loc),
name: name.to_string(),
display_name: name.to_string(),
storage: var_decl.storage.clone(),
storage: if let Some(s) = &var_decl.storage { Some(s.clone().into()) } else { None },
is_tmp: false,
is_symbolic: true,
tmp_of: None,
Expand All @@ -642,7 +642,7 @@ pub trait ContextBuilder:
loc: Some(loc),
name: name.to_string(),
display_name: name.to_string(),
storage: var_decl.storage.clone(),
storage: if let Some(s) = &var_decl.storage { Some(s.clone().into()) } else { None },
is_tmp: false,
is_symbolic: true,
tmp_of: None,
Expand Down
Loading

0 comments on commit 3d1b17a

Please sign in to comment.