diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CAstAnalysisScope.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CAstAnalysisScope.java index 39380de0b..99106dcec 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CAstAnalysisScope.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CAstAnalysisScope.java @@ -94,7 +94,6 @@ public class CAstAnalysisScope extends AnalysisScope { */ @Override public ClassLoaderReference getSyntheticLoader() { - Assertions.UNREACHABLE(); return null; } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstClass.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstClass.java index cea3a713f..5f5111219 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstClass.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstClass.java @@ -176,7 +176,7 @@ abstract public class AstClass implements IClass, ClassConstants { return getField(name); } @Override - public Collection getDeclaredMethods() { + public Collection getDeclaredMethods() { return declaredMethods.values(); } @@ -235,7 +235,7 @@ abstract public class AstClass implements IClass, ClassConstants { } @Override - public Collection getAllMethods() { + public Collection getAllMethods() { Collection result = HashSetFactory.make(); for (IMethod iMethod : getDeclaredMethods()) { result.add(iMethod); diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstDynamicField.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstDynamicField.java index 1cb3b497e..ae9bc6c30 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstDynamicField.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstDynamicField.java @@ -88,4 +88,45 @@ public class AstDynamicField implements IField { public Collection getAnnotations() { return Collections.emptySet(); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((cls == null) ? 0 : cls.hashCode()); + result = prime * result + ((descriptor == null) ? 0 : descriptor.hashCode()); + result = prime * result + (isStatic ? 1231 : 1237); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AstDynamicField other = (AstDynamicField) obj; + if (cls == null) { + if (other.cls != null) + return false; + } else if (!cls.equals(other.cls)) + return false; + if (descriptor == null) { + if (other.descriptor != null) + return false; + } else if (!descriptor.equals(other.descriptor)) + return false; + if (isStatic != other.isStatic) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/SingleClassLoaderFactory.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/SingleClassLoaderFactory.java index 052eea4d6..338ea9ce4 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/SingleClassLoaderFactory.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/SingleClassLoaderFactory.java @@ -14,6 +14,7 @@ import com.ibm.wala.classLoader.ClassLoaderFactory; import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.ipa.summaries.BypassSyntheticClassLoader; import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.util.debug.Assertions; @@ -28,8 +29,13 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory { */ private IClassLoader THE_LOADER = null; + /** + * Support synthetic classes + */ + private IClassLoader syntheticLoader; + @Override - public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) { + public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) { if (THE_LOADER == null) { THE_LOADER = makeTheLoader(cha); try { @@ -39,9 +45,14 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory { } } - assert classLoaderReference.equals(getTheReference()); - - return THE_LOADER; + if (classLoaderReference.equals(scope.getSyntheticLoader())) { + syntheticLoader = new BypassSyntheticClassLoader(scope.getSyntheticLoader(), THE_LOADER, scope.getExclusions(), cha); + return syntheticLoader; + + } else { + assert classLoaderReference.equals(getTheReference()); + return THE_LOADER; + } } public IClassLoader getTheLoader() { diff --git a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/DefaultMethodsTest.java b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/DefaultMethodsTest.java index d8714afdb..b45224008 100644 --- a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/DefaultMethodsTest.java +++ b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/DefaultMethodsTest.java @@ -86,7 +86,7 @@ public class DefaultMethodsTest extends WalaTestCase { TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1"); IClass test1Class = cha.lookupClass(test1Type); - Collection allMethods = test1Class.getAllMethods(); + Collection allMethods = test1Class.getAllMethods(); IMethod defaultMethod = test1Class.getMethod(t1m.getSelector()); Assert.assertTrue("Expecting default methods to show up in IClass.allMethods()", allMethods.contains(defaultMethod)); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java index d0a484335..6abe51ebf 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java @@ -168,7 +168,7 @@ public class GetMethodContextInterpreter implements SSAContextInterpreter { */ private static Collection getAllNormalPublicMethods(IClass cls,Atom name) { Collection result = HashSetFactory.make(); - Collection allMethods = null; + Collection allMethods = null; allMethods = cls.getAllMethods(); for (IMethod m : allMethods) { if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaLangClassContextInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaLangClassContextInterpreter.java index a5aed8289..840653a43 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaLangClassContextInterpreter.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaLangClassContextInterpreter.java @@ -239,7 +239,7 @@ public class JavaLangClassContextInterpreter implements SSAContextInterpreter { */ private static Collection getAllNormalPublicMethods(IClass cls) { Collection result = HashSetFactory.make(); - Collection allMethods = null; + Collection allMethods = null; allMethods = cls.getAllMethods(); for (IMethod m : allMethods) { if (!m.isInit() && !m.isClinit() && m.isPublic()) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java index 43df0f1ba..fcb3f18ea 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java @@ -343,7 +343,7 @@ public class ArrayClass implements IClass, Constants { * @see com.ibm.wala.classLoader.IClass#getAllMethods() */ @Override - public Collection getAllMethods() { + public Collection getAllMethods() { return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getAllMethods(); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java index 1bca04c10..15ff5ce4e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java @@ -405,7 +405,7 @@ public abstract class BytecodeClass implements IClass { } IClass s = getSuperclass(); while (s != null) { - Iterator superDeclaredMethods = s.getDeclaredMethods().iterator(); + Iterator superDeclaredMethods = s.getDeclaredMethods().iterator(); while (superDeclaredMethods.hasNext()) { result.add(superDeclaredMethods.next()); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java index 705aed968..a1730088e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java @@ -135,7 +135,7 @@ public interface IClass extends IClassHierarchyDweller { /** * @return an Iterator of the IMethods declared by this class. */ - Collection getDeclaredMethods(); + Collection getDeclaredMethods(); /** * Compute the instance fields declared by this class or any of its superclasses. @@ -155,7 +155,7 @@ public interface IClass extends IClassHierarchyDweller { /** * Compute the methods declared by this class or any of its superclasses. */ - Collection getAllMethods(); + Collection getAllMethods(); /** * Compute the instance fields declared by this class. diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/SyntheticClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/SyntheticClass.java index 76a323990..cdf8741f0 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/SyntheticClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/SyntheticClass.java @@ -16,7 +16,6 @@ import java.util.Collection; import java.util.Collections; import com.ibm.wala.ipa.cha.IClassHierarchy; -import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.TypeName; import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.annotations.Annotation; @@ -77,7 +76,7 @@ public abstract class SyntheticClass implements IClass { */ @Override public IClassLoader getClassLoader() { - return cha.getLoader(ClassLoaderReference.Primordial); + return cha.getLoader(T.getClassLoader()); } /* diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassMethodTargetSelector.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassMethodTargetSelector.java index 8a391beab..ca8c5b4c5 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassMethodTargetSelector.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassMethodTargetSelector.java @@ -112,7 +112,14 @@ public class BypassMethodTargetSelector implements MethodTargetSelector { IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget, site.isStatic()); - + // try synthetic method that matches receiver type + if (dispatchType != null) { + ref = MethodReference.findOrCreate(dispatchType.getReference(), ref.getSelector()); + chaTarget = chaMethodTargetSelector.getCalleeTarget(caller, site, dispatchType); + target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget, + site.isStatic()); + } + if (DEBUG) { System.err.println("target is initially " + target); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClass.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClass.java index cf2a30c6b..1e2186d49 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClass.java @@ -137,7 +137,7 @@ public class BypassSyntheticClass extends SyntheticClass { * @see com.ibm.wala.classLoader.IClass#getDeclaredMethods() */ @Override - public Collection getDeclaredMethods() { + public Collection getDeclaredMethods() { return realType.getDeclaredMethods(); } @@ -236,7 +236,7 @@ public class BypassSyntheticClass extends SyntheticClass { * @see com.ibm.wala.classLoader.IClass#getAllMethods() */ @Override - public Collection getAllMethods() { + public Collection getAllMethods() { return realType.getAllMethods(); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClassLoader.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClassLoader.java index 77d7bc205..91a796e4d 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClassLoader.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClassLoader.java @@ -50,7 +50,7 @@ import com.ibm.wala.util.strings.Atom; * * Code that wants to introduce synthetic classes uses the registerClass method, * giving it an Atom which is the class name, and an IClass which is the class - * to load. Since the synthetic loader musat be a child of the others, it would + * to load. Since the synthetic loader must be a child of the others, it would * be very bad to use an existing name for a new synthetic class. * * Class lookup works just as for any other classloader. @@ -148,7 +148,7 @@ public class BypassSyntheticClassLoader implements IClassLoader { */ @Override public Language getLanguage() { - return Language.JAVA; + return parent.getLanguage(); } /* diff --git a/com.ibm.wala.core/src/com/ibm/wala/util/scope/JUnitEntryPoints.java b/com.ibm.wala.core/src/com/ibm/wala/util/scope/JUnitEntryPoints.java index 8185ba8e7..8e7431ba1 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/util/scope/JUnitEntryPoints.java +++ b/com.ibm.wala.core/src/com/ibm/wala/util/scope/JUnitEntryPoints.java @@ -54,8 +54,8 @@ public class JUnitEntryPoints { System.out.println("application class: " + klass); // return all the tests methods - Collection methods = klass.getAllMethods(); - Iterator methodsIt = methods.iterator(); + Collection methods = klass.getAllMethods(); + Iterator methodsIt = methods.iterator(); while (methodsIt.hasNext()) { IMethod m = methodsIt.next(); diff --git a/com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/util/AndroidEntryPointLocator.java b/com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/util/AndroidEntryPointLocator.java index b1f8be05b..4d75c1642 100644 --- a/com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/util/AndroidEntryPointLocator.java +++ b/com.ibm.wala.dalvik/src/com/ibm/wala/dalvik/util/AndroidEntryPointLocator.java @@ -248,7 +248,7 @@ nextMethod: // Don't consider internal overrides continue; } - final Collection methods = candid.getDeclaredMethods(); + final Collection methods = candid.getDeclaredMethods(); for (final IMethod method : methods) { @@ -329,7 +329,7 @@ nextMethod: { // Overridden methods if (isAPIComponent(appClass)) continue; if (isExcluded(appClass)) continue; - final Collection methods = appClass.getDeclaredMethods(); + final Collection methods = appClass.getDeclaredMethods(); for (final IMethod method : methods) { if ((method.isInit() || method.isClinit()) && (! this.flags.contains(LocatorFlags.WITH_CTOR))) { logger.debug("Skipping constructor of {}", method); @@ -359,7 +359,7 @@ nextMethod: } if (isExcluded(iFace)) continue; logger.debug("Searching Interface {}", iFace); - final Collection ifMethods = iFace.getDeclaredMethods(); + final Collection ifMethods = iFace.getDeclaredMethods(); for (final IMethod ifMethod : ifMethods) { final IMethod method = appClass.getMethod(ifMethod.getSelector()); if (method != null && method.getDeclaringClass().getClassLoader().getReference().equals(ClassLoaderReference.Application)) { diff --git a/com.ibm.wala.scandroid/source/org/scandroid/spec/MethodNamePattern.java b/com.ibm.wala.scandroid/source/org/scandroid/spec/MethodNamePattern.java index 9f6e45506..ffdb1c2f6 100644 --- a/com.ibm.wala.scandroid/source/org/scandroid/spec/MethodNamePattern.java +++ b/com.ibm.wala.scandroid/source/org/scandroid/spec/MethodNamePattern.java @@ -85,7 +85,7 @@ public class MethodNamePattern { Collection matching = new LinkedList<>(); Atom atom = Atom.findOrCreateUnicodeAtom(memberName); Descriptor desc = descriptor == null ? null : Descriptor.findOrCreateUTF8(descriptor); - Collection allMethods = c.getAllMethods(); + Collection allMethods = c.getAllMethods(); for(IMethod m: allMethods) { if(m.getName().equals(atom) && (desc == null || m.getDescriptor().equals(desc))) { matching.add(m);