Skip to content

Commit c325804

Browse files
committed
Adds support for null pointers passed as function call parameter.
This adds support for the cases where a null pointer is passed as a parameter to a function that may assign to it. We add checks in goto program to handle such instances as special cases of assigns clause handling.
1 parent 7795e1e commit c325804

File tree

5 files changed

+106
-2
lines changed

5 files changed

+106
-2
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
4+
void bar(int *x, int *y) __CPROVER_assigns(*x, *y) __CPROVER_requires(*x > 0)
5+
__CPROVER_ensures(*x == 3 && (y == NULL || *y == 5))
6+
{
7+
*x = 3;
8+
if(y != NULL)
9+
*y = 5;
10+
}
11+
12+
void foo(int *x) __CPROVER_assigns(*x) __CPROVER_requires(*x > 0)
13+
__CPROVER_ensures(*x == 3)
14+
{
15+
bar(x, NULL);
16+
}
17+
18+
int main()
19+
{
20+
int n;
21+
foo(&n);
22+
23+
assert(n == 3);
24+
return 0;
25+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo --replace-call-with-contract bar
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Verification:
10+
This test checks support for a null pointer passed as a parameter to a
11+
function that may assign to it. The null pointer is passed to function
12+
bar which has been replaced by it's function contracts, while the calling
13+
function foo is being checked (by enforcing it's function contracts).
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
4+
void bar(int *x, int *y) __CPROVER_assigns(*x, *y) __CPROVER_requires(*x > 0)
5+
__CPROVER_ensures(*x == 3 && (y == NULL || *y == 5))
6+
{
7+
*x = 3;
8+
if(y != NULL)
9+
*y = 5;
10+
}
11+
12+
void foo(int *x) __CPROVER_assigns(*x) __CPROVER_requires(*x > 0)
13+
__CPROVER_ensures(*x == 3)
14+
{
15+
bar(x, NULL);
16+
*x = 3;
17+
}
18+
19+
int main()
20+
{
21+
int n;
22+
foo(&n);
23+
24+
assert(n == 3);
25+
return 0;
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Verification:
10+
This test checks support for a null pointer passed as a parameter to a
11+
function that may assign to it. The null pointer is passed to function
12+
bar, while the calling function foo is being checked (by enforcing
13+
it's function contracts).

src/goto-instrument/code_contracts.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,11 +1542,31 @@ goto_programt assigns_clauset::havoc_code(
15421542
goto_programt havoc_statements;
15431543
for(assigns_clause_targett *target : targets)
15441544
{
1545+
// if(target != NULL) goto x;
1546+
// havoc_statements
1547+
// z: skip
1548+
1549+
// create the z label
1550+
goto_programt tmp_z;
1551+
goto_programt::targett z = tmp_z.add(goto_programt::make_skip(location));
1552+
1553+
// TODO: generalize this
1554+
// currently only supports pointers
1555+
exprt condition = equal_exprt(
1556+
target->get_direct_pointer(),
1557+
null_pointer_exprt(to_pointer_type(target->get_direct_pointer().type())));
1558+
1559+
havoc_statements.add(goto_programt::make_goto(z, condition, location));
1560+
1561+
// create havoc_statements
15451562
for(goto_programt::instructiont instruction :
15461563
target->havoc_code(location).instructions)
15471564
{
15481565
havoc_statements.add(std::move(instruction));
15491566
}
1567+
1568+
// add the z label instruction
1569+
havoc_statements.destructive_append(tmp_z);
15501570
}
15511571
return havoc_statements;
15521572
}
@@ -1595,8 +1615,15 @@ exprt assigns_clauset::compatible_expression(
15951615
{
15961616
if(first_iter)
15971617
{
1598-
current_target_compatible =
1599-
target->compatible_expression(*called_target);
1618+
// TODO: generalize this
1619+
// currently only supports pointers
1620+
current_target_compatible = or_exprt(
1621+
equal_exprt(
1622+
called_target->get_direct_pointer(),
1623+
null_pointer_exprt(
1624+
to_pointer_type(called_target->get_direct_pointer().type()))),
1625+
target->compatible_expression(*called_target));
1626+
16001627
first_iter = false;
16011628
}
16021629
else

0 commit comments

Comments
 (0)