wala / ML

Eclipse Public License 2.0
23 stars 17 forks source link

Can't find external classes #146

Closed khatchad closed 4 months ago

khatchad commented 4 months ago

Consider the following example:

# client.py
from classes4 import C

def f():
    C()

f()

# classes4.py
class C:
    pass

The resulting call graph on 5ad4daec4bde8087b714892bd956f482a7e17d2d:

Node: synthetic < PythonLoader, Lcom/ibm/wala/FakeRootClass, fakeRootMethod()V > Context: Everywhere
 - invokestatic < PythonLoader, Lcom/ibm/wala/FakeRootClass, fakeWorldClinit()V >@0
     -> Node: synthetic < PythonLoader, Lcom/ibm/wala/FakeRootClass, fakeWorldClinit()V > Context: Everywhere
 - invokevirtual < PythonLoader, Lscript client.py, do()LRoot; >@2
     -> Node: <Code body of function Lscript client.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@2 ]
 - invokevirtual < PythonLoader, Lscript classes4.py, do()LRoot; >@4
     -> Node: <Code body of function Lscript classes4.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@4 ]

Node: synthetic < PythonLoader, Lcom/ibm/wala/FakeRootClass, fakeWorldClinit()V > Context: Everywhere

Node: <Code body of function Lscript client.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@2 ]
 - JSCall@98
     -> Node: <Code body of function Lscript client.py/f> Context: CallStringContext: [ script client.py.do()LRoot;@98 ]

Node: <Code body of function Lscript client.py/f> Context: CallStringContext: [ script client.py.do()LRoot;@98 ]

Node: <Code body of function Lscript classes4.py> Context: CallStringContext: [ com.ibm.wala.FakeRootClass.fakeRootMethod()V@4 ]

Note that the second to last line shows that f() has no callees. It should call the constructor for C. I've also tried this with an explicit default ctor as well as explicitly defined methods.

khatchad commented 4 months ago

I've also tried external functions. Those also don't work.

khatchad commented 4 months ago

I've also tried external functions. Those also don't work.

But they do work in our client that imports Ariadne as a dependency, which makes me think that this could be a testing issue, at least for the external functions case. However, external ctors and other method calls don't work in both the Ariadne tests as well as our client application.

khatchad commented 4 months ago

Well, here's an interesting find. The tests in com.ibm.wala.cast.python.test are run twice. I assume once with Jython and once with Jythion3. In one run it works and in the other one, it doesn't. I am thinking then that the reason our fix works in our client is because we are forcing Jython3 to load.

khatchad commented 4 months ago

This also makes me believe that the ML tests are using Jython and not Jython3.

khatchad commented 4 months ago

I'm unsure how this is happening, i.e., how the tests are being run twice.

khatchad commented 4 months ago

Well, in the test, I can repro this and cannot repro this depending on the test iteration. Why there are multiple I don't know, but it seems that the first one tests stuff in target/, while the second tests stuff in the repo. Other than that, I cannot see the differences between the two runs to understand why the call graph differs.

khatchad commented 3 months ago

It's possible that the modules are created differently depending on the location of the test files. In one test iteration, the test files come from target/, in an other, they come from the repo. Here's the module creation logic for test cases:

https://github.com/wala/ML/blob/d9a3d6be01441474acdf67c81ca62b8323598375/com.ibm.wala.cast.python.test/source/com/ibm/wala/cast/python/test/TestPythonCallGraphShape.java#L73-L85