mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
39 lines
1.9 KiB
Markdown
39 lines
1.9 KiB
Markdown
# 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.
|
|
|
|
```py
|
|
# name:foo
|
|
def foo():
|
|
pass
|
|
# calls:foo
|
|
foo()
|
|
```
|
|
|
|
This is greatly inspired by [`CallGraphs/AnnotatedTest`](https://github.com/github/codeql/blob/696d19cb1440b6f6a75c6a2c1319e18860ceb436/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql) 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](../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.
|
|
|
|
```py
|
|
import random
|
|
if random.random() < 0.5:
|
|
func = foo
|
|
else:
|
|
func = bar
|
|
func()
|
|
```
|