Files

Call Graph Tests

A small testing framework for our call graph resolution. It relies on manual annotation of calls and callables, and will only include output if something is wrong. For example, if we are not able to resolve that the foo() call will call the foo function, that should give an alert.

# name:foo
def foo():
    pass
# calls:foo
foo()

This is greatly inspired by CallGraphs/AnnotatedTest from JavaScript.

IMPORTANT: Names used in annotations are not scoped, so must be unique globally. (this is a bit annoying, but makes things simple). If multiple identical annotations are used, an error message will be output.

Important files:

  • CallGraphTest.qll: main code to find annotated calls/callables and setting everything up.
  • PointsTo.ql: results when using points-to for call graph resolution.
  • TypeTracker.ql: results when using TypeTracking for call graph resolution.
  • Relative.ql: differences between using points-to and TypeTracking.
  • code/ contains the actual Python code we test against (included by test.py).

All queries will also execute some debug_* predicates. These highlight any obvious problems with the annotation setup, and so there should never be any results committed. To show that this works as expected, see the CallGraph-xfail which uses symlinked versions of the files in this directory (can't include as subdir, so has to be a sibling).

options file

If the value for --max-import-depth is set so that import random will extract random.py from the standard library, BUT NO transitive imports are extracted, then points-to analysis will fail to handle the following snippet.

import random
if random.random() < 0.5:
    func = foo
else:
    func = bar
func()