void addLocation(CallLocation location) { if (callLocations.putIfAbsent(location.getMethod(), location) == null) { for (MethodDependency method : methods) { method.addLocation(location); } } } }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); Set<MethodReference> callbackMethods = repository.callbackMethods.get(ref); if (callbackMethods != null) { for (MethodReference callbackMethod : callbackMethods) { agent.linkMethod(callbackMethod).addLocation(new CallLocation(ref)).use(); } } }
void initClass(ClassDependency cls, CallLocation location) { ClassReader reader = cls.getClassReader(); MethodReader method = reader.getMethod(CLINIT_METHOD); if (method != null) { deferredTasks.add(() -> { MethodDependency initMethod = linkMethod(method.getReference()); if (location != null) { initMethod.addLocation(location); } initMethod.use(); }); } }
@Override public void consume(DependencyType type) { String className = type.getName(); if (DependencyAnalyzer.shouldLog) { System.out.println("Virtual call of " + methodDesc + " detected on " + node.getTag() + ". " + "Target class is " + className); } if (className.startsWith("[")) { className = "java.lang.Object"; type = analyzer.getType(className); } MethodDependency methodDep = analyzer.linkMethod(className, methodDesc); if (!methods.add(methodDep)) { return; } for (CallLocation location : callLocations.values()) { methodDep.addLocation(location); } if (!methodDep.isMissing()) { methodDep.use(); } }
@Override public void cloneArray(VariableReader receiver, VariableReader array) { DependencyNode arrayNode = getNode(array); MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); cloneDep.addLocation(impreciseLocation); cloneDep.use(); }
@Override protected void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments) { CallLocation callLocation = impreciseLocation; if (instance == null) { dependencyAnalyzer.linkClass(method.getClassName()).initClass(callLocation); } MethodDependency methodDep = dependencyAnalyzer.linkMethod(method); methodDep.addLocation(callLocation); methodDep.use(); }
private void attachConstructor(DependencyAgent agent, String type, CallLocation location) { MethodReference ref = new MethodReference(type, "<init>", ValueType.VOID); MethodDependency methodDep = agent.linkMethod(ref); methodDep.addLocation(location); methodDep.getVariable(0).propagate(agent.getType(type)); methodDep.use(); } }
@Override protected void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, List<? extends VariableReader> arguments) { DependencyNode[] actualArgs = new DependencyNode[arguments.size() + 1]; for (int i = 0; i < arguments.size(); ++i) { actualArgs[i + 1] = nodes[arguments.get(i).getIndex()]; } actualArgs[0] = getNode(instance); DependencyConsumer listener = new VirtualCallConsumer(getNode(instance), method.getClassName(), method.getDescriptor(), dependencyAnalyzer, actualArgs, receiver != null ? getNode(receiver) : null, getCallLocation(), currentExceptionConsumer); getNode(instance).addConsumer(listener); dependencyAnalyzer.getClassSource().overriddenMethods(method).forEach(methodImpl -> { dependencyAnalyzer.linkMethod(methodImpl.getReference()).addLocation(getCallLocation()); }); }
@Override public void nullCheck(VariableReader receiver, VariableReader value) { DependencyNode valueNode = getNode(value); DependencyNode receiverNode = getNode(receiver); if (valueNode != null) { valueNode.connect(receiverNode); } MethodDependency npeMethod = getAnalyzer().linkMethod(NPE_INIT_METHOD); npeMethod.addLocation(getCallLocation()); npeMethod.use(); }
@Override public void stringConstant(VariableReader receiver, String cst) { DependencyNode node = getNode(receiver); if (node != null) { node.propagate(getAnalyzer().getType("java.lang.String")); } MethodDependency method = getAnalyzer().linkMethod(STRING_INIT_FROM_CHARS_METHOD); method.addLocation(getCallLocation()); method.use(); }
@Override public void monitorEnter(VariableReader objectRef) { if (getAnalyzer().asyncSupported) { MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_ENTER_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); } MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_ENTER_SYNC_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); }
@Override public void monitorExit(VariableReader objectRef) { if (getAnalyzer().asyncSupported) { MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_EXIT_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); } MethodDependency methodDep = getAnalyzer().linkMethod(MONITOR_EXIT_SYNC_METHOD); methodDep.addLocation(getCallLocation()); getNode(objectRef).connect(methodDep.getVariable(1)); methodDep.use(); }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { MethodReference ref = method.getReference(); if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) { List<ServiceLoaderFilter> filters = getFilters(agent); method.getResult().propagate(agent.getType("[Ljava/lang/Object;")); DependencyNode sourceNode = agent.linkMethod(LOAD_METHOD).getVariable(1).getClassValueNode(); sourceNode.connect(method.getResult().getArrayItem()); sourceNode.addConsumer(type -> { CallLocation location = new CallLocation(LOAD_METHOD); for (String implementationType : getImplementations(type.getName())) { if (filters.stream().anyMatch(filter -> !filter.apply(type.getName(), implementationType))) { continue; } serviceMap.computeIfAbsent(type.getName(), k -> new ArrayList<>()).add(implementationType); MethodReference ctor = new MethodReference(implementationType, new MethodDescriptor("<init>", ValueType.VOID)); agent.linkMethod(ctor).addLocation(location).use(); method.getResult().getArrayItem().propagate(agent.getType(implementationType)); } }); } }
@Override public void cloneArray(VariableReader receiver, VariableReader array) { DependencyNode arrayNode = getNode(array); DependencyNode receiverNode = getNode(receiver); if (arrayNode != null && receiverNode != null) { arrayNode.addConsumer(receiverNode::propagate); arrayNode.getArrayItem().connect(receiverNode.getArrayItem()); } MethodDependency cloneDep = getAnalyzer().linkMethod(CLONE_METHOD); cloneDep.addLocation(getCallLocation()); arrayNode.connect(cloneDep.getVariable(0)); cloneDep.use(); }
@Override public void methodReached(DependencyAgent agent, MethodDependency method) { if (method.getReference().getClassName().equals(Platform.class.getName()) && method.getReference().getName().equals("getEnumConstants")) { allEnums.connect(method.getResult().getArrayItem()); final MethodReference ref = method.getReference(); allEnums.addConsumer(type -> { ClassReader cls = agent.getClassSource().get(type.getName()); MethodReader valuesMethod = cls.getMethod(new MethodDescriptor("values", ValueType.arrayOf(ValueType.object(cls.getName())))); if (valuesMethod != null) { MethodDependency valuesDep = agent.linkMethod(valuesMethod.getReference()); valuesDep.addLocation(new CallLocation(ref)); valuesDep.use(); } }); method.getResult().propagate(agent.getType("[Ljava/lang/Enum;")); for (String cls : agent.getReachableClasses()) { classReached(agent, cls); } } } }
private MethodDependency installAdditionalDependencies() { MethodDependency nameDep = agent.linkMethod(new MethodReference(Class.class, "getName", String.class)); nameDep.addLocation(location); nameDep.getVariable(0).propagate(agent.getType(Class.class.getName())); nameDep.getThrown().connect(methodDep.getThrown()); nameDep.use(); MethodDependency equalsDep = agent.linkMethod(new MethodReference(String.class, "equals", Object.class, boolean.class)); equalsDep.addLocation(location); nameDep.getResult().connect(equalsDep.getVariable(0)); equalsDep.getVariable(1).propagate(agent.getType("java.lang.String")); equalsDep.getThrown().connect(methodDep.getThrown()); equalsDep.use(); MethodDependency hashCodeDep = agent.linkMethod(new MethodReference(String.class, "hashCode", int.class)); hashCodeDep.addLocation(location); hashCodeDep.getVariable(0).propagate(agent.getType("java.lang.String")); nameDep.getResult().connect(hashCodeDep.getVariable(0)); hashCodeDep.getThrown().connect(methodDep.getThrown()); hashCodeDep.use(); agent.linkMethod(new MethodReference(Object.class, "hashCode", int.class)); agent.linkMethod(new MethodReference(Object.class, "equals", Object.class, boolean.class)); return nameDep; }
private void handleNewInstance(DependencyAgent agent, MethodDependency method) { CallLocation location = new CallLocation(method.getReference()); DependencyNode classValueNode = agent.linkMethod(getConstructors) .addLocation(location) .getVariable(0).getClassValueNode(); classValueNode.addConsumer(reflectedType -> { if (reflectedType.getName().startsWith("[")) { return; } Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName()); ClassReader cls = agent.getClassSource().get(reflectedType.getName()); for (MethodDescriptor methodDescriptor : accessibleMethods) { MethodReader calledMethod = cls.getMethod(methodDescriptor); MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location); calledMethodDep.use(); for (int i = 0; i < calledMethod.parameterCount(); ++i) { propagateSet(agent, methodDescriptor.parameterType(i), method.getVariable(1).getArrayItem(), calledMethodDep.getVariable(i + 1), location); } calledMethodDep.getVariable(0).propagate(reflectedType); linkClassIfNecessary(agent, calledMethod, location); } }); classValueNode.connect(method.getResult()); }
private void handleFieldSet(DependencyAgent agent, MethodDependency method) { CallLocation location = new CallLocation(method.getReference()); DependencyNode classValueNode = agent.linkMethod(getFields) .addLocation(location) .getVariable(0).getClassValueNode(); classValueNode.addConsumer(reflectedType -> { if (reflectedType.getName().startsWith("[")) { return; } Set<String> accessibleFields = getAccessibleFields(agent, reflectedType.getName()); ClassReader cls = agent.getClassSource().get(reflectedType.getName()); for (String fieldName : accessibleFields) { FieldReader field = cls.getField(fieldName); FieldDependency fieldDep = agent.linkField(field.getReference()).addLocation(location); propagateSet(agent, field.getType(), method.getVariable(2), fieldDep.getValue(), location); linkClassIfNecessary(agent, field, location); } }); }
private void handleFieldGet(DependencyAgent agent, MethodDependency method) { CallLocation location = new CallLocation(method.getReference()); DependencyNode classValueNode = agent.linkMethod(getFields) .addLocation(location) .getVariable(0).getClassValueNode(); classValueNode.addConsumer(reflectedType -> { if (reflectedType.getName().startsWith("[")) { return; } Set<String> accessibleFields = getAccessibleFields(agent, reflectedType.getName()); ClassReader cls = agent.getClassSource().get(reflectedType.getName()); for (String fieldName : accessibleFields) { FieldReader field = cls.getField(fieldName); FieldDependency fieldDep = agent.linkField(field.getReference()) .addLocation(location); propagateGet(agent, field.getType(), fieldDep.getValue(), method.getResult(), location); linkClassIfNecessary(agent, field, location); } }); }
private void handleInvoke(DependencyAgent agent, MethodDependency method) { CallLocation location = new CallLocation(method.getReference()); DependencyNode classValueNode = agent.linkMethod(getMethods) .addLocation(location) .getVariable(0).getClassValueNode(); classValueNode.addConsumer(reflectedType -> { if (reflectedType.getName().startsWith("[")) { return; } Set<MethodDescriptor> accessibleMethods = getAccessibleMethods(agent, reflectedType.getName()); ClassReader cls = agent.getClassSource().get(reflectedType.getName()); for (MethodDescriptor methodDescriptor : accessibleMethods) { MethodReader calledMethod = cls.getMethod(methodDescriptor); MethodDependency calledMethodDep = agent.linkMethod(calledMethod.getReference()).addLocation(location); calledMethodDep.use(); for (int i = 0; i < calledMethod.parameterCount(); ++i) { propagateSet(agent, methodDescriptor.parameterType(i), method.getVariable(2).getArrayItem(), calledMethodDep.getVariable(i + 1), location); } propagateSet(agent, ValueType.object(reflectedType.getName()), method.getVariable(1), calledMethodDep.getVariable(0), location); propagateGet(agent, calledMethod.getResultType(), calledMethodDep.getResult(), method.getResult(), location); linkClassIfNecessary(agent, calledMethod, location); } }); }