From 765f27a2405a034c868afdf385b321d4e1c9ba57 Mon Sep 17 00:00:00 2001 From: plotchy Date: Fri, 19 Jul 2024 20:21:23 -0400 Subject: [PATCH] adding comments for match arm examples --- crates/solc-expressions/src/array.rs | 52 +---- crates/solc-expressions/src/assign.rs | 17 +- crates/solc-expressions/src/bin_op.rs | 7 + crates/solc-expressions/src/cmp.rs | 206 +----------------- crates/solc-expressions/src/literal.rs | 1 + .../src/pre_post_in_decrement.rs | 11 +- 6 files changed, 43 insertions(+), 251 deletions(-) diff --git a/crates/solc-expressions/src/array.rs b/crates/solc-expressions/src/array.rs index 017e96ec..df294c87 100644 --- a/crates/solc-expressions/src/array.rs +++ b/crates/solc-expressions/src/array.rs @@ -48,6 +48,8 @@ pub trait Array: AnalyzerBackend + Sized { ) -> Result<(), ExprErr> { match ret { ExprRet::Single(inner_ty) | ExprRet::SingleLiteral(inner_ty) => { + // ie: uint[] + // ie: uint[][] if let Some(var_type) = VarType::try_from_idx(self, inner_ty) { let dyn_b = Builtin::Array(var_type); if let Some(idx) = self.builtins().get(&dyn_b) { @@ -65,6 +67,7 @@ pub trait Array: AnalyzerBackend + Sized { } } ExprRet::Multi(inner) => { + // ie: unsure of syntax needed to get here. (not possible?) inner .into_iter() .map(|i| self.match_ty(ctx, ty_expr, i)) @@ -180,7 +183,6 @@ pub trait Array: AnalyzerBackend + Sized { (RangeOp::Lte, RangeOp::Gte), )?; } - let name = format!( "{}[{}]", parent.name(self).into_expr_err(loc)?, @@ -470,52 +472,4 @@ pub trait Array: AnalyzerBackend + Sized { Ok(()) } } - - fn update_array_min_if_length( - &mut self, - arena: &mut RangeArena>, - ctx: ContextNode, - loc: Loc, - maybe_length: ContextVarNode, - ) -> Result<(), ExprErr> { - if let Some(backing_arr) = maybe_length.len_var_to_array(self).into_expr_err(loc)? { - let next_arr = self.advance_var_in_ctx( - backing_arr.latest_version_or_inherited_in_ctx(ctx, self), - loc, - ctx, - )?; - let new_len = Elem::from(backing_arr) - .get_length() - .max(maybe_length.into()); - let min = Elem::from(backing_arr).set_length(new_len); - next_arr - .set_range_min(self, arena, min) - .into_expr_err(loc)?; - } - Ok(()) - } - - fn update_array_max_if_length( - &mut self, - arena: &mut RangeArena>, - ctx: ContextNode, - loc: Loc, - maybe_length: ContextVarNode, - ) -> Result<(), ExprErr> { - if let Some(backing_arr) = maybe_length.len_var_to_array(self).into_expr_err(loc)? { - let next_arr = self.advance_var_in_ctx( - backing_arr.latest_version_or_inherited_in_ctx(ctx, self), - loc, - ctx, - )?; - let new_len = Elem::from(backing_arr) - .get_length() - .min(maybe_length.into()); - let max = Elem::from(backing_arr).set_length(new_len); - next_arr - .set_range_max(self, arena, max) - .into_expr_err(loc)?; - } - Ok(()) - } } diff --git a/crates/solc-expressions/src/assign.rs b/crates/solc-expressions/src/assign.rs index bf6787fc..3a123c87 100644 --- a/crates/solc-expressions/src/assign.rs +++ b/crates/solc-expressions/src/assign.rs @@ -77,6 +77,7 @@ pub trait Assign: AnalyzerBackend + Sized Ok(()) } (ExprRet::Single(lhs), ExprRet::SingleLiteral(rhs)) => { + // ie: uint x = 5; let lhs_cvar = ContextVarNode::from(*lhs).latest_version_or_inherited_in_ctx(ctx, self); let rhs_cvar = @@ -86,6 +87,7 @@ pub trait Assign: AnalyzerBackend + Sized Ok(()) } (ExprRet::Single(lhs), ExprRet::Single(rhs)) => { + // ie: uint x = y; let lhs_cvar = ContextVarNode::from(*lhs).latest_version_or_inherited_in_ctx(ctx, self); let rhs_cvar = @@ -94,23 +96,31 @@ pub trait Assign: AnalyzerBackend + Sized .into_expr_err(loc)?; Ok(()) } - (l @ ExprRet::Single(_), ExprRet::Multi(rhs_sides)) => rhs_sides - .iter() - .try_for_each(|expr_ret| self.match_assign_sides(arena, ctx, loc, l, expr_ret)), + (l @ ExprRet::Single(_), ExprRet::Multi(rhs_sides)) => { + // ie: uint x = (a, b), not possible? + rhs_sides + .iter() + .try_for_each(|expr_ret| self.match_assign_sides(arena, ctx, loc, l, expr_ret)) + } (ExprRet::Multi(lhs_sides), r @ ExprRet::Single(_) | r @ ExprRet::SingleLiteral(_)) => { + // ie: (uint x, uint y) = a, not possible? lhs_sides .iter() .try_for_each(|expr_ret| self.match_assign_sides(arena, ctx, loc, expr_ret, r)) } (ExprRet::Multi(lhs_sides), ExprRet::Multi(rhs_sides)) => { // try to zip sides if they are the same length + // (x, y) = (a, b) + // ie: (x, y) = (a, b, c), not possible? if lhs_sides.len() == rhs_sides.len() { + // (x, y) = (a, b) lhs_sides.iter().zip(rhs_sides.iter()).try_for_each( |(lhs_expr_ret, rhs_expr_ret)| { self.match_assign_sides(arena, ctx, loc, lhs_expr_ret, rhs_expr_ret) }, ) } else { + // ie: (x, y) = (a, b, c), not possible? rhs_sides.iter().try_for_each(|rhs_expr_ret| { self.match_assign_sides(arena, ctx, loc, lhs_paths, rhs_expr_ret) }) @@ -203,6 +213,7 @@ pub trait Assign: AnalyzerBackend + Sized } if !lhs_cvar.ty_eq(&rhs_cvar, self).into_expr_err(loc)? { + // lhs type doesnt match rhs type (not possible? have never reached this) let cast_to_min = match lhs_cvar.range_min(self).into_expr_err(loc)? { Some(v) => v, None => { diff --git a/crates/solc-expressions/src/bin_op.rs b/crates/solc-expressions/src/bin_op.rs index 01c02663..bad31ca5 100644 --- a/crates/solc-expressions/src/bin_op.rs +++ b/crates/solc-expressions/src/bin_op.rs @@ -75,6 +75,7 @@ pub trait BinOp: AnalyzerBackend + Sized { "No right hand side provided for binary operation".to_string(), )), (ExprRet::SingleLiteral(lhs), ExprRet::SingleLiteral(rhs)) => { + // ie: 5 + 5 let lhs_cvar = ContextVarNode::from(*lhs).latest_version_or_inherited_in_ctx(ctx, self); let rhs_cvar = @@ -89,6 +90,7 @@ pub trait BinOp: AnalyzerBackend + Sized { Ok(()) } (ExprRet::SingleLiteral(lhs), ExprRet::Single(rhs)) => { + // ie: 5 + x ContextVarNode::from(*lhs) .cast_from(&ContextVarNode::from(*rhs), self, arena) .into_expr_err(loc)?; @@ -104,6 +106,7 @@ pub trait BinOp: AnalyzerBackend + Sized { Ok(()) } (ExprRet::Single(lhs), ExprRet::SingleLiteral(rhs)) => { + // ie: x + 5 ContextVarNode::from(*rhs) .cast_from(&ContextVarNode::from(*lhs), self, arena) .into_expr_err(loc)?; @@ -119,6 +122,7 @@ pub trait BinOp: AnalyzerBackend + Sized { Ok(()) } (ExprRet::Single(lhs), ExprRet::Single(rhs)) => { + // ie: x + y let lhs_cvar = ContextVarNode::from(*lhs).latest_version_or_inherited_in_ctx(ctx, self); let rhs_cvar = @@ -131,6 +135,7 @@ pub trait BinOp: AnalyzerBackend + Sized { Ok(()) } (lhs @ ExprRet::Single(..), ExprRet::Multi(rhs_sides)) => { + // ie: x + (y, z), (not possible?) rhs_sides .iter() .map(|expr_ret| self.op_match(arena, ctx, loc, lhs, expr_ret, op, assign)) @@ -138,6 +143,7 @@ pub trait BinOp: AnalyzerBackend + Sized { Ok(()) } (ExprRet::Multi(lhs_sides), rhs @ ExprRet::Single(..)) => { + // ie: (x, y) + z, (not possible?) lhs_sides .iter() .map(|expr_ret| self.op_match(arena, ctx, loc, expr_ret, rhs, op, assign)) @@ -147,6 +153,7 @@ pub trait BinOp: AnalyzerBackend + Sized { (_, ExprRet::CtxKilled(kind)) => ctx.kill(self, loc, *kind).into_expr_err(loc), (ExprRet::CtxKilled(kind), _) => ctx.kill(self, loc, *kind).into_expr_err(loc), (ExprRet::Multi(lhs_sides), ExprRet::Multi(rhs_sides)) => Err(ExprErr::UnhandledCombo( + // ie: (x, y) + (a, b), (not possible?) loc, format!("Unhandled combination in binop: {lhs_sides:?} {rhs_sides:?}"), )), diff --git a/crates/solc-expressions/src/cmp.rs b/crates/solc-expressions/src/cmp.rs index 59f81700..8cbee813 100644 --- a/crates/solc-expressions/src/cmp.rs +++ b/crates/solc-expressions/src/cmp.rs @@ -165,12 +165,14 @@ pub trait Cmp: AnalyzerBackend + Sized { match (lhs_paths, rhs_paths) { (_, ExprRet::Null) | (ExprRet::Null, _) => Ok(()), (ExprRet::SingleLiteral(lhs), ExprRet::Single(rhs)) => { + // ie: 5 == x ContextVarNode::from(*lhs) .literal_cast_from(&ContextVarNode::from(*rhs), self) .into_expr_err(loc)?; self.cmp_inner(arena, ctx, loc, &ExprRet::Single(*rhs), op, rhs_paths) } (ExprRet::SingleLiteral(lhs), ExprRet::SingleLiteral(rhs)) => { + // ie: 5 == 5 let lhs_cvar = ContextVarNode::from(*lhs).latest_version_or_inherited_in_ctx(ctx, self); let rhs_cvar = @@ -187,12 +189,14 @@ pub trait Cmp: AnalyzerBackend + Sized { ) } (ExprRet::Single(lhs), ExprRet::SingleLiteral(rhs)) => { + // ie: x == 5 ContextVarNode::from(*rhs) .literal_cast_from(&ContextVarNode::from(*lhs), self) .into_expr_err(loc)?; self.cmp_inner(arena, ctx, loc, lhs_paths, op, &ExprRet::Single(*rhs)) } (ExprRet::Single(lhs), ExprRet::Single(rhs)) => { + // ie: x == y let lhs_cvar = ContextVarNode::from(*lhs); let rhs_cvar = ContextVarNode::from(*rhs); tracing::trace!( @@ -260,12 +264,14 @@ pub trait Cmp: AnalyzerBackend + Sized { .into_expr_err(loc) } (l @ ExprRet::Single(_lhs), ExprRet::Multi(rhs_sides)) => { + // ie: x == [y, z] (not possible?) rhs_sides .iter() .try_for_each(|expr_ret| self.cmp_inner(arena, ctx, loc, l, op, expr_ret))?; Ok(()) } (ExprRet::Multi(lhs_sides), r @ ExprRet::Single(_)) => { + // ie: (x, y) == z (not possible?) lhs_sides .iter() .try_for_each(|expr_ret| self.cmp_inner(arena, ctx, loc, expr_ret, op, r))?; @@ -273,7 +279,10 @@ pub trait Cmp: AnalyzerBackend + Sized { } (ExprRet::Multi(lhs_sides), ExprRet::Multi(rhs_sides)) => { // try to zip sides if they are the same length + // ie: (x, y) == (a, b) (not possible?) + // ie: (x, y, z) == (a, b) (not possible?) if lhs_sides.len() == rhs_sides.len() { + // ie: (x, y) == (a, b) (not possible?) lhs_sides.iter().zip(rhs_sides.iter()).try_for_each( |(lhs_expr_ret, rhs_expr_ret)| { self.cmp_inner(arena, ctx, loc, lhs_expr_ret, op, rhs_expr_ret) @@ -281,6 +290,7 @@ pub trait Cmp: AnalyzerBackend + Sized { )?; Ok(()) } else { + // ie: (x, y, z) == (a, b) (not possible?) rhs_sides.iter().try_for_each(|rhs_expr_ret| { self.cmp_inner(arena, ctx, loc, lhs_paths, op, rhs_expr_ret) })?; @@ -293,200 +303,4 @@ pub trait Cmp: AnalyzerBackend + Sized { )), } } - - // fn not_eval( - // &mut self, - // _ctx: ContextNode, - // loc: Loc, - // lhs_cvar: ContextVarNode, - // ) -> Result { - // if let Some(lhs_range) = lhs_cvar.ref_range(self).into_expr_err(loc)? { - // let lhs_min = lhs_range.evaled_range_min(self, arena).into_expr_err(loc)?; - - // // invert - // if lhs_min.range_eq(&lhs_range.minimize(self, arena).into_expr_err(loc)?, self) { - // let val = Elem::Expr(RangeExpr::new( - // lhs_range.range_min().into_owned(), - // RangeOp::Not, - // Elem::Null, - // )); - - // return Ok(SolcRange::new(val.clone(), val, lhs_range.exclusions.clone())); - // } - // } - - // let min = Elem::Concrete(RangeConcrete { - // val: Concrete::Bool(false), - // loc, - // }).arenaize(self); - - // let max = Elem::Concrete(RangeConcrete { - // val: Concrete::Bool(true), - // loc, - // }).arenaize(self); - // Ok(SolcRange::new( - // min, - // max, - // vec![], - // )) - // } - - fn range_eval( - &self, - arena: &mut RangeArena>, - _ctx: ContextNode, - lhs_cvar: ContextVarNode, - rhs_cvar: ContextVarNode, - op: RangeOp, - ) -> Result { - if let Some(lhs_range) = lhs_cvar.ref_range(self)? { - if let Some(rhs_range) = rhs_cvar.ref_range(self)? { - match op { - RangeOp::Lt => { - // if lhs_max < rhs_min, we know this cmp will evaluate to - // true - - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - if let Some(Ordering::Less) = lhs_max.range_ord(&rhs_min, arena) { - return Ok(true.into()); - } - - // Similarly if lhs_min >= rhs_max, we know this cmp will evaluate to - // false - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - match lhs_min.range_ord(&rhs_max, arena) { - Some(Ordering::Greater) => { - return Ok(false.into()); - } - Some(Ordering::Equal) => { - return Ok(false.into()); - } - _ => {} - } - } - RangeOp::Gt => { - // if lhs_min > rhs_max, we know this cmp will evaluate to - // true - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - if let Some(Ordering::Greater) = lhs_min.range_ord(&rhs_max, arena) { - return Ok(true.into()); - } - - // if lhs_max <= rhs_min, we know this cmp will evaluate to - // false - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - match lhs_max.range_ord(&rhs_min, arena) { - Some(Ordering::Less) => { - return Ok(false.into()); - } - Some(Ordering::Equal) => { - return Ok(false.into()); - } - _ => {} - } - } - RangeOp::Lte => { - // if lhs_max <= rhs_min, we know this cmp will evaluate to - // true - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - match lhs_max.range_ord(&rhs_min, arena) { - Some(Ordering::Less) => { - return Ok(true.into()); - } - Some(Ordering::Equal) => { - return Ok(true.into()); - } - _ => {} - } - - // Similarly if lhs_min > rhs_max, we know this cmp will evaluate to - // false - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - if let Some(Ordering::Greater) = lhs_min.range_ord(&rhs_max, arena) { - return Ok(false.into()); - } - } - RangeOp::Gte => { - // if lhs_min >= rhs_max, we know this cmp will evaluate to - // true - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - match lhs_min.range_ord(&rhs_max, arena) { - Some(Ordering::Greater) => { - return Ok(true.into()); - } - Some(Ordering::Equal) => { - return Ok(true.into()); - } - _ => {} - } - - // if lhs_max < rhs_min, we know this cmp will evaluate to - // false - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - if let Some(Ordering::Less) = lhs_max.range_ord(&rhs_min, arena) { - return Ok(false.into()); - } - } - RangeOp::Eq => { - // if all elems are equal we know its true - // we dont know anything else - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - if let ( - Some(Ordering::Equal), - Some(Ordering::Equal), - Some(Ordering::Equal), - ) = ( - // check lhs_min == lhs_max, ensures lhs is const - lhs_min.range_ord(&lhs_max, arena), - // check lhs_min == rhs_min, checks if lhs == rhs - lhs_min.range_ord(&rhs_min, arena), - // check rhs_min == rhs_max, ensures rhs is const - rhs_min.range_ord(&rhs_max, arena), - ) { - return Ok(true.into()); - } - } - RangeOp::Neq => { - // if all elems are equal we know its true - // we dont know anything else - let lhs_min = lhs_range.evaled_range_min(self, arena)?; - let lhs_max = lhs_range.evaled_range_max(self, arena)?; - let rhs_min = rhs_range.evaled_range_min(self, arena)?; - let rhs_max = rhs_range.evaled_range_max(self, arena)?; - if let ( - Some(Ordering::Equal), - Some(Ordering::Equal), - Some(Ordering::Equal), - ) = ( - // check lhs_min == lhs_max, ensures lhs is const - lhs_min.range_ord(&lhs_max, arena), - // check lhs_min == rhs_min, checks if lhs == rhs - lhs_min.range_ord(&rhs_min, arena), - // check rhs_min == rhs_max, ensures rhs is const - rhs_min.range_ord(&rhs_max, arena), - ) { - return Ok(false.into()); - } - } - e => unreachable!("Cmp with strange op: {:?}", e), - } - Ok(SolcRange::default_bool()) - } else { - Ok(SolcRange::default_bool()) - } - } else { - Ok(SolcRange::default_bool()) - } - } } diff --git a/crates/solc-expressions/src/literal.rs b/crates/solc-expressions/src/literal.rs index 6ced7c03..a5c2a2f4 100644 --- a/crates/solc-expressions/src/literal.rs +++ b/crates/solc-expressions/src/literal.rs @@ -251,6 +251,7 @@ pub trait Literal: AnalyzerBackend + Sized { }); ConcreteNode::from(self.add_node(Node::Concrete(Concrete::Bytes(max, target)))) } else { + // hex"" ConcreteNode::from(self.add_node(Node::Concrete(Concrete::DynBytes(h)))) }; diff --git a/crates/solc-expressions/src/pre_post_in_decrement.rs b/crates/solc-expressions/src/pre_post_in_decrement.rs index 9550c32d..98a47c36 100644 --- a/crates/solc-expressions/src/pre_post_in_decrement.rs +++ b/crates/solc-expressions/src/pre_post_in_decrement.rs @@ -135,12 +135,14 @@ pub trait PrePostIncDecrement: Ok(()) } ExprRet::SingleLiteral(var) => { + // ie: 5++; (not valid syntax) ContextVarNode::from(*var) .try_increase_size(self, arena) .into_expr_err(loc)?; self.match_in_de_crement(arena, ctx, pre, increment, loc, &ExprRet::Single(*var)) } ExprRet::Single(var) => { + // ie: a++; let cvar = ContextVarNode::from(*var).latest_version_or_inherited_in_ctx(ctx, self); let elem = Elem::from(cvar); let one = Elem::from(Concrete::from(U256::from(1))).cast(elem.clone()); @@ -228,9 +230,12 @@ pub trait PrePostIncDecrement: Ok(()) } } - ExprRet::Multi(inner) => inner.iter().try_for_each(|expr| { - self.match_in_de_crement(arena, ctx, pre, increment, loc, expr) - }), + ExprRet::Multi(inner) => { + // ie: (5, 5)++; (invalid syntax) + inner.iter().try_for_each(|expr| { + self.match_in_de_crement(arena, ctx, pre, increment, loc, expr) + }) + } ExprRet::Null => Ok(()), } }