Exemple #1
0
    def _parse_contracts_from_json(self, json_data):
        first = json_data.find('{')
        if first != -1:
            last = json_data.rfind('}') + 1
            filename = json_data[0:first]
            json_data = json_data[first:last]

            data_loaded = json.loads(json_data)

            if data_loaded['name'] == 'root':
                self._solc_version = '0.3'
                logger.error('solc <0.4 is not supported')
                exit(-1)
            elif data_loaded['name'] == 'SourceUnit':
                self._solc_version = '0.4'
                self._parse_source_unit(data_loaded, filename)
            else:
                logger.error('solc version is not supported')
                exit(-1)

            for contract_data in data_loaded['children']:
                # if self.solc_version == '0.3':
                #     assert contract_data['name'] == 'Contract'
                #     contract = ContractSolc03(self, contract_data)
                if self.solc_version == '0.4':
                    assert contract_data['name'] in [
                        'ContractDefinition', 'PragmaDirective',
                        'ImportDirective'
                    ]
                    if contract_data['name'] == 'ContractDefinition':
                        contract = ContractSolc04(self, contract_data)
                        if 'src' in contract_data:
                            contract.set_offset(contract_data['src'], self)
                        self._contractsNotParsed.append(contract)
                    elif contract_data['name'] == 'PragmaDirective':
                        pragma = Pragma(
                            contract_data['attributes']["literals"])
                        pragma.set_offset(contract_data['src'], self)
                        self._pragma_directives.append(pragma)
                    elif contract_data['name'] == 'ImportDirective':
                        import_directive = Import(
                            contract_data['attributes']["absolutePath"])
                        import_directive.set_offset(contract_data['src'], self)
                        self._import_directives.append(import_directive)

            return True
        return False
Exemple #2
0
    def _parse_contracts_from_loaded_json(self, data_loaded, filename):
        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):
                    with open(sourcePath, encoding='utf8') as f:
                        source_code = f.read()
                    self.source_code[sourcePath] = source_code

        if data_loaded[self.get_key()] == 'root':
            self._solc_version = '0.3'
            logger.error('solc <0.4 is not supported')
            return
        elif data_loaded[self.get_key()] == 'SourceUnit':
            self._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()]:
            # if self.solc_version == '0.3':
            #     assert contract_data[self.get_key()] == 'Contract'
            #     contract = ContractSolc03(self, contract_data)
            if self.solc_version == '0.4':
                assert contract_data[self.get_key()] in [
                    'ContractDefinition', 'PragmaDirective', 'ImportDirective'
                ]
                if contract_data[self.get_key()] == 'ContractDefinition':
                    contract = ContractSolc04(self, contract_data)
                    if 'src' in contract_data:
                        contract.set_offset(contract_data['src'], self)
                    self._contractsNotParsed.append(contract)
                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)
                    self._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']["absolutePath"])
                    import_directive.set_offset(contract_data['src'], self)
                    self._import_directives.append(import_directive)
Exemple #3
0
def _handle_import_aliases(symbol_aliases: Dict, import_directive: Import,
                           scope: FileScope) -> None:
    """
    Handle the parsing of import aliases

    Args:
        symbol_aliases (Dict): json dict from solc
        import_directive (Import): current import directive
        scope (FileScope): current file scape

    Returns:

    """
    for symbol_alias in symbol_aliases:
        if ("foreign" in symbol_alias and "name" in symbol_alias["foreign"]
                and "local" in symbol_alias):
            original_name = symbol_alias["foreign"]["name"]
            local_name = symbol_alias["local"]
            import_directive.renaming[local_name] = original_name
            # Assuming that two imports cannot collide in renaming
            scope.renaming[local_name] = original_name
Exemple #4
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")
Exemple #6
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"
                )
Exemple #7
0
    def _parse_contracts_from_loaded_json(self, data_loaded, filename):
        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._add_source_code(sourcePath)

        if data_loaded[self.get_key()] == 'root':
            self._solc_version = '0.3'
            logger.error('solc <0.4 is not supported')
            return
        elif data_loaded[self.get_key()] == 'SourceUnit':
            self._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 = ContractSolc04(self, contract_data)
                if 'src' in contract_data:
                    contract.set_offset(contract_data['src'], self)
                self._contractsNotParsed.append(contract)
            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)
                self._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']["absolutePath"])
                import_directive.set_offset(contract_data['src'], self)
                self._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,  # TODO: determine if collission possible
                    'linearizedBaseContracts': [],
                    'fullyImplemented': True,
                    'contractKind': 'SLitherInternal'
                }
                self._top_level_contracts_counter += 1
                top_level_contract = ContractSolc04(self, fake_contract_data)
                top_level_contract.is_top_level = True
                top_level_contract.set_offset(contract_data['src'], self)

                if contract_data[self.get_key()] == 'StructDefinition':
                    top_level_contract._structuresNotParsed.append(
                        contract_data)  # Todo add proper setters
                else:
                    top_level_contract._enumsNotParsed.append(
                        contract_data)  # Todo add proper setters

                self._contractsNotParsed.append(top_level_contract)