Skip to content

Commit 84a5186

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 84a5186

File tree

7 files changed

+163
-3
lines changed

7 files changed

+163
-3
lines changed
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+
}
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).
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+
}
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).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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 == 5)
6+
{
7+
}
8+
9+
void foo(int *x) __CPROVER_assigns(*x) __CPROVER_requires(*x > 0)
10+
__CPROVER_ensures(*x == 3)
11+
{
12+
int *y;
13+
bar(x, y);
14+
assert (*y == 5);
15+
}
16+
17+
int main()
18+
{
19+
int n;
20+
foo(&n);
21+
22+
assert(n == 3);
23+
return 0;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KNOWNBUG
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 an uninitialized pointer passed as a parameter
11+
to a function that may assign to it. The uninitialized pointer is passed to
12+
function bar which has been replaced by it's function contracts, while the
13+
calling function foo is being checked (by enforcing it's function contracts).
14+
15+
Known Bug:
16+
Currently, there is no way to check if an assigned pointer is invalid (which
17+
may be the case for uninitialized pointers). We do handle NULL pointers as a
18+
special case, however, we do not yet have a way to handle invalid pointer.

src/goto-instrument/code_contracts.cpp

+44-3
Original file line numberDiff line numberDiff line change
@@ -1542,11 +1542,38 @@ 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. Currently only supports pointers
1554+
// See GitHub issue #6087 for further details
1555+
if(target->target_type == assigns_clause_targett::target_type::Scalar)
1556+
{
1557+
exprt condition = equal_exprt(
1558+
target->get_direct_pointer(),
1559+
null_pointer_exprt(
1560+
to_pointer_type(target->get_direct_pointer().type())));
1561+
1562+
havoc_statements.add(goto_programt::make_goto(z, condition, location));
1563+
}
1564+
1565+
// create havoc_statements
15451566
for(goto_programt::instructiont instruction :
15461567
target->havoc_code(location).instructions)
15471568
{
15481569
havoc_statements.add(std::move(instruction));
15491570
}
1571+
1572+
if(target->target_type == assigns_clause_targett::target_type::Scalar)
1573+
{
1574+
// add the z label instruction
1575+
havoc_statements.destructive_append(tmp_z);
1576+
}
15501577
}
15511578
return havoc_statements;
15521579
}
@@ -1595,9 +1622,23 @@ exprt assigns_clauset::compatible_expression(
15951622
{
15961623
if(first_iter)
15971624
{
1598-
current_target_compatible =
1599-
target->compatible_expression(*called_target);
1600-
first_iter = false;
1625+
// TODO: generalize this. Currently only supports pointers
1626+
// See GitHub issue #6087 for further details
1627+
if(target->target_type == assigns_clause_targett::target_type::Scalar)
1628+
{
1629+
current_target_compatible = or_exprt(
1630+
equal_exprt(
1631+
called_target->get_direct_pointer(),
1632+
null_pointer_exprt(
1633+
to_pointer_type(called_target->get_direct_pointer().type()))),
1634+
target->compatible_expression(*called_target));
1635+
}
1636+
else
1637+
{
1638+
current_target_compatible =
1639+
target->compatible_expression(*called_target);
1640+
first_iter = false;
1641+
}
16011642
}
16021643
else
16031644
{

0 commit comments

Comments
 (0)