diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 7bae88c5cc..c8b69d4b22 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -512,7 +512,7 @@ def parse_contracts(self): # pylint: disable=too-many-statements,too-many-branc self._analyze_third_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self._underlying_contract_to_parser.values()] - self._analyze_using_for(contracts_to_be_analyzed) + self._analyze_using_for(contracts_to_be_analyzed, libraries) self._parsed = True @@ -624,9 +624,14 @@ def _analyze_third_part( else: contracts_to_be_analyzed += [contract] - def _analyze_using_for(self, contracts_to_be_analyzed: List[ContractSolc]): + def _analyze_using_for( + self, contracts_to_be_analyzed: List[ContractSolc], libraries: List[ContractSolc] + ): self._analyze_top_level_using_for() + for lib in libraries: + lib.analyze_using_for() + while contracts_to_be_analyzed: contract = contracts_to_be_analyzed[0] diff --git a/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip new file mode 100644 index 0000000000..ca32c7583b Binary files /dev/null and b/tests/ast-parsing/compile/using-for-in-library-0.8.0.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json b/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json new file mode 100644 index 0000000000..4975ab40a6 --- /dev/null +++ b/tests/ast-parsing/expected/using-for-in-library-0.8.0.sol-0.8.15-compact.json @@ -0,0 +1,8 @@ +{ + "A": { + "a(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + }, + "B": { + "b(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: RETURN 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/using-for-in-library-0.8.0.sol b/tests/ast-parsing/using-for-in-library-0.8.0.sol new file mode 100644 index 0000000000..0e8f6a6b9f --- /dev/null +++ b/tests/ast-parsing/using-for-in-library-0.8.0.sol @@ -0,0 +1,14 @@ + +library A { + using B for uint256; + + function a(uint256 v) public view returns (uint) { + return v.b(); + } +} + +library B { + function b(uint256 v) public view returns (uint) { + return 1; + } +} diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py index 0d6118601d..7e22ea1866 100644 --- a/tests/test_ast_parsing.py +++ b/tests/test_ast_parsing.py @@ -428,6 +428,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]: Test("using-for-2-0.8.0.sol", ["0.8.15"]), Test("using-for-3-0.8.0.sol", ["0.8.15"]), Test("using-for-4-0.8.0.sol", ["0.8.15"]), + Test("using-for-in-library-0.8.0.sol", ["0.8.15"]), Test("using-for-alias-contract-0.8.0.sol", ["0.8.15"]), Test("using-for-alias-top-level-0.8.0.sol", ["0.8.15"]), Test("using-for-functions-list-1-0.8.0.sol", ["0.8.15"]), diff --git a/tests/test_features.py b/tests/test_features.py index a5541b5891..924e0b1543 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -128,3 +128,14 @@ def test_using_for_alias_contract() -> None: if isinstance(ir, InternalCall) and ir.function_name == "a": return assert False + + +def test_using_for_in_library() -> None: + solc_select.switch_global_version("0.8.15", always_install=True) + slither = Slither("./tests/ast-parsing/using-for-in-library-0.8.0.sol") + contract_c = slither.get_contract_from_name("A")[0] + libCall = contract_c.get_function_from_full_name("a(uint256)") + for ir in libCall.all_slithir_operations(): + if isinstance(ir, LibraryCall) and ir.destination == "B" and ir.function_name == "b": + return + assert False