diff --git a/tests/test_missing_reentrancy_guard.py b/tests/test_missing_reentrancy_guard.py index 3c81e4c..2e8469f 100644 --- a/tests/test_missing_reentrancy_guard.py +++ b/tests/test_missing_reentrancy_guard.py @@ -1579,4 +1579,4 @@ def test_missing_reentrancy_guard(vulnerable_ast): ast_json, src_paths, ) - assert "Line 12 Columns 5-33" in results["results"][0]["lines"] + assert "Line 12 Columns 4-33" in results["results"][0]["lines"] diff --git a/tests/test_unspecific_pragma_detector.py b/tests/test_unspecific_pragma_detector.py new file mode 100644 index 0000000..a93f3a9 --- /dev/null +++ b/tests/test_unspecific_pragma_detector.py @@ -0,0 +1,66 @@ +import json +import pytest +from eburger.serializer import reduce_json +from eburger.yaml_parser import process_yaml + + +@pytest.fixture +def vulnerable_ast() -> tuple[dict, list]: + ast_json = """{ + "sources": { + "vulnerable_contracts/unspecific_pragma_detector.sol": { + "AST": { + "absolutePath": "vulnerable_contracts/unspecific_pragma_detector.sol", + "exportedSymbols": { + "OutOfControlContract": [ + 2 + ] + }, + "id": 3, + "license": "MIT", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + "^", + "0.8", + ".0" + ], + "nodeType": "PragmaDirective", + "src": "32:23:0" + }, + { + "abstract": false, + "baseContracts": [], + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 2, + "linearizedBaseContracts": [ + 2 + ], + "name": "OutOfControlContract", + "nodeType": "ContractDefinition", + "nodes": [], + "scope": 3, + "src": "57:32:0" + } + ], + "src": "32:58:0" + } + } + } +}""" + return json.loads(ast_json) + + +def test_unspecific_pragma_detector(vulnerable_ast): + ast_json, src_paths = reduce_json(vulnerable_ast) + results = process_yaml( + "eburger/templates/unspecific_pragma_detector.yaml", + ast_json, + src_paths, + ) + assert "Line 2 Columns 1-24" in results["results"][0]["lines"] diff --git a/tests/test_unverified_from_address_in_transfer.py b/tests/test_unverified_from_address_in_transfer.py new file mode 100644 index 0000000..8c3b0e7 --- /dev/null +++ b/tests/test_unverified_from_address_in_transfer.py @@ -0,0 +1,732 @@ +import json +import pytest +from eburger.serializer import reduce_json +from eburger.yaml_parser import process_yaml + + +@pytest.fixture +def vulnerable_ast() -> tuple[dict, list]: + ast_json = """{ + "sources": { + "vulnerable_contracts/unverified_from_address_in_transfer/src/unverified_from_address_in_transfer.sol": { + "id": 8, + "ast": { + "absolutePath": "vulnerable_contracts/unverified_from_address_in_transfer/src/unverified_from_address_in_transfer.sol", + "id": 937, + "exportedSymbols": { + "Address": [ + 849 + ], + "IERC1363": [ + 81 + ], + "IERC20": [ + 167 + ], + "InsecureTokenTransfer": [ + 936 + ], + "SafeERC20": [ + 590 + ] + }, + "nodeType": "SourceUnit", + "src": "32:796:8", + "nodes": [ + { + "id": 880, + "nodeType": "PragmaDirective", + "src": "32:23:8", + "nodes": [], + "literals": [ + "solidity", + "0.8", + ".20" + ] + }, + { + "id": 881, + "nodeType": "ImportDirective", + "src": "57:72:8", + "nodes": [], + "absolutePath": "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol", + "file": "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol", + "nameLocation": "-1:-1:-1", + "scope": 937, + "sourceUnit": 168, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 882, + "nodeType": "ImportDirective", + "src": "130:81:8", + "nodes": [], + "absolutePath": "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol", + "file": "../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol", + "nameLocation": "-1:-1:-1", + "scope": 937, + "sourceUnit": 591, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 936, + "nodeType": "ContractDefinition", + "src": "213:614:8", + "nodes": [ + { + "id": 886, + "nodeType": "UsingForDirective", + "src": "250:27:8", + "nodes": [], + "global": false, + "libraryName": { + "id": 883, + "name": "SafeERC20", + "nameLocations": [ + "256:9:8" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 590, + "src": "256:9:8" + }, + "typeName": { + "id": 885, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 884, + "name": "IERC20", + "nameLocations": [ + "270:6:8" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 167, + "src": "270:6:8" + }, + "referencedDeclaration": 167, + "src": "270:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + } + }, + { + "id": 889, + "nodeType": "VariableDeclaration", + "src": "283:21:8", + "nodes": [], + "constant": false, + "mutability": "mutable", + "name": "_token", + "nameLocation": "298:6:8", + "scope": 936, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + }, + "typeName": { + "id": 888, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 887, + "name": "IERC20", + "nameLocations": [ + "283:6:8" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 167, + "src": "283:6:8" + }, + "referencedDeclaration": 167, + "src": "283:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "visibility": "private" + }, + { + "id": 900, + "nodeType": "FunctionDefinition", + "src": "311:71:8", + "nodes": [], + "body": { + "id": 899, + "nodeType": "Block", + "src": "344:38:8", + "nodes": [], + "statements": [ + { + "expression": { + "id": 897, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 895, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 889, + "src": "354:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 896, + "name": "tokenAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 892, + "src": "363:12:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "src": "354:21:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "id": 898, + "nodeType": "ExpressionStatement", + "src": "354:21:8" + } + ] + }, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 893, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 892, + "mutability": "mutable", + "name": "tokenAddress", + "nameLocation": "330:12:8", + "nodeType": "VariableDeclaration", + "scope": 900, + "src": "323:19:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + }, + "typeName": { + "id": 891, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 890, + "name": "IERC20", + "nameLocations": [ + "323:6:8" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 167, + "src": "323:6:8" + }, + "referencedDeclaration": 167, + "src": "323:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "visibility": "internal" + } + ], + "src": "322:21:8" + }, + "returnParameters": { + "id": 894, + "nodeType": "ParameterList", + "parameters": [], + "src": "344:0:8" + }, + "scope": 936, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 918, + "nodeType": "FunctionDefinition", + "src": "388:145:8", + "nodes": [], + "body": { + "id": 917, + "nodeType": "Block", + "src": "471:62:8", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "id": 912, + "name": "sender", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 902, + "src": "501:6:8", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 913, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 904, + "src": "509:9:8", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 914, + "name": "value", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 906, + "src": "520:5:8", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 909, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 889, + "src": "481:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "id": 911, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "488:12:8", + "memberName": "transferFrom", + "nodeType": "MemberAccess", + "referencedDeclaration": 166, + "src": "481:19:8", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,address,uint256) external returns (bool)" + } + }, + "id": 915, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "481:45:8", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 916, + "nodeType": "ExpressionStatement", + "src": "481:45:8" + } + ] + }, + "functionSelector": "36c26e1b", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "insecureTransfer", + "nameLocation": "397:16:8", + "parameters": { + "id": 907, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 902, + "mutability": "mutable", + "name": "sender", + "nameLocation": "422:6:8", + "nodeType": "VariableDeclaration", + "scope": 918, + "src": "414:14:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 901, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "414:7:8", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 904, + "mutability": "mutable", + "name": "recipient", + "nameLocation": "438:9:8", + "nodeType": "VariableDeclaration", + "scope": 918, + "src": "430:17:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 903, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "430:7:8", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 906, + "mutability": "mutable", + "name": "value", + "nameLocation": "457:5:8", + "nodeType": "VariableDeclaration", + "scope": 918, + "src": "449:13:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 905, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "449:7:8", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "413:50:8" + }, + "returnParameters": { + "id": 908, + "nodeType": "ParameterList", + "parameters": [], + "src": "471:0:8" + }, + "scope": 936, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 935, + "nodeType": "FunctionDefinition", + "src": "598:226:8", + "nodes": [], + "body": { + "id": 934, + "nodeType": "Block", + "src": "665:159:8", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "expression": { + "id": 928, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "788:3:8", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 929, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "792:6:8", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "788:10:8", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 930, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 920, + "src": "800:9:8", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 931, + "name": "value", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 922, + "src": "811:5:8", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 925, + "name": "_token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 889, + "src": "768:6:8", + "typeDescriptions": { + "typeIdentifier": "t_contract$_IERC20_$167", + "typeString": "contract IERC20" + } + }, + "id": 927, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "775:12:8", + "memberName": "transferFrom", + "nodeType": "MemberAccess", + "referencedDeclaration": 166, + "src": "768:19:8", + "typeDescriptions": { + "typeIdentifier": "t_function_external_nonpayable$_t_address_$_t_address_$_t_uint256_$returns$_t_bool_$", + "typeString": "function (address,address,uint256) external returns (bool)" + } + }, + "id": 932, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "768:49:8", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 933, + "nodeType": "ExpressionStatement", + "src": "768:49:8" + } + ] + }, + "functionSelector": "fda7d818", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "secureTransferTo", + "nameLocation": "607:16:8", + "parameters": { + "id": 923, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 920, + "mutability": "mutable", + "name": "recipient", + "nameLocation": "632:9:8", + "nodeType": "VariableDeclaration", + "scope": 935, + "src": "624:17:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 919, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "624:7:8", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 922, + "mutability": "mutable", + "name": "value", + "nameLocation": "651:5:8", + "nodeType": "VariableDeclaration", + "scope": 935, + "src": "643:13:8", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 921, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "643:7:8", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "623:34:8" + }, + "returnParameters": { + "id": 924, + "nodeType": "ParameterList", + "parameters": [], + "src": "665:0:8" + }, + "scope": 936, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "InsecureTokenTransfer", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [ + 936 + ], + "name": "InsecureTokenTransfer", + "nameLocation": "222:21:8", + "scope": 937, + "usedErrors": [], + "usedEvents": [] + } + ], + "license": "MIT" + } + } + } +}""" + return json.loads(ast_json) + + +def test_unverified_from_address_in_transfer(vulnerable_ast): + ast_json, src_paths = reduce_json(vulnerable_ast) + results = process_yaml( + "eburger/templates/unverified_from_address_in_transfer.yaml", + ast_json, + src_paths, + ) + assert "Line 17 Columns 9-54" in results["results"][0]["lines"] diff --git a/tests/test_use_of_encodepacked.py b/tests/test_use_of_encodepacked.py new file mode 100644 index 0000000..fb9efb3 --- /dev/null +++ b/tests/test_use_of_encodepacked.py @@ -0,0 +1,800 @@ +import json +import pytest +from eburger.serializer import reduce_json +from eburger.yaml_parser import process_yaml + + +@pytest.fixture +def vulnerable_ast() -> tuple[dict, list]: + ast_json = """{ + "sources": { + "vulnerable_contracts/use_of_encodepacked.sol": { + "AST": { + "absolutePath": "vulnerable_contracts/use_of_encodepacked.sol", + "exportedSymbols": { + "BadCode": [ + 57 + ] + }, + "id": 58, + "license": "MIT", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + "0.8", + ".20" + ], + "nodeType": "PragmaDirective", + "src": "32:23:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "BadCode", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 57, + "linearizedBaseContracts": [ + 57 + ], + "name": "BadCode", + "nameLocation": "66:7:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "body": { + "id": 18, + "nodeType": "Block", + "src": "178:67:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "id": 13, + "name": "input1", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3, + "src": "222:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "id": 14, + "name": "input2", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 5, + "src": "230:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + }, + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "id": 11, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "205:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 12, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "209:12:0", + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "src": "205:16:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 15, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "205:32:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 10, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "195:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 16, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "195:43:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "functionReturnParameters": 9, + "id": 17, + "nodeType": "Return", + "src": "188:50:0" + } + ] + }, + "functionSelector": "1661d18a", + "id": 19, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "hashCollision1", + "nameLocation": "89:14:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 6, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 3, + "mutability": "mutable", + "name": "input1", + "nameLocation": "118:6:0", + "nodeType": "VariableDeclaration", + "scope": 19, + "src": "104:20:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 2, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "104:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 5, + "mutability": "mutable", + "name": "input2", + "nameLocation": "140:6:0", + "nodeType": "VariableDeclaration", + "scope": 19, + "src": "126:20:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 4, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "126:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "103:44:0" + }, + "returnParameters": { + "id": 9, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 8, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 19, + "src": "169:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 7, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "169:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "src": "168:9:0" + }, + "scope": 57, + "src": "80:165:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 37, + "nodeType": "Block", + "src": "351:67:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "id": 32, + "name": "input1", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 21, + "src": "395:6:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + }, + { + "id": 33, + "name": "input2", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 24, + "src": "403:6:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_memory_ptr", + "typeString": "uint256[] memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + }, + { + "typeIdentifier": "t_array$_t_uint256_$dyn_memory_ptr", + "typeString": "uint256[] memory" + } + ], + "expression": { + "id": 30, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "378:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 31, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "382:12:0", + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "src": "378:16:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 34, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "378:32:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 29, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "368:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 35, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "368:43:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "functionReturnParameters": 28, + "id": 36, + "nodeType": "Return", + "src": "361:50:0" + } + ] + }, + "functionSelector": "193b1d10", + "id": 38, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "hashCollision2", + "nameLocation": "260:14:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 25, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 21, + "mutability": "mutable", + "name": "input1", + "nameLocation": "288:6:0", + "nodeType": "VariableDeclaration", + "scope": 38, + "src": "275:19:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 20, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "275:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 24, + "mutability": "mutable", + "name": "input2", + "nameLocation": "313:6:0", + "nodeType": "VariableDeclaration", + "scope": 38, + "src": "296:23:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_memory_ptr", + "typeString": "uint256[]" + }, + "typeName": { + "baseType": { + "id": 22, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "296:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 23, + "nodeType": "ArrayTypeName", + "src": "296:9:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_uint256_$dyn_storage_ptr", + "typeString": "uint256[]" + } + }, + "visibility": "internal" + } + ], + "src": "274:46:0" + }, + "returnParameters": { + "id": 28, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 27, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 38, + "src": "342:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 26, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "342:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "src": "341:9:0" + }, + "scope": 57, + "src": "251:167:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 55, + "nodeType": "Block", + "src": "523:61:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "id": 50, + "name": "input1", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 40, + "src": "561:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + }, + { + "id": 51, + "name": "input2", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 42, + "src": "569:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + }, + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "id": 48, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "550:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 49, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "554:6:0", + "memberName": "encode", + "nodeType": "MemberAccess", + "src": "550:10:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 52, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "550:26:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 47, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "540:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 53, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "540:37:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "functionReturnParameters": 46, + "id": 54, + "nodeType": "Return", + "src": "533:44:0" + } + ] + }, + "functionSelector": "4b191d6f", + "id": 56, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "noHashCollision", + "nameLocation": "433:15:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 43, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 40, + "mutability": "mutable", + "name": "input1", + "nameLocation": "463:6:0", + "nodeType": "VariableDeclaration", + "scope": 56, + "src": "449:20:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 39, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "449:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 42, + "mutability": "mutable", + "name": "input2", + "nameLocation": "485:6:0", + "nodeType": "VariableDeclaration", + "scope": 56, + "src": "471:20:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 41, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "471:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + } + ], + "src": "448:44:0" + }, + "returnParameters": { + "id": 46, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 45, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 56, + "src": "514:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 44, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "514:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "src": "513:9:0" + }, + "scope": 57, + "src": "424:160:0", + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + } + ], + "scope": 58, + "src": "57:529:0", + "usedErrors": [], + "usedEvents": [] + } + ], + "src": "32:554:0" + }, + "id": 0 + } + } +}""" + return json.loads(ast_json) + + +def test_use_of_encodepacked(vulnerable_ast): + ast_json, src_paths = reduce_json(vulnerable_ast) + results = process_yaml( + "eburger/templates/use_of_encodepacked.yaml", + ast_json, + src_paths, + ) + assert "Line 6 Columns 26-42" in results["results"][0]["lines"] diff --git a/tests/test_use_of_safetransferlib.py b/tests/test_use_of_safetransferlib.py new file mode 100644 index 0000000..63185fd --- /dev/null +++ b/tests/test_use_of_safetransferlib.py @@ -0,0 +1,368 @@ +import json +import pytest +from eburger.serializer import reduce_json +from eburger.yaml_parser import process_yaml + + +@pytest.fixture +def vulnerable_ast() -> tuple[dict, list]: + ast_json = """{ + "sources": { + "vulnerable_contracts/use_of_safetransferlib/src/use_of_safetransferlib.sol": { + "id": 2, + "ast": { + "absolutePath": "vulnerable_contracts/use_of_safetransferlib/src/use_of_safetransferlib.sol", + "id": 501, + "exportedSymbols": { + "ERC20": [ + 387 + ], + "NotSoSafe": [ + 500 + ], + "SafeTransferLib": [ + 472 + ] + }, + "nodeType": "SourceUnit", + "src": "32:296:2", + "nodes": [ + { + "id": 474, + "nodeType": "PragmaDirective", + "src": "32:23:2", + "nodes": [], + "literals": [ + "solidity", + "0.8", + ".20" + ] + }, + { + "id": 477, + "nodeType": "ImportDirective", + "src": "56:84:2", + "nodes": [], + "absolutePath": "lib/solmate/src/utils/SafeTransferLib.sol", + "file": "../lib/solmate/src/utils/SafeTransferLib.sol", + "nameLocation": "-1:-1:-1", + "scope": 501, + "sourceUnit": 473, + "symbolAliases": [ + { + "foreign": { + "id": 475, + "name": "ERC20", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 387, + "src": "64:5:2", + "typeDescriptions": {} + }, + "nameLocation": "-1:-1:-1" + }, + { + "foreign": { + "id": 476, + "name": "SafeTransferLib", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 472, + "src": "71:15:2", + "typeDescriptions": {} + }, + "nameLocation": "-1:-1:-1" + } + ], + "unitAlias": "" + }, + { + "id": 500, + "nodeType": "ContractDefinition", + "src": "142:186:2", + "nodes": [ + { + "id": 481, + "nodeType": "UsingForDirective", + "src": "167:32:2", + "nodes": [], + "global": false, + "libraryName": { + "id": 478, + "name": "SafeTransferLib", + "nameLocations": [ + "173:15:2" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 472, + "src": "173:15:2" + }, + "typeName": { + "id": 480, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 479, + "name": "ERC20", + "nameLocations": [ + "193:5:2" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 387, + "src": "193:5:2" + }, + "referencedDeclaration": 387, + "src": "193:5:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$387", + "typeString": "contract ERC20" + } + } + }, + { + "id": 499, + "nodeType": "FunctionDefinition", + "src": "205:121:2", + "nodes": [], + "body": { + "id": 498, + "nodeType": "Block", + "src": "279:47:2", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "id": 494, + "name": "to", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 486, + "src": "308:2:2", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 495, + "name": "amount", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 488, + "src": "312:6:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 491, + "name": "token", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 484, + "src": "289:5:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$387", + "typeString": "contract ERC20" + } + }, + "id": 493, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "295:12:2", + "memberName": "safeTransfer", + "nodeType": "MemberAccess", + "referencedDeclaration": 451, + "src": "289:18:2", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_contract$_ERC20_$387_$_t_address_$_t_uint256_$returns$__$attached_to$_t_contract$_ERC20_$387_$", + "typeString": "function (contract ERC20,address,uint256)" + } + }, + "id": 496, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "289:30:2", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 497, + "nodeType": "ExpressionStatement", + "src": "289:30:2" + } + ] + }, + "functionSelector": "328373f0", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "sendSomeTokens", + "nameLocation": "214:14:2", + "parameters": { + "id": 489, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 484, + "mutability": "mutable", + "name": "token", + "nameLocation": "235:5:2", + "nodeType": "VariableDeclaration", + "scope": 499, + "src": "229:11:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$387", + "typeString": "contract ERC20" + }, + "typeName": { + "id": 483, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 482, + "name": "ERC20", + "nameLocations": [ + "229:5:2" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 387, + "src": "229:5:2" + }, + "referencedDeclaration": 387, + "src": "229:5:2", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ERC20_$387", + "typeString": "contract ERC20" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 486, + "mutability": "mutable", + "name": "to", + "nameLocation": "250:2:2", + "nodeType": "VariableDeclaration", + "scope": 499, + "src": "242:10:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 485, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "242:7:2", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 488, + "mutability": "mutable", + "name": "amount", + "nameLocation": "262:6:2", + "nodeType": "VariableDeclaration", + "scope": 499, + "src": "254:14:2", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 487, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "254:7:2", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "228:41:2" + }, + "returnParameters": { + "id": 490, + "nodeType": "ParameterList", + "parameters": [], + "src": "279:0:2" + }, + "scope": 500, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + } + ], + "abstract": false, + "baseContracts": [], + "canonicalName": "NotSoSafe", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [ + 500 + ], + "name": "NotSoSafe", + "nameLocation": "151:9:2", + "scope": 501, + "usedErrors": [], + "usedEvents": [] + } + ], + "license": "MIT" + } + } + } +}""" + return json.loads(ast_json) + + +def test_use_of_safetransferlib(vulnerable_ast): + ast_json, src_paths = reduce_json(vulnerable_ast) + results = process_yaml( + "eburger/templates/use_of_safetransferlib.yaml", + ast_json, + src_paths, + ) + assert "Line 3 Columns 1-85" in results["results"][0]["lines"]