def parse_type(t, caller_context): # local import to avoid circular dependency from slither.solc_parsing.expressions.expression_parsing import parse_expression from slither.solc_parsing.variables.function_type_variable import FunctionTypeVariableSolc if isinstance(caller_context, Contract): contract = caller_context elif isinstance(caller_context, Function): contract = caller_context.contract else: raise ParsingError('Incorrect caller context') is_compact_ast = caller_context.is_compact_ast if is_compact_ast: key = 'nodeType' else: key = 'name' structures = contract.structures enums = contract.enums contracts = contract.slither.contracts if isinstance(t, UnknownType): return _find_from_type_name(t.name, contract, contracts, structures, enums) elif t[key] == 'ElementaryTypeName': if is_compact_ast: return ElementaryType(t['name']) return ElementaryType(t['attributes'][key]) elif t[key] == 'UserDefinedTypeName': if is_compact_ast: return _find_from_type_name(t['typeDescriptions']['typeString'], contract, contracts, structures, enums) # Determine if we have a type node (otherwise we use the name node, as some older solc did not have 'type'). type_name_key = 'type' if 'type' in t['attributes'] else key return _find_from_type_name(t['attributes'][type_name_key], contract, contracts, structures, enums) elif t[key] == 'ArrayTypeName': length = None if is_compact_ast: if t['length']: length = parse_expression(t['length'], caller_context) array_type = parse_type(t['baseType'], contract) else: if len(t['children']) == 2: length = parse_expression(t['children'][1], caller_context) else: assert len(t['children']) == 1 array_type = parse_type(t['children'][0], contract) return ArrayType(array_type, length) elif t[key] == 'Mapping': if is_compact_ast: mappingFrom = parse_type(t['keyType'], contract) mappingTo = parse_type(t['valueType'], contract) else: assert len(t['children']) == 2 mappingFrom = parse_type(t['children'][0], contract) mappingTo = parse_type(t['children'][1], contract) return MappingType(mappingFrom, mappingTo) elif t[key] == 'FunctionTypeName': if is_compact_ast: params = t['parameterTypes'] return_values = t['returnParameterTypes'] index = 'parameters' else: assert len(t['children']) == 2 params = t['children'][0] return_values = t['children'][1] index = 'children' assert params[key] == 'ParameterList' assert return_values[key] == 'ParameterList' params_vars = [] return_values_vars = [] for p in params[index]: var = FunctionTypeVariableSolc(p) var.set_offset(p['src'], caller_context.slither) var.analyze(caller_context) params_vars.append(var) for p in return_values[index]: var = FunctionTypeVariableSolc(p) var.set_offset(p['src'], caller_context.slither) var.analyze(caller_context) return_values_vars.append(var) return FunctionType(params_vars, return_values_vars) raise ParsingError('Type name not found ' + str(t))
def parse_type(t, caller_context): # local import to avoid circular dependency from slither.solc_parsing.expressions.expression_parsing import parse_expression from slither.solc_parsing.variables.function_type_variable import FunctionTypeVariableSolc if isinstance(caller_context, Contract): contract = caller_context elif isinstance(caller_context, Function): contract = caller_context.contract else: logger.error('Incorrect caller context') exit(-1) structures = contract.structures enums = contract.enums contracts = contract.slither.contracts if isinstance(t, UnknownType): return _find_from_type_name(t.name, contract, contracts, structures, enums) elif t['name'] == 'ElementaryTypeName': return ElementaryType(t['attributes']['name']) elif t['name'] == 'UserDefinedTypeName': return _find_from_type_name(t['attributes']['name'], contract, contracts, structures, enums) elif t['name'] == 'ArrayTypeName': length = None if len(t['children']) == 2: length = parse_expression(t['children'][1], caller_context) else: assert len(t['children']) == 1 array_type = parse_type(t['children'][0], contract) return ArrayType(array_type, length) elif t['name'] == 'Mapping': assert len(t['children']) == 2 mappingFrom = parse_type(t['children'][0], contract) mappingTo = parse_type(t['children'][1], contract) return MappingType(mappingFrom, mappingTo) elif t['name'] == 'FunctionTypeName': assert len(t['children']) == 2 params = t['children'][0] return_values = t['children'][1] assert params['name'] == 'ParameterList' assert return_values['name'] == 'ParameterList' params_vars = [] return_values_vars = [] for p in params['children']: var = FunctionTypeVariableSolc(p) var.set_offset(p['src'], caller_context.slither) var.analyze(caller_context) params_vars.append(var) for p in return_values['children']: var = FunctionTypeVariableSolc(p) var.set_offset(p['src'], caller_context.slither) var.analyze(caller_context) return_values_vars.append(var) return FunctionType(params_vars, return_values_vars) logger.error('Type name not found ' + str(t)) exit(-1)