[docs]def__init__(self):ifself.project.arch.name!="Soot":raiseSootClassHierarchyError("SootClassHierarchyError only supports analyzing Soot programs.")self.interface_implementers={}self.sub_interfaces={}self.dir_sub_interfaces={}self.sub_classes={}self.dir_sub_classes={}# init dataself.init_hierarchy()
[docs]definit_hierarchy(self):forclass_name,clsinself.project.loader.main_object.classes.items():if"INTERFACE"incls.attrs:self.interface_implementers[cls]=[]self.dir_sub_interfaces[cls]=[]else:self.dir_sub_classes[cls]=[]forclass_name,clsinself.project.loader.main_object.classes.items():ifself.has_super_class(cls):if"INTERFACE"incls.attrs:# TODO# super_interfacespasselse:super_class=self.project.loader.main_object.classes[cls.super_class]self.dir_sub_classes[super_class].append(cls)fori_nameincls.interfaces:# get interfaceifi_namenotinself.project.loader.main_object.classes:continuei=self.project.loader.main_object.classes[i_name]self.interface_implementers[i].append(cls)# fill direct implementers with subclassesforclass_name,clsinself.project.loader.main_object.classes.items():if"INTERFACE"incls.attrs:implementers=self.interface_implementers[cls]s=set()forcinimplementers:s|=set(self.get_sub_classes_including(c))self.interface_implementers[cls]=list(s)
[docs]defget_super_classes(self,cls):if"INTERFACE"incls.attrs:raiseSootClassHierarchyError("This is an Interface")super_classes=[]current=clstry:whileTrue:current=self.project.loader.main_object.classes[current.super_class]super_classes.append(current)exceptKeyError:returnsuper_classes
[docs]defget_implementers(self,interface):if"INTERFACE"notininterface.attrs:raiseSootClassHierarchyError("This is not an interface")res_set=set()foriinself.get_sub_interfaces_including(interface):res_set|=set(self.interface_implementers[i])returnlist(res_set)
[docs]defget_sub_interfaces(self,interface):if"INTERFACE"notininterface.attrs:raiseSootClassHierarchyError("This is not an interface")ifinterfaceinself.sub_interfaces:returnself.sub_interfaces[interface]# Otherwiseres=[]foriinself.dir_sub_interfaces[interface]:res.extend(self.get_sub_interfaces_including(i))self.sub_interfaces[interface]=resreturnres
[docs]defget_sub_classes(self,cls):if"INTERFACE"incls.attrs:raiseSootClassHierarchyError("This is an Interface. Class needed")ifclsinself.sub_classes:returnself.sub_classes[cls]res=[]forcinself.dir_sub_classes[cls]:res.extend(self.get_sub_classes_including(c))self.sub_classes[cls]=resreturnres
[docs]defget_sub_classes_including(self,cls):if"INTERFACE"incls.attrs:raiseSootClassHierarchyError("This is an Interface. Class needed")res=[]res.extend(self.get_sub_classes(cls))res.append(cls)returnres
[docs]defresolve_concrete_dispatch(self,cls,method):if"INTERFACE"incls.attrs:raiseSootClassHierarchyError("class needed!")forcinself.get_super_classes_including(cls):forminc.methods:ifm.name==method.nameandm.params==method.params:ifself.is_visible_method(c,method):returnmraiseNoConcreteDispatch("Could not resolve concrete dispatch!")
[docs]defresolve_special_dispatch(self,method,container):# container is the method that contains the invokemethod_cls=self.project.loader.main_object.classes[method.class_name]container_cls=self.project.loader.main_object.classes[container.class_name]ifmethod.name=="<init>"or"PRIVATE"inmethod.attrs:returnmethodelifself.is_subclass(method_cls,container_cls):returnself.resolve_concrete_dispatch(container_cls,method)else:returnmethod
[docs]defresolve_invoke(self,invoke_expr,method,container):# Generic method to resolve invoke# Given an invoke expression it figures out which "technique" should be appliedinvoke_type=str(type(invoke_expr))cls=self.project.loader.main_object.classes[method.class_name]if"VirtualInvokeExpr"ininvoke_type:targets=self.resolve_abstract_dispatch(cls,method)elif"DynamicInvokeExpr"ininvoke_type:targets=self.resolve_abstract_dispatch(cls,method)elif"InterfaceInvokeExpr"ininvoke_type:targets=self.resolve_abstract_dispatch(cls,method)elif"SpecialInvokeExpr"ininvoke_type:t=self.resolve_special_dispatch(method,container)targets=[t]elif"StaticInvokeExpr"ininvoke_type:targets=[method]returntargets