Пример #1
0
    def _analyze_struct_events(self, contract: ContractSolc):

        contract.analyze_constant_state_variables()

        # Struct can refer to enum, or state variables
        contract.analyze_structs()
        # Event can refer to struct
        contract.analyze_events()

        contract.analyze_using_for()

        contract.set_is_analyzed(True)
Пример #2
0
    def _analyze_variables_modifiers_functions(self, contract: ContractSolc):
        # State variables, modifiers and functions can refer to anything

        contract.analyze_params_modifiers()
        contract.analyze_params_functions()

        contract.analyze_state_variables()

        contract.analyze_content_modifiers()
        contract.analyze_content_functions()

        contract.set_is_analyzed(True)
Пример #3
0
 def _parse_struct_var_modifiers_functions(self, contract: ContractSolc):
     contract.parse_structs()  # struct can refer another struct
     contract.parse_state_variables()
     contract.parse_modifiers()
     contract.parse_functions()
     contract.set_is_analyzed(True)
Пример #4
0
 def _analyze_enums(self, contract: ContractSolc):
     # Enum must be analyzed first
     contract.analyze_enums()
     contract.set_is_analyzed(True)
Пример #5
0
    def parse_contracts_from_loaded_json(
        self, data_loaded: Dict, filename: str
    ):  # pylint: disable=too-many-branches
        if "nodeType" in data_loaded:
            self._is_compact_ast = True

        if "sourcePaths" in data_loaded:
            for sourcePath in data_loaded["sourcePaths"]:
                if os.path.isfile(sourcePath):
                    self._core.add_source_code(sourcePath)

        if data_loaded[self.get_key()] == "root":
            self._core.solc_version = "0.3"
            logger.error("solc <0.4 is not supported")
            return
        if data_loaded[self.get_key()] == "SourceUnit":
            self._core.solc_version = "0.4"
            self._parse_source_unit(data_loaded, filename)
        else:
            logger.error("solc version is not supported")
            return

        for contract_data in data_loaded[self.get_children()]:
            assert contract_data[self.get_key()] in [
                "ContractDefinition",
                "PragmaDirective",
                "ImportDirective",
                "StructDefinition",
                "EnumDefinition",
            ]
            if contract_data[self.get_key()] == "ContractDefinition":
                contract = Contract()
                contract_parser = ContractSolc(self, contract, contract_data)
                if "src" in contract_data:
                    contract.set_offset(contract_data["src"], self._core)

                self._underlying_contract_to_parser[contract] = contract_parser

            elif contract_data[self.get_key()] == "PragmaDirective":
                if self._is_compact_ast:
                    pragma = Pragma(contract_data["literals"])
                else:
                    pragma = Pragma(contract_data["attributes"]["literals"])
                pragma.set_offset(contract_data["src"], self._core)
                self._core.pragma_directives.append(pragma)
            elif contract_data[self.get_key()] == "ImportDirective":
                if self.is_compact_ast:
                    import_directive = Import(contract_data["absolutePath"])
                else:
                    import_directive = Import(contract_data["attributes"].get("absolutePath", ""))
                import_directive.set_offset(contract_data["src"], self._core)
                self._core.import_directives.append(import_directive)

            elif contract_data[self.get_key()] in [
                "StructDefinition",
                "EnumDefinition",
            ]:
                # This can only happen for top-level structure and enum
                # They were introduced with 0.6.5
                assert self._is_compact_ast  # Do not support top level definition for legacy AST
                fake_contract_data = {
                    "name": f"SlitherInternalTopLevelContract{self._top_level_contracts_counter}",
                    "id": -1000
                    + self._top_level_contracts_counter,  # TODO: determine if collission possible
                    "linearizedBaseContracts": [],
                    "fullyImplemented": True,
                    "contractKind": "SLitherInternal",
                }
                self._top_level_contracts_counter += 1
                contract = Contract()
                top_level_contract = ContractSolc(self, contract, fake_contract_data)
                contract.is_top_level = True
                contract.set_offset(contract_data["src"], self._core)

                if contract_data[self.get_key()] == "StructDefinition":
                    top_level_contract.structures_not_parsed.append(
                        contract_data
                    )  # Todo add proper setters
                else:
                    top_level_contract.enums_not_parsed.append(
                        contract_data
                    )  # Todo add proper setters

                self._underlying_contract_to_parser[contract] = top_level_contract
    def parse_top_level_from_loaded_json(
        self, data_loaded: Dict, filename: str
    ):  # pylint: disable=too-many-branches,too-many-statements
        if "nodeType" in data_loaded:
            self._is_compact_ast = True

        if "sourcePaths" in data_loaded:
            for sourcePath in data_loaded["sourcePaths"]:
                if os.path.isfile(sourcePath):
                    self._compilation_unit.core.add_source_code(sourcePath)

        if data_loaded[self.get_key()] == "root":
            logger.error("solc <0.4 is not supported")
            return
        if data_loaded[self.get_key()] == "SourceUnit":
            self._parse_source_unit(data_loaded, filename)
        else:
            logger.error("solc version is not supported")
            return

        for top_level_data in data_loaded[self.get_children()]:
            if top_level_data[self.get_key()] == "ContractDefinition":
                contract = Contract(self._compilation_unit)
                contract_parser = ContractSolc(self, contract, top_level_data)
                if "src" in top_level_data:
                    contract.set_offset(top_level_data["src"], self._compilation_unit)

                self._underlying_contract_to_parser[contract] = contract_parser

            elif top_level_data[self.get_key()] == "PragmaDirective":
                if self._is_compact_ast:
                    pragma = Pragma(top_level_data["literals"])
                else:
                    pragma = Pragma(top_level_data["attributes"]["literals"])
                pragma.set_offset(top_level_data["src"], self._compilation_unit)
                self._compilation_unit.pragma_directives.append(pragma)
            elif top_level_data[self.get_key()] == "ImportDirective":
                if self.is_compact_ast:
                    import_directive = Import(top_level_data["absolutePath"])
                    # TODO investigate unitAlias in version < 0.7 and legacy ast
                    if "unitAlias" in top_level_data:
                        import_directive.alias = top_level_data["unitAlias"]
                else:
                    import_directive = Import(top_level_data["attributes"].get("absolutePath", ""))
                import_directive.set_offset(top_level_data["src"], self._compilation_unit)
                self._compilation_unit.import_directives.append(import_directive)

            elif top_level_data[self.get_key()] == "StructDefinition":
                st = StructureTopLevel()
                st.set_offset(top_level_data["src"], self._compilation_unit)
                st_parser = StructureTopLevelSolc(st, top_level_data, self)

                self._compilation_unit.structures_top_level.append(st)
                self._structures_top_level_parser.append(st_parser)

            elif top_level_data[self.get_key()] == "EnumDefinition":
                # Note enum don't need a complex parser, so everything is directly done
                self._parse_enum(top_level_data)

            elif top_level_data[self.get_key()] == "VariableDeclaration":
                var = TopLevelVariable()
                var_parser = TopLevelVariableSolc(var, top_level_data)
                var.set_offset(top_level_data["src"], self._compilation_unit)

                self._compilation_unit.variables_top_level.append(var)
                self._variables_top_level_parser.append(var_parser)
            elif top_level_data[self.get_key()] == "FunctionDefinition":
                func = FunctionTopLevel(self._compilation_unit)
                func_parser = FunctionSolc(func, top_level_data, None, self)

                self._compilation_unit.functions_top_level.append(func)
                self._functions_top_level_parser.append(func_parser)
                self.add_function_or_modifier_parser(func_parser)

            else:
                raise SlitherException(f"Top level {top_level_data[self.get_key()]} not supported")
Пример #7
0
    def parse_top_level_from_loaded_json(self, data_loaded: Dict,
                                         filename: str):  # pylint: disable=too-many-branches,too-many-statements,too-many-locals
        if "nodeType" in data_loaded:
            self._is_compact_ast = True

        if "sourcePaths" in data_loaded:
            for sourcePath in data_loaded["sourcePaths"]:
                if os.path.isfile(sourcePath):
                    self._compilation_unit.core.add_source_code(sourcePath)

        if data_loaded[self.get_key()] == "root":
            logger.error("solc <0.4 is not supported")
            return
        if data_loaded[self.get_key()] == "SourceUnit":
            self._parse_source_unit(data_loaded, filename)
        else:
            logger.error("solc version is not supported")
            return

        if self.get_children() not in data_loaded:
            return
        scope = self.compilation_unit.get_scope(filename)

        for top_level_data in data_loaded[self.get_children()]:
            if top_level_data[self.get_key()] == "ContractDefinition":
                contract = Contract(self._compilation_unit, scope)
                contract_parser = ContractSolc(self, contract, top_level_data)
                scope.contracts[contract.name] = contract
                if "src" in top_level_data:
                    contract.set_offset(top_level_data["src"],
                                        self._compilation_unit)

                self._underlying_contract_to_parser[contract] = contract_parser

            elif top_level_data[self.get_key()] == "PragmaDirective":
                if self._is_compact_ast:
                    pragma = Pragma(top_level_data["literals"], scope)
                    scope.pragmas.add(pragma)
                else:
                    pragma = Pragma(top_level_data["attributes"]["literals"],
                                    scope)
                    scope.pragmas.add(pragma)
                pragma.set_offset(top_level_data["src"],
                                  self._compilation_unit)
                self._compilation_unit.pragma_directives.append(pragma)
            elif top_level_data[self.get_key()] == "ImportDirective":
                if self.is_compact_ast:
                    import_directive = Import(
                        Path(top_level_data["absolutePath"], ),
                        scope,
                    )
                    scope.imports.add(import_directive)
                    # TODO investigate unitAlias in version < 0.7 and legacy ast
                    if "unitAlias" in top_level_data:
                        import_directive.alias = top_level_data["unitAlias"]
                    if "symbolAliases" in top_level_data:
                        symbol_aliases = top_level_data["symbolAliases"]
                        _handle_import_aliases(symbol_aliases,
                                               import_directive, scope)
                else:
                    import_directive = Import(
                        Path(
                            top_level_data["attributes"].get(
                                "absolutePath", ""), ),
                        scope,
                    )
                    scope.imports.add(import_directive)
                    # TODO investigate unitAlias in version < 0.7 and legacy ast
                    if ("attributes" in top_level_data
                            and "unitAlias" in top_level_data["attributes"]):
                        import_directive.alias = top_level_data["attributes"][
                            "unitAlias"]
                import_directive.set_offset(top_level_data["src"],
                                            self._compilation_unit)
                self._compilation_unit.import_directives.append(
                    import_directive)

                get_imported_scope = self.compilation_unit.get_scope(
                    import_directive.filename)
                scope.accessible_scopes.append(get_imported_scope)

            elif top_level_data[self.get_key()] == "StructDefinition":
                scope = self.compilation_unit.get_scope(filename)
                st = StructureTopLevel(self.compilation_unit, scope)
                st.set_offset(top_level_data["src"], self._compilation_unit)
                st_parser = StructureTopLevelSolc(st, top_level_data, self)
                scope.structures[st.name] = st

                self._compilation_unit.structures_top_level.append(st)
                self._structures_top_level_parser.append(st_parser)

            elif top_level_data[self.get_key()] == "EnumDefinition":
                # Note enum don't need a complex parser, so everything is directly done
                self._parse_enum(top_level_data, filename)

            elif top_level_data[self.get_key()] == "VariableDeclaration":
                var = TopLevelVariable(scope)
                var_parser = TopLevelVariableSolc(var, top_level_data, self)
                var.set_offset(top_level_data["src"], self._compilation_unit)

                self._compilation_unit.variables_top_level.append(var)
                self._variables_top_level_parser.append(var_parser)
                scope.variables[var.name] = var
            elif top_level_data[self.get_key()] == "FunctionDefinition":
                scope = self.compilation_unit.get_scope(filename)
                func = FunctionTopLevel(self._compilation_unit, scope)
                scope.functions.add(func)
                func.set_offset(top_level_data["src"], self._compilation_unit)
                func_parser = FunctionSolc(func, top_level_data, None, self)

                self._compilation_unit.functions_top_level.append(func)
                self._functions_top_level_parser.append(func_parser)
                self.add_function_or_modifier_parser(func_parser)

            elif top_level_data[self.get_key()] == "ErrorDefinition":
                scope = self.compilation_unit.get_scope(filename)
                custom_error = CustomErrorTopLevel(self._compilation_unit,
                                                   scope)
                custom_error.set_offset(top_level_data["src"],
                                        self._compilation_unit)

                custom_error_parser = CustomErrorSolc(custom_error,
                                                      top_level_data, self)
                scope.custom_errors.add(custom_error)
                self._compilation_unit.custom_errors.append(custom_error)
                self._custom_error_parser.append(custom_error_parser)

            elif top_level_data[
                    self.get_key()] == "UserDefinedValueTypeDefinition":
                assert "name" in top_level_data
                alias = top_level_data["name"]
                assert "underlyingType" in top_level_data
                underlying_type = top_level_data["underlyingType"]
                assert ("nodeType" in underlying_type and
                        underlying_type["nodeType"] == "ElementaryTypeName")
                assert "name" in underlying_type

                original_type = ElementaryType(underlying_type["name"])

                user_defined_type = TypeAliasTopLevel(original_type, alias,
                                                      scope)
                user_defined_type.set_offset(top_level_data["src"],
                                             self._compilation_unit)
                scope.user_defined_types[alias] = user_defined_type

            else:
                raise SlitherException(
                    f"Top level {top_level_data[self.get_key()]} not supported"
                )