From 220d4f04ff2413df4b5dce933dd9afdc3219611d Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Wed, 14 Feb 2024 15:09:29 -0500 Subject: [PATCH 1/8] For classes, add a field to the script object just like functions. Then, (external) classes can be found by the PA when they are imported. Otherwise, they cannot be found. --- .../cast/python/ir/PythonCAstToIRTranslator.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java b/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java index 037db7c52..ecd4f6498 100644 --- a/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java +++ b/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java @@ -613,6 +613,18 @@ protected void leaveTypeEntity( .PutInstruction(code.cfg().getCurrentInstruction(), v, val, fr)); }); } + + code.cfg() + .unknownInstructions( + () -> { + FieldReference fnField = + FieldReference.findOrCreate( + PythonTypes.Root, Atom.findOrCreateUnicodeAtom(n.getName()), PythonTypes.Root); + code.cfg() + .addInstruction( + Python.instructionFactory() + .PutInstruction(code.cfg().getCurrentInstruction(), 1, v, fnField)); + }); } @Override From 087256c6c27c8dd541f21e31f176744c88b9bef3 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Wed, 14 Feb 2024 15:48:57 -0500 Subject: [PATCH 2/8] Format. --- .../com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java b/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java index ecd4f6498..9eb559993 100644 --- a/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java +++ b/com.ibm.wala.cast.python/source/com/ibm/wala/cast/python/ir/PythonCAstToIRTranslator.java @@ -619,7 +619,9 @@ protected void leaveTypeEntity( () -> { FieldReference fnField = FieldReference.findOrCreate( - PythonTypes.Root, Atom.findOrCreateUnicodeAtom(n.getName()), PythonTypes.Root); + PythonTypes.Root, + Atom.findOrCreateUnicodeAtom(n.getName()), + PythonTypes.Root); code.cfg() .addInstruction( Python.instructionFactory() From 27619a434c36d2ca4ca3b388259e8a428e0e3631 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Wed, 14 Feb 2024 15:55:40 -0500 Subject: [PATCH 3/8] Add test. --- com.ibm.wala.cast.python.test/data/class.py | 6 +++++ com.ibm.wala.cast.python.test/data/client.py | 15 ++++++++++++ .../wala/cast/python/test/TestClasses.java | 23 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 com.ibm.wala.cast.python.test/data/class.py create mode 100644 com.ibm.wala.cast.python.test/data/client.py diff --git a/com.ibm.wala.cast.python.test/data/class.py b/com.ibm.wala.cast.python.test/data/class.py new file mode 100644 index 000000000..6267fc000 --- /dev/null +++ b/com.ibm.wala.cast.python.test/data/class.py @@ -0,0 +1,6 @@ +class C: + pass + + +def g(): + pass diff --git a/com.ibm.wala.cast.python.test/data/client.py b/com.ibm.wala.cast.python.test/data/client.py new file mode 100644 index 000000000..db0ab0eaa --- /dev/null +++ b/com.ibm.wala.cast.python.test/data/client.py @@ -0,0 +1,15 @@ +from B import g +from B import C + + +class D: + pass + + +def f(): + g() + D() + C() + + +f() diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index d417b3b14..99390a422 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -1,17 +1,25 @@ package com.ibm.wala.cast.python.test; +import static org.junit.Assert.assertEquals; + import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil; import com.ibm.wala.cast.python.client.PythonAnalysisEngine; +import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder; import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.util.CancelException; import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; +import java.util.logging.Logger; import org.junit.Test; public class TestClasses extends TestPythonCallGraphShape { + private static final Logger LOGGER = Logger.getLogger(TestClasses.class.getName()); + protected static final Object[][] assertionsClasses1 = new Object[][] { new Object[] {ROOT, new String[] {"script classes1.py"}}, @@ -119,4 +127,19 @@ public void testClasses3() (SSAContextInterpreter) builder.getContextInterpreter(), builder.getPointerAnalysis(), CG); verifyGraphAssertions(CG, assertionsClasses3); } + + /** Can we find a class (and initialize it) from another file? */ + @Test + public void testExternalClass() + throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { + CallGraph callGraph = this.process("client.py", "class.py"); + Collection nodes = this.getNodes(callGraph, "script client.py/f"); + assertEquals(1, nodes.size()); + CGNode f = nodes.iterator().next(); + + for (Iterator succNodes = callGraph.getSuccNodes(f); succNodes.hasNext(); ) { + CGNode next = succNodes.next(); + LOGGER.info(() -> "Next node: " + next + "."); + } + } } From 89eb2c99cbf7a8d4bbcc2cc3e7cc0a262678f544 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Thu, 15 Feb 2024 12:29:39 -0500 Subject: [PATCH 4/8] Change test. --- com.ibm.wala.cast.python.test/data/class.py | 6 --- .../data/classes4.py | 2 + com.ibm.wala.cast.python.test/data/client.py | 9 +--- .../wala/cast/python/test/TestClasses.java | 48 +++++++++++++++++-- 4 files changed, 46 insertions(+), 19 deletions(-) delete mode 100644 com.ibm.wala.cast.python.test/data/class.py create mode 100644 com.ibm.wala.cast.python.test/data/classes4.py diff --git a/com.ibm.wala.cast.python.test/data/class.py b/com.ibm.wala.cast.python.test/data/class.py deleted file mode 100644 index 6267fc000..000000000 --- a/com.ibm.wala.cast.python.test/data/class.py +++ /dev/null @@ -1,6 +0,0 @@ -class C: - pass - - -def g(): - pass diff --git a/com.ibm.wala.cast.python.test/data/classes4.py b/com.ibm.wala.cast.python.test/data/classes4.py new file mode 100644 index 000000000..646b07aed --- /dev/null +++ b/com.ibm.wala.cast.python.test/data/classes4.py @@ -0,0 +1,2 @@ +class C: + pass diff --git a/com.ibm.wala.cast.python.test/data/client.py b/com.ibm.wala.cast.python.test/data/client.py index db0ab0eaa..ac142ae68 100644 --- a/com.ibm.wala.cast.python.test/data/client.py +++ b/com.ibm.wala.cast.python.test/data/client.py @@ -1,14 +1,7 @@ -from B import g -from B import C - - -class D: - pass +from classes4 import C def f(): - g() - D() C() diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index 99390a422..18e09f357 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -1,14 +1,19 @@ package com.ibm.wala.cast.python.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil; import com.ibm.wala.cast.python.client.PythonAnalysisEngine; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder; import com.ibm.wala.ipa.cha.ClassHierarchyException; +import com.ibm.wala.types.TypeName; import com.ibm.wala.util.CancelException; import java.io.IOException; import java.util.Collection; @@ -128,18 +133,51 @@ public void testClasses3() verifyGraphAssertions(CG, assertionsClasses3); } + protected static final Object[][] externalClassAssertions = + new Object[][] { + new Object[] {ROOT, new String[] {"script client.py"}}, + new Object[] { + "script client.py", + new String[] { + "script client.py/f", + } + }, + // TODO: Re-add once https://github.com/wala/ML/issues/146 is fixed. + /* + new Object[] { + "script client.py/f", + new String[] { + "script client.py/C", + } + } + */ + }; + /** Can we find a class (and initialize it) from another file? */ @Test public void testExternalClass() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { - CallGraph callGraph = this.process("client.py", "class.py"); + CallGraph callGraph = this.process("client.py", "classes4.py"); + + verifyGraphAssertions(callGraph, externalClassAssertions); + Collection nodes = this.getNodes(callGraph, "script client.py/f"); assertEquals(1, nodes.size()); CGNode f = nodes.iterator().next(); - for (Iterator succNodes = callGraph.getSuccNodes(f); succNodes.hasNext(); ) { - CGNode next = succNodes.next(); - LOGGER.info(() -> "Next node: " + next + "."); - } + Iterator succNodes = callGraph.getSuccNodes(f); + // TODO: Change to assertTrue() once https://github.com/wala/ML/issues/146 is fixed. + assertFalse(succNodes.hasNext()); + + CGNode node = + f; // Change to succNodes.next() once https://github.com/wala/ML/issues/146 is fixed. + assertFalse("Expecting only one callee.", succNodes.hasNext()); + + IMethod method = node.getMethod(); + IClass declaringClass = method.getDeclaringClass(); + TypeName name = declaringClass.getName(); + + // TODO: Change to assertEquals() once https://github.com/wala/ML/issues/146 is fixed. + assertNotEquals("Lscript classes4.py/C", name.toString()); } } From 55eb75cbfe605e3bc7eab54d342c723ee6bccbab Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Thu, 15 Feb 2024 15:41:22 -0500 Subject: [PATCH 5/8] Fix comment. --- .../source/com/ibm/wala/cast/python/test/TestClasses.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index 18e09f357..7305965e7 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -170,7 +170,7 @@ public void testExternalClass() assertFalse(succNodes.hasNext()); CGNode node = - f; // Change to succNodes.next() once https://github.com/wala/ML/issues/146 is fixed. + f; // TODO: Change to succNodes.next() once https://github.com/wala/ML/issues/146 is fixed. assertFalse("Expecting only one callee.", succNodes.hasNext()); IMethod method = node.getMethod(); From 7335b2982907f1bf6606297c5bb7cbb657c28d15 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Thu, 15 Feb 2024 16:10:56 -0500 Subject: [PATCH 6/8] Update TestClasses.java --- .../source/com/ibm/wala/cast/python/test/TestClasses.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index 7305965e7..36a233a30 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -167,7 +167,7 @@ public void testExternalClass() Iterator succNodes = callGraph.getSuccNodes(f); // TODO: Change to assertTrue() once https://github.com/wala/ML/issues/146 is fixed. - assertFalse(succNodes.hasNext()); + assertTrue(succNodes.hasNext()); CGNode node = f; // TODO: Change to succNodes.next() once https://github.com/wala/ML/issues/146 is fixed. From f2c856639f853bcf04fa319b1fb6117afb8da6b3 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Thu, 15 Feb 2024 16:11:49 -0500 Subject: [PATCH 7/8] Update TestClasses.java --- .../source/com/ibm/wala/cast/python/test/TestClasses.java | 1 + 1 file changed, 1 insertion(+) diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index 36a233a30..91808d736 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNotEquals; import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil; From 355223d261c4aa6e7d103c09a89b248623e4b384 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Thu, 15 Feb 2024 21:16:31 -0500 Subject: [PATCH 8/8] Change back to false. --- .../source/com/ibm/wala/cast/python/test/TestClasses.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java index 91808d736..1a8ac0380 100644 --- a/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java +++ b/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestClasses.java @@ -168,7 +168,7 @@ public void testExternalClass() Iterator succNodes = callGraph.getSuccNodes(f); // TODO: Change to assertTrue() once https://github.com/wala/ML/issues/146 is fixed. - assertTrue(succNodes.hasNext()); + assertFalse(succNodes.hasNext()); CGNode node = f; // TODO: Change to succNodes.next() once https://github.com/wala/ML/issues/146 is fixed.