Skip to content

Commit 49f605d

Browse files
committed
Support for empty assigns clause
CBMC currently doesn't enforce assigns clauses if there isn't one. However, whenever enforcing a function contract, the absence of an assigns clause should be interpreted as an empty write set (i.e., no inputs will be modified by this function). CBMC now properly checks for empty assigns clause behavior. Signed-off-by: Felipe R. Monteiro <[email protected]>
1 parent c41ce2b commit 49f605d

File tree

10 files changed

+64
-37
lines changed

10 files changed

+64
-37
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
CORE
22
main.c
33
--enforce-all-contracts
4-
^EXIT=10$
4+
^EXIT=0$
55
^SIGNAL=0$
6-
^VERIFICATION FAILED$
6+
^VERIFICATION SUCCESSFUL$
77
--
88
--
99
This test checks that verification fails when a function with an assigns clause calls a function without an assigns clause.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
int foo(int *x) __CPROVER_assigns(*x)
2+
__CPROVER_ensures(__CPROVER_return_value == *x + 5)
3+
{
4+
int z = 5;
5+
int y = bar(&z);
6+
return *x + 5;
7+
}
8+
9+
int bar(int *a) __CPROVER_ensures(__CPROVER_return_value >= 5)
10+
{
11+
*a = *a + 2;
12+
return *a;
13+
}
14+
15+
int main()
16+
{
17+
int n;
18+
n = foo(&n);
19+
return 0;
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
--

regression/contracts/function_check_02/main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
// in ensures to fail.
66

77
int initialize(int *arr)
8+
/* clang-format off */
9+
__CPROVER_assigns(*arr)
810
__CPROVER_ensures(
9-
__CPROVER_forall {int i; (0 <= i && i < 10) ==> arr[i] == i}
11+
__CPROVER_forall {
12+
int i;
13+
(0 <= i && i < 10) ==> arr[i] == i
14+
}
1015
)
16+
/* clang-format on */
1117
{
1218
for(int i = 0; i < 10; i++)
1319
{

regression/contracts/quantifiers-exists-ensures-01/main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// clang-format off
2-
int f1(int *arr) __CPROVER_ensures(__CPROVER_exists {
3-
int i;
4-
(0 <= i && i < 10) ==> arr[i] == i
5-
})
2+
int f1(int *arr)
3+
__CPROVER_assigns(*arr)
4+
__CPROVER_ensures(__CPROVER_exists {
5+
int i;
6+
(0 <= i && i < 10) ==> arr[i] == i
7+
})
68
// clang-format on
79
{
810
for(int i = 0; i < 10; i++)

regression/contracts/quantifiers-forall-ensures-01/main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// clang-format off
2-
int f1(int *arr) __CPROVER_ensures(__CPROVER_forall {
3-
int i;
4-
(0 <= i && i < 10) ==> arr[i] == 0
5-
})
2+
int f1(int *arr)
3+
__CPROVER_assigns(*arr)
4+
__CPROVER_ensures(__CPROVER_forall {
5+
int i;
6+
(0 <= i && i < 10) ==> arr[i] == 0
7+
})
68
// clang-format on
79
{
810
for(int i = 0; i < 10; i++)

regression/contracts/quantifiers-nested-01/main.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
// clang-format off
2-
int f1(int *arr) __CPROVER_ensures(__CPROVER_forall {
3-
int i;
4-
__CPROVER_forall
5-
{
6-
int j;
7-
(0 <= i && i < 10 && i <= j && j < 10) ==> arr[i] <= arr[j]
8-
}
9-
})
2+
int f1(int *arr)
3+
__CPROVER_assigns(*arr)
4+
__CPROVER_ensures(__CPROVER_forall {
5+
int i;
6+
__CPROVER_forall
7+
{
8+
int j;
9+
(0 <= i && i < 10 && i <= j && j < 10) ==> arr[i] <= arr[j]
10+
}
11+
})
1012
// clang-format on
1113
{
1214
for(int i = 0; i < 10; i++)

regression/contracts/quantifiers-nested-03/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
int f1(int *arr)
1+
int f1(int *arr) __CPROVER_assigns(*arr)
22
__CPROVER_ensures(__CPROVER_return_value == 0 && __CPROVER_exists {
33
int i;
44
(0 <= i && i < 10) && arr[i] == i

src/goto-instrument/code_contracts.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -513,20 +513,8 @@ void code_contractst::instrument_call_statement(
513513

514514
exprt called_assigns =
515515
to_code_with_contract_type(called_symbol.type).assigns();
516-
if(called_assigns.is_nil()) // Called function has no assigns clause
517-
{
518-
// Create a false assertion, so the analysis
519-
// will fail if this function is called.
520-
goto_programt failing_assertion;
521-
failing_assertion.add(goto_programt::make_assertion(
522-
false_exprt(), instruction_iterator->source_location));
523-
program.insert_before_swap(instruction_iterator, failing_assertion);
524-
++instruction_iterator;
525-
526-
return;
527-
}
528-
else // Called function has assigns clause
529-
{
516+
if(!called_assigns.is_nil()) // Called function has assigns clause
517+
{
530518
replace_symbolt replace;
531519
// Replace formal parameters
532520
code_function_callt::argumentst::const_iterator a_it =
@@ -540,6 +528,7 @@ void code_contractst::instrument_call_statement(
540528
if(!p_it->get_identifier().empty())
541529
{
542530
symbol_exprt p(p_it->get_identifier(), p_it->type());
531+
std::cout << "p.get_identifier: " << p.get_identifier() << std::endl;
543532
replace.insert(p, *a_it);
544533
}
545534
}
@@ -634,9 +623,6 @@ bool code_contractst::add_pointer_checks(const std::string &function_name)
634623
const auto &type = to_code_with_contract_type(function_symbol.type);
635624

636625
exprt assigns_expr = type.assigns();
637-
// Return if there are no reference checks to perform.
638-
if(assigns_expr.is_nil())
639-
return false;
640626

641627
assigns_clauset assigns(assigns_expr, *this, function_id, log);
642628

src/goto-instrument/code_contracts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Date: February 2016
1414
#ifndef CPROVER_GOTO_INSTRUMENT_CODE_CONTRACTS_H
1515
#define CPROVER_GOTO_INSTRUMENT_CODE_CONTRACTS_H
1616

17+
#include <iostream>
1718
#include <set>
1819
#include <string>
1920
#include <unordered_set>

0 commit comments

Comments
 (0)