Add support for string.concat

Fix #1075
pull/1086/head
Josselin 3 years ago
parent c4d3898e25
commit 5eee87acb9
  1. 1
      slither/core/declarations/solidity_variables.py
  2. 12
      slither/slithir/convert.py
  3. 2
      slither/slithir/operations/member.py
  4. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.8.12-compact.zip
  5. 3
      tests/ast-parsing/expected/units_and_global_variables-0.8.12-compact.json
  6. 119
      tests/ast-parsing/units_and_global_variables-0.8.12.sol

@ -71,6 +71,7 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = {
"abi.encodeWithSelector()": ["bytes"], "abi.encodeWithSelector()": ["bytes"],
"abi.encodeWithSignature()": ["bytes"], "abi.encodeWithSignature()": ["bytes"],
"bytes.concat()": ["bytes"], "bytes.concat()": ["bytes"],
"string.concat()": ["string"],
# abi.decode returns an a list arbitrary types # abi.decode returns an a list arbitrary types
"abi.decode()": [], "abi.decode()": [],
"type(address)": [], "type(address)": [],

@ -944,6 +944,18 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: dis
s.set_expression(ins.expression) s.set_expression(ins.expression)
return s return s
if ins.ori.variable_left == ElementaryType("string") and ins.ori.variable_right == Constant(
"concat"
):
s = SolidityCall(
SolidityFunction("string.concat()"),
ins.nbr_arguments,
ins.lvalue,
ins.type_call,
)
s.set_expression(ins.expression)
return s
msgcall = HighLevelCall( msgcall = HighLevelCall(
ins.ori.variable_left, ins.ori.variable_left,
ins.ori.variable_right, ins.ori.variable_right,

@ -22,7 +22,7 @@ class Member(OperationWithLValue):
# f.h(1); # f.h(1);
# } # }
# } # }
# Can be an ElementaryType because of bytes.concat # Can be an ElementaryType because of bytes.concat, string.concat
assert is_valid_rvalue(variable_left) or isinstance( assert is_valid_rvalue(variable_left) or isinstance(
variable_left, variable_left,
(Contract, Enum, Function, CustomError, SolidityImportPlaceHolder, ElementaryType), (Contract, Enum, Function, CustomError, SolidityImportPlaceHolder, ElementaryType),

@ -4,9 +4,8 @@
"Test": { "Test": {
"ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n", "ether_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n",
"time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n", "time_unit()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n",
"block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n}\n", "block_and_transactions()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n}\n",
"abi_encode()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n}\n", "abi_encode()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: NEW VARIABLE 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n}\n",
"member()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n}\n",
"error_handling()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n", "error_handling()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n}\n",
"math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n", "math_and_crypto()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: NEW VARIABLE 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: NEW VARIABLE 9\n\"];\n9->10;\n10[label=\"Node Type: EXPRESSION 10\n\"];\n}\n",
"address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n", "address_related()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n2->3;\n3[label=\"Node Type: EXPRESSION 3\n\"];\n3->4;\n4[label=\"Node Type: EXPRESSION 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: EXPRESSION 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: EXPRESSION 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n}\n",

@ -0,0 +1,119 @@
pragma experimental ABIEncoderV2;
contract A{}
interface I{}
contract Test{
function ether_unit() public{
1 wei;
1 ether;
}
function time_unit() public{
1 seconds;
1 minutes;
1 hours;
1 days;
1 weeks;
}
function block_and_transactions() payable public{
blockhash(0);
block.basefee;
block.chainid;
block.coinbase;
block.difficulty;
block.gaslimit;
block.number;
block.timestamp;
gasleft();
msg.data;
msg.sender;
msg.sig;
msg.value;
block.timestamp;
tx.gasprice;
tx.origin;
}
function abi_encode() public{
bytes memory m;
abi.decode(m, (uint, uint));
abi.encode(10);
abi.encodePacked(uint(10));
bytes4 selector;
abi.encodeWithSelector(selector, 10);
string memory signature;
abi.encodeWithSignature(signature, 10);
}
function member() public{
bytes1 b1;
bytes32 b32;
bytes.concat(b1, b32);
string.concat("", "");
}
function error_handling() public{
assert(true);
require(true);
require(true, "something");
revert();
revert("something");
}
function math_and_crypto() public{
addmod(0, 0, 1);
mulmod(0, 0, 1);
keccak256("");
sha256("");
ripemd160("");
bytes32 hash;
uint8 v;
bytes32 r;
bytes32 s;
ecrecover(hash,v,r,s);
}
function address_related() public{
address payable a;
a.balance;
a.code;
a.codehash;
a.send(0);
a.transfer(0);
a.call("");
a.delegatecall("");
a.staticcall("");
}
function return_addr() internal returns(address){}
function address_edge_case() public{
// For now slithIR loss precision on this edge case
// And create a Ref variable instead of a Temporary one
return_addr().balance;
return_addr().code;
return_addr().codehash;
}
function contract_related() public{
this;
address payable a;
selfdestruct(a);
}
function type_related() public{
type(A).name;
type(A).creationCode;
type(A).runtimeCode;
type(I).interfaceId;
type(uint256).min;
type(uint256).min;
}
}
Loading…
Cancel
Save