From bf4cf2043901f9fa9dd48810fc774932e8886360 Mon Sep 17 00:00:00 2001 From: brock elmore Date: Thu, 18 Jul 2024 07:33:22 -0700 Subject: [PATCH] push fix --- .../pyrometer/tests/test_data/dyn_types.sol | 104 +++++++++--------- .../src/context_builder/flattened.rs | 4 +- .../src/func_call/intrinsic_call/array.rs | 45 ++++++-- .../func_call/intrinsic_call/constructors.rs | 29 ++++- 4 files changed, 120 insertions(+), 62 deletions(-) diff --git a/crates/pyrometer/tests/test_data/dyn_types.sol b/crates/pyrometer/tests/test_data/dyn_types.sol index 6f304c46..83d04e7b 100644 --- a/crates/pyrometer/tests/test_data/dyn_types.sol +++ b/crates/pyrometer/tests/test_data/dyn_types.sol @@ -4,38 +4,38 @@ pragma solidity ^0.8.0; contract DynTypes { uint256[] storeVar; - struct Strukt { - uint256 a; - uint256 b; - } + // struct Strukt { + // uint256 a; + // uint256 b; + // } - mapping(address => Strukt) public someMapping; + // mapping(address => Strukt) public someMapping; - function bytes_dyn(bytes calldata x) public pure { - bytes memory y = x; - require(x.length < 10); - y[8] = 0xff; - require(y.length == 9); - } + // function bytes_dyn(bytes calldata x) public pure { + // bytes memory y = x; + // require(x.length < 10); + // y[8] = 0xff; + // require(y.length == 9); + // } - function array_dyn(uint256[] memory x) public pure { - x[0] = 5; - require(x.length < 10); - uint256[] memory y = x; - y[8] = 100; - require(y.length == 9); - } + // function array_dyn(uint256[] memory x) public pure { + // x[0] = 5; + // require(x.length < 10); + // uint256[] memory y = x; + // y[8] = 100; + // require(y.length == 9); + // } - function nested_bytes_dyn(bytes[] memory x, uint y) public pure { - bytes memory a = hex"1337"; - x[0] = a; - require(x[0][0] == hex"13"); - // return x[0][0]; + // function nested_bytes_dyn(bytes[] memory x, uint y) public pure { + // bytes memory a = hex"1337"; + // x[0] = a; + // require(x[0][0] == hex"13"); + // // return x[0][0]; - x[y] = hex"1122"; - uint256 z = y - 1; - require(x[z + 1][0] == hex"11"); - } + // x[y] = hex"1122"; + // uint256 z = y - 1; + // require(x[z + 1][0] == hex"11"); + // } function array_push(uint256 x) public { // require(x > 5); @@ -51,34 +51,34 @@ contract DynTypes { require(y == x); } - function indexInto() public view returns (uint256) { - return storeVar[basicFunc()]; - } + // function indexInto() public view returns (uint256) { + // return storeVar[basicFunc()]; + // } - function basicFunc() public pure returns (uint256) { - return 1; - } + // function basicFunc() public pure returns (uint256) { + // return 1; + // } - function indexIntoMapping(address who) public { - // TODO: this should panic - Strukt storage a = someMapping[who]; - a.a = 100; - a.b = 100; - require(someMapping[who].a == 300); - } + // function indexIntoMapping(address who) public { + // // TODO: this should panic + // Strukt storage a = someMapping[who]; + // a.a = 100; + // a.b = 100; + // require(someMapping[who].a == 300); + // } - address[] t; + // address[] t; - function inLoop(address holder, address[] memory tokens) public pure { - address[] memory h = new address[](1); - h[0] = holder; - inLoop(h, tokens); - } + // function inLoop(address holder, address[] memory tokens) public pure { + // address[] memory h = new address[](1); + // h[0] = holder; + // inLoop(h, tokens); + // } - function inLoop(address[] memory holders, address[] memory) public pure { - for (uint j = 0; j < holders.length; j++) { - address holder = holders[j]; - holder; - } - } + // function inLoop(address[] memory holders, address[] memory) public pure { + // for (uint j = 0; j < holders.length; j++) { + // address holder = holders[j]; + // holder; + // } + // } } diff --git a/crates/solc-expressions/src/context_builder/flattened.rs b/crates/solc-expressions/src/context_builder/flattened.rs index 0e9217e6..41461c1c 100644 --- a/crates/solc-expressions/src/context_builder/flattened.rs +++ b/crates/solc-expressions/src/context_builder/flattened.rs @@ -1466,8 +1466,8 @@ pub trait Flatten: VarType::User(TypeNode::Struct(s), _) => { self.construct_struct_inner(arena, ctx, s, inputs, loc) } - VarType::User(TypeNode::Contract(_), _) => { - unreachable!("should be unreachable: contract") + VarType::User(TypeNode::Contract(c), _) => { + self.construct_contract_inner(arena, ctx, c, inputs, loc) } VarType::User(TypeNode::Func(s), _) => { if self.builtin_fn_nodes().iter().any(|(_, v)| *v == func) { diff --git a/crates/solc-expressions/src/func_call/intrinsic_call/array.rs b/crates/solc-expressions/src/func_call/intrinsic_call/array.rs index 171fca16..1b3b615b 100644 --- a/crates/solc-expressions/src/func_call/intrinsic_call/array.rs +++ b/crates/solc-expressions/src/func_call/intrinsic_call/array.rs @@ -1,3 +1,4 @@ +use crate::assign::Assign; use crate::func_caller::NamedOrUnnamedArgs; use crate::{array::Array, bin_op::BinOp, ContextBuilder, ExpressionParser, ListAccess}; @@ -24,17 +25,47 @@ pub trait ArrayCaller: AnalyzerBackend + S inputs: ExprRet, loc: Loc, ) -> Result<(), ExprErr> { - match &*func_name { + match func_name { "push" => { let inputs_vec = inputs.as_vec(); let arr = inputs_vec[0].expect_single().into_expr_err(loc)?; - let push_elem = if let Some(push_elem) = inputs_vec.get(1) { - Some(push_elem.expect_single().into_expr_err(loc)?) - } else { - None - }; + let arr = ContextVarNode::from(arr).latest_version(self); - todo!(); + // get length + let len = self + .get_length(arena, ctx, arr, true, loc)? + .unwrap() + .latest_version(self); + + // get the index access for the *previous* length + let index_access = self + .index_into_array_raw(arena, ctx, loc, len, arr, false, true)? + .unwrap(); + + // create a temporary 1 variable + let tmp_one = self.add_concrete_var(ctx, Concrete::from(U256::from(1)), loc)?; + + // add 1 to the length + let tmp_len = self.op(arena, loc, len, tmp_one, ctx, RangeOp::Add(false), false)?; + + let tmp_len = ContextVarNode::from(tmp_len.expect_single().unwrap()); + tmp_len.underlying_mut(self).unwrap().is_tmp = false; + + // set the new length + self.set_var_as_length(arena, ctx, loc, tmp_len, arr.latest_version(self))?; + + if let Some(push_elem) = inputs_vec.get(1) { + self.match_assign_sides( + arena, + ctx, + loc, + &ExprRet::Single(index_access.0.into()), + push_elem, + ) + } else { + ctx.push_expr(ExprRet::Single(index_access.0.into()), self) + .into_expr_err(loc) + } } "pop" => { todo!(); diff --git a/crates/solc-expressions/src/func_call/intrinsic_call/constructors.rs b/crates/solc-expressions/src/func_call/intrinsic_call/constructors.rs index 01e165eb..83327ab1 100644 --- a/crates/solc-expressions/src/func_call/intrinsic_call/constructors.rs +++ b/crates/solc-expressions/src/func_call/intrinsic_call/constructors.rs @@ -3,7 +3,7 @@ use crate::{assign::Assign, func_call::helper::CallerHelper, ContextBuilder, Exp use graph::{ elem::*, - nodes::{Concrete, ContextNode, ContextVar, ContextVarNode, ExprRet, StructNode}, + nodes::{Concrete, ContextNode, ContextVar, ContextVarNode, ContractNode, ExprRet, StructNode}, AnalyzerBackend, ContextEdge, Edge, Node, Range, VarType, }; use shared::{ExprErr, IntoExprErr, NodeIdx, RangeArena}; @@ -169,6 +169,33 @@ pub trait ConstructorCaller: }) } + fn construct_contract_inner( + &mut self, + _arena: &mut RangeArena>, + ctx: ContextNode, + con_node: ContractNode, + _input: ExprRet, + loc: Loc, + ) -> Result<(), ExprErr> { + // construct a new contract + + let var = match ContextVar::maybe_from_user_ty(self, loc, con_node.0.into()) { + Some(v) => v, + None => { + return Err(ExprErr::VarBadType( + loc, + format!( + "Could not create context variable from user type: {:?}", + self.node(con_node) + ), + )) + } + }; + let contract_cvar = ContextVarNode::from(self.add_node(Node::ContextVar(var))); + ctx.push_expr(ExprRet::Single(contract_cvar.into()), self) + .into_expr_err(loc) + } + fn construct_struct_inner( &mut self, arena: &mut RangeArena>,