Basic Usage
To analyze programs, Mopsa provides five binaries:
mopsa-c
for C programs,mopsa-python
performs a value analysis of Python programs, whilemopsa-python-types
performs a type-only analysis,mopsa-cpython
for Python programs relying on custom C libraries,mopsa-universal
works on a toy imperative language defined within Mopsa.
C analysis
Consider the following program hello.c
:
1#define LEN 100
2int main(int argc, char* argv[]) {
3 int a[LEN];
4 for(int i = 0; i <= LEN; i++)
5 a[i] = 0;
6 return 0;
7}
By running mopsa-c hello.c
we get the following report:
Analysis terminated successfully
Analysis time: 0.028s
⚠ Check #2:
resources/code/hello.c: In function 'main':
resources/code/hello.c:5.4-8: warning: Invalid memory access
5: a[i] = 0;
^^^^
accessing 4 bytes at offsets [4,400] of variable 'a' of size 400 bytes
Callstack:
from resources/code/hello.c:2.4-8: main
Checks summary: 2 total, ✔ 1 safe, ⚠ 1 warning
Invalid memory access: 1 total, ⚠ 1 warning
Integer overflow: 1 total, ✔ 1 safe
As expected, Mopsa raises an alarm at line 5, corresponding to the invalid access to array a
when index i
reaches LEN
.
Mopsa indicates the total number of checks of each kind it performed.
Here, in addition to the failed memory access check, there is an integer overflow check that passed.
It corresponds to the incrementation i++
.
By default, Mopsa reports the detailed list of unsuccessful checks but only the number of successful checks.
Using the -show-safe-checks
option, Mopsa will also list the successful checks.
More details on checks are available in the reports section.
Changing the <=
at line 4 into <
(hello-fixed.c
) and running again the analysis, Mopsa reports no alarm.
This proves that the program is free from invalid memory accesses and integer overflows:
Analysis terminated successfully
✔ No alarm
Analysis time: 0.028s
Checks summary: 2 total, ✔ 2 safe
Invalid memory access: 1 total, ✔ 1 safe
Integer overflow: 1 total, ✔ 1 safe
Analyzing a program containing multiple files is performed similarly, by providing the list of all source files to mopsa-c
.
The C front end in Mopsa understands the -I
option to specify preprocessor include directories, and arbitrary C preprocessor and compiler options can be passed with the -ccopt
option (for instance -ccopt -DSYMBOL=VALUE
).
By default, Mopsa starts the analysis with the main
C function, and fails if it is not defined.
This can be overridden with the -c-entry
option
You can jump to the C benchmarks section for more interesting analysis examples in C.
Python analysis
Python programs are also analyzed by simply calling mopsa-python
on the list of source files.
Consider the following example hello.py
:
1def absolute(x):
2 if (x < 0): return -x
3 else: x
4
5a = absolute(absolute(10))
The missing return
statement at line 3 makes the function absolute
return None
, which triggers a TypeError
in the second call as indicated by the output of Mopsa:
$ mopsa-python hello.py
Analysis terminated successfully
✗ Check #1:hello.py: In function 'absolute':
hello.py:2.8-13: error: Uncaught Python exception
2: if (x < 0): return -x
^^^^^
Uncaught Python exception: TypeError: '__lt__' not supported between instances of 'cb{NoneType}' and 'cb{int}'
Callstack:
from hello.py:5.4-26: absolute
Analysis summary:
Time: 0.015s
Checks: 1 total, ✗ 1 error
Uncaught Python exception: 1 total, ✗ 1 error
You can jump to the Python benchmarks section for more interesting analysis examples in Python.
Multilanguage analysis (Python+C)
Analyzing multilanguage programs is a bit more involved, as we need to rely on the mopsa-build tool.
We illustrate this approach on the running example of our [SAS21] paper.
You will need the files counter.c
, setup.py
and count.py
.
The first thing to do is build the counter.c
library.
We call the build process with custom wrappers, so that Mopsa stores the relationship between the .so
file and the sources, using mopsa-build python3 setup.py build --force --inplace
(this first step may require having the packages python3-dev python3-setuptools
being installed on your computer).
Once this is done, we can run the actual analysis of count.py
shown below, using mopsa-cpython count.py
.
Note that mopsa-cpython
relies the header files of Python 3.8, which are assumed to be in /usr/include/python3.8
(the path can be changed in bin/mopsa-cpython
).
1from counter import Counter
2import random
3
4c = Counter()
5p = random.randrange(128)
6print(f"p = {p}")
7c.incr(2**p-1)
8c.incr()
9r = c.counter
10print(f"r = {r}")
The result is shown below. Mopsa detects both the OverflowError
that may be raised and a silent integer overflow that may also happen. The last error is a false alarm that should be easily avoided once a partitioning domain is used in Mopsa.
Analysis terminated successfully (with assumptions)
Analysis time: 0.960s
⚠ Check #4:
./counter.c: In function 'CounterIncr':
./counter.c:19.2-18: warning: Integer overflow
19: self->count += i;
^^^^^^^^^^^^^^^^
'(@Inst{c class counter.Counter}:kAbt598DpMv9uK!6On%fD[16]:s32 + i)' has value [0,2147483648] that is larger than the range of 'signed int' = [-2147483648,2147483647]
'(self->count + i)' has value [0,2147483648] that is larger than the range of 'signed int' = [-2147483648,2147483647]
Callstack:
from count.py:8.0-8: CounterIncr
✗ Check #506:
count.py: In function 'PyErr_SetString':
count.py:7.0-14: error: OverflowError exception
7: c.incr(2**p-1)
^^^^^^^^^^^^^^
Uncaught Python exception: OverflowError: signed integer is greater than maximum
Uncaught Python exception: OverflowError: Python int too large to convert to C long
Callstack:
from /home/raphael/these/mopsa/share/mopsa/stubs/cpython/python_stubs.c:923.16-34: PyErr_SetString
from ./counter.c:17.6-38::convert_single[0]: PyParseTuple_int_helper
from count.py:7.0-14: CounterIncr
+1 other callstack
⚠ Check #507:
count.py:7.0-14: warning: SystemError exception
7: c.incr(2**p-1)
^^^^^^^^^^^^^^
Uncaught Python exception: SystemError: CounterIncr returned a result with an error set
Checks summary: 574 total, ✔ 571 safe, ✗ 1 error, ⚠ 2 warnings
Stub condition: 4 total, ✔ 4 safe
Invalid memory access: 194 total, ✔ 194 safe
Integer overflow: 186 total, ✔ 185 safe, ⚠ 1 warning
Invalid shift: 72 total, ✔ 72 safe
AttributeError exception: 25 total, ✔ 25 safe
IndexError exception: 3 total, ✔ 3 safe
ModuleNotFoundError exception: 2 total, ✔ 2 safe
NameError exception: 26 total, ✔ 26 safe
OverflowError exception: 1 total, ✗ 1 error
SystemError exception: 5 total, ✔ 4 safe, ⚠ 1 warning
TypeError exception: 30 total, ✔ 30 safe
UnboundLocalError exception: 26 total, ✔ 26 safe
1 assumption:
./counter.c:67.26-59: in C/Python analysis, unsupported fields: tp_as_async, tp_hash, tp_clear ...
Multilanguage benchmarks refers to the multilanguage benchmarks we used in our experimental evaluation. They can also be run using the SAS 2021 artefact [SAS21-artefact].
Raphaël Monat, Abdelraouf Ouadjaout, Antoine Miné: Static Type Analysis by Abstract Interpretation of Python Programs. SAS 2021: 323-345
Raphaël Monat, Abdelraouf Ouadjaout, Antoine Miné: Static Type Analysis by Abstract Interpretation of Python Programs – Artefact. Zenodo