From 130b92c444c206572682f2e007cca64670e3b03e Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Sat, 27 Jan 2024 19:35:47 -0800 Subject: [PATCH] Fix issue 1356 (#1367) Change how we access the `TypeAbstraction` in a `Context` to avoid a `ClassCastException`. Fixes #1356 --- .../GetMethodContextInterpreter.java | 4 +- .../core/tests/callGraph/CallGraphTest.java | 43 +++++++++++++++++++ .../src/testSubjects/java/simple/Example.java | 19 ++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 core/src/testSubjects/java/simple/Example.java diff --git a/core/src/main/java/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java b/core/src/main/java/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java index c2cbaef532..cf718ec1d8 100644 --- a/core/src/main/java/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java +++ b/core/src/main/java/com/ibm/wala/analysis/reflection/GetMethodContextInterpreter.java @@ -137,8 +137,8 @@ public Iterator iterateNewSites(CGNode node) { throw new IllegalArgumentException("node is null"); } assert understands(node); - GetMethodContext context = (GetMethodContext) node.getContext(); - TypeReference tr = context.getType().getTypeReference(); + TypeReference tr = + ((TypeAbstraction) node.getContext().get(ContextKey.RECEIVER)).getTypeReference(); if (tr != null) { return new NonNullSingletonIterator<>(NewSiteReference.make(0, tr)); } diff --git a/core/src/test/java/com/ibm/wala/core/tests/callGraph/CallGraphTest.java b/core/src/test/java/com/ibm/wala/core/tests/callGraph/CallGraphTest.java index a20853c202..968e0b5462 100644 --- a/core/src/test/java/com/ibm/wala/core/tests/callGraph/CallGraphTest.java +++ b/core/src/test/java/com/ibm/wala/core/tests/callGraph/CallGraphTest.java @@ -18,6 +18,7 @@ import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.Language; +import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.core.tests.demandpa.AbstractPtrTest; import com.ibm.wala.core.tests.util.TestConstants; import com.ibm.wala.core.tests.util.WalaTestCase; @@ -30,6 +31,7 @@ import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraphBuilder; +import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException; import com.ibm.wala.ipa.callgraph.CallGraphStats; import com.ibm.wala.ipa.callgraph.Entrypoint; import com.ibm.wala.ipa.callgraph.IAnalysisCacheView; @@ -37,6 +39,7 @@ import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint; import com.ibm.wala.ipa.callgraph.impl.Util; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder; @@ -48,12 +51,14 @@ import com.ibm.wala.ipa.cha.ClassHierarchyFactory; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.ISSABasicBlock; +import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.Descriptor; import com.ibm.wala.types.MethodReference; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.Iterator2Iterable; import com.ibm.wala.util.collections.IteratorUtil; +import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.graph.Graph; import com.ibm.wala.util.graph.GraphIntegrity; @@ -361,6 +366,44 @@ public void testZeroOneContainerStaticMethods() "did not find call to valueOf"); } + /** Testing that there is no crash during iteration of points to sets */ + @Test + public void testIteratingPointsToSetsForCreationSites() + throws CallGraphBuilderCancelException, IOException, ClassHierarchyException { + AnalysisScope scope = + CallGraphTestUtil.makeJ2SEAnalysisScope( + TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); + ClassHierarchy cha = ClassHierarchyFactory.make(scope); + Iterable entrypoints = Util.makeMainEntrypoints(cha, "Lsimple/Example"); + AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); + IAnalysisCacheView cache = new AnalysisCacheImpl(); + CallGraphBuilder builder = + Util.makeZeroCFABuilder(Language.JAVA, options, cache, cha); + CallGraph cg = builder.makeCallGraph(options, null); + PointerAnalysis pointerAnalysis = builder.getPointerAnalysis(); + for (PointerKey pk : pointerAnalysis.getPointerKeys()) { + if (pk instanceof LocalPointerKey) { + LocalPointerKey lpk = (LocalPointerKey) pk; + String className = lpk.getNode().getMethod().getDeclaringClass().getName().toString(); + String methodName = lpk.getNode().getMethod().getName().toString(); + ClassLoaderReference clr = + lpk.getNode().getMethod().getDeclaringClass().getClassLoader().getReference(); + if (clr.equals(ClassLoaderReference.Application) + && className.equals("Lsimple/Example") + && methodName.equals("foo")) { + if (lpk.isParameter()) { + for (InstanceKey ik : pointerAnalysis.getPointsToSet(lpk)) { + Iterator> iterator = ik.getCreationSites(cg); + while (iterator.hasNext()) { + iterator.next(); // making sure there is no crash here + } + } + } + } + } + } + } + /** make main entrypoints, even in the primordial loader. */ public static Iterable makePrimordialMainEntrypoints(ClassHierarchy cha) { final Atom mainMethod = Atom.findOrCreateAsciiAtom("main"); diff --git a/core/src/testSubjects/java/simple/Example.java b/core/src/testSubjects/java/simple/Example.java new file mode 100644 index 0000000000..1f5212fef5 --- /dev/null +++ b/core/src/testSubjects/java/simple/Example.java @@ -0,0 +1,19 @@ +package simple; + +public class Example { + private static int i = 0; + + public static void main(String[] args) { + Object obj1 = new Object(); + Object obj2 = "1"; + Object obj3 = 1; + if (i == 0) { + obj1 = obj3; + } else if (i == 1) { + obj2 = obj3; + } + foo(obj1, obj2); + } + + private static void foo(Object o1, Object o2) {} +}