Closed
Description
The modular product program encoding assumes that any object allocation reached in both executions produces an object reference that is low. However real allocators don’t behave that way: allocation decisions depend on what previous allocations have occurred. The following example demonstrates this potential unsoundness in current Nagini:
from nagini_contracts.contracts import *
class MyObject(object):
pass
def sif_print_str(x: str) -> None:
Requires(Low(x))
Requires(LowVal(x))
pass
def test(x: int) -> None:
if x > 0:
m1 = MyObject()
m2 = MyObject()
sif_print_str(str(m2))
Nagini verifies this correctly (using command line nagini –sif true
). Yet on my machine, the first allocation always yields an object whose least significant 8 bits of the address exposed in its str
is “c0” while for the second allocation these bits are reliably “60” instead.
$ python
Python 3.8.13 (default, Apr 19 2022, 00:53:22)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class MyObject(object):
... pass
...
>>> m1 = MyObject()
>>> m2 = MyObject()
>>> str(m1)
'<__main__.MyObject object at 0x7f214e94d4c0>'
>>> str(m2)
'<__main__.MyObject object at 0x7f214e8a5d60>'
Metadata
Metadata
Assignees
Labels
No labels