Skip to content

Commit bbe628b

Browse files
author
Remi Delmas
committed
Function contracts: check for the presence of loops before assigns clause instrumentation.
1 parent b847942 commit bbe628b

File tree

14 files changed

+241
-44
lines changed

14 files changed

+241
-44
lines changed

regression/contracts/assigns_validity_pointer_01/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ SUCCESS
88
// bar
99
ASSERT \*foo::x > 0
1010
IF ¬\(\*foo::x = 3\) THEN GOTO \d
11-
IF ¬\(.*0.* = NULL\) THEN GOTO \d
1211
ASSIGN .*::tmp_if_expr := \(\*\(.*0.*\) = 5 \? true : false\)
1312
ASSIGN .*::tmp_if_expr\$\d := .*::tmp_if_expr \? true : false
1413
ASSUME .*::tmp_if_expr\$\d

regression/contracts/function_check_02/main.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ int initialize(int *arr)
1515
)
1616
// clang-format on
1717
{
18-
for(int i = 0; i < 10; i++)
19-
{
20-
arr[i] = i;
21-
}
18+
arr[0] = 0;
19+
arr[1] = 1;
20+
arr[2] = 2;
21+
arr[3] = 3;
22+
arr[4] = 4;
23+
arr[5] = 5;
24+
arr[6] = 6;
25+
arr[7] = 7;
26+
arr[8] = 8;
27+
arr[9] = 9;
2228

2329
return 0;
2430
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
int foo(int *arr)
2+
// clang-format off
3+
__CPROVER_assigns(__CPROVER_POINTER_OBJECT(arr))
4+
// clang-format off
5+
{
6+
for(int i = 0; i < 10; i++)
7+
arr[i] = i;
8+
9+
return 0;
10+
}
11+
12+
int main()
13+
{
14+
int arr[10];
15+
foo(arr);
16+
}
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+
^--- begin invariant violation report ---$
5+
^Invariant check failed$
6+
^Condition: is_loop_free\(.*\)
7+
^Reason: Loops remain in function 'foo', assigns clause checking instrumentation cannot be applied\.$
8+
^EXIT=(127|134)$
9+
^SIGNAL=0$
10+
--
11+
--
12+
This test checks that loops that remain in the program when attempting to
13+
instrument assigns clauses are detected and trigger an INVARIANT.

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ int f1(int *arr)
77
})
88
// clang-format on
99
{
10-
for(int i = 0; i < 10; i++)
11-
{
12-
arr[i] = i;
13-
}
10+
arr[0] = 0;
11+
arr[1] = 1;
12+
arr[2] = 2;
13+
arr[3] = 3;
14+
arr[4] = 4;
15+
arr[5] = 5;
16+
arr[6] = 6;
17+
arr[7] = 7;
18+
arr[8] = 8;
19+
arr[9] = 9;
1420

1521
return 0;
1622
}
@@ -24,10 +30,16 @@ int f2(int *arr)
2430
})
2531
// clang-format on
2632
{
27-
for(int i = 0; i < 10; i++)
28-
{
29-
arr[i] = 0;
30-
}
33+
arr[0] = 0;
34+
arr[1] = 1;
35+
arr[2] = 2;
36+
arr[3] = 3;
37+
arr[4] = 4;
38+
arr[5] = 5;
39+
arr[6] = 6;
40+
arr[7] = 7;
41+
arr[8] = 8;
42+
arr[9] = 9;
3143

3244
return 0;
3345
}

regression/contracts/quantifiers-exists-requires-enforce/main.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <stdbool.h>
22
#include <stdlib.h>
33

4-
#define MAX_LEN 64
4+
#define MAX_LEN 10
55

66
// clang-format off
77
bool f1(int *arr, int len)
@@ -18,11 +18,27 @@ bool f1(int *arr, int len)
1818
// clang-format on
1919
{
2020
bool found_four = false;
21-
for(int i = 0; i <= MAX_LEN; i++)
22-
{
23-
if(i < len)
24-
found_four |= (arr[i] == 4);
25-
}
21+
if(0 < len)
22+
found_four |= (arr[0] == 4);
23+
if(1 < len)
24+
found_four |= (arr[1] == 4);
25+
if(2 < len)
26+
found_four |= (arr[2] == 4);
27+
if(3 < len)
28+
found_four |= (arr[3] == 4);
29+
if(4 < len)
30+
found_four |= (arr[4] == 4);
31+
if(5 < len)
32+
found_four |= (arr[5] == 4);
33+
if(6 < len)
34+
found_four |= (arr[6] == 4);
35+
if(7 < len)
36+
found_four |= (arr[7] == 4);
37+
if(8 < len)
38+
found_four |= (arr[8] == 4);
39+
40+
if(9 < len)
41+
found_four |= (arr[9] == 4);
2642

2743
// clang-format off
2844
return (len > 0 ==> found_four);

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <stdlib.h>
22

3-
#define MAX_LEN 16
3+
#define MAX_LEN 10
44

55
// clang-format off
66
int f1(int *arr, int len)
@@ -12,11 +12,27 @@ int f1(int *arr, int len)
1212
})
1313
// clang-format on
1414
{
15-
for(int i = 0; i < MAX_LEN; i++)
16-
{
17-
if(i < len)
18-
arr[i] = 0;
19-
}
15+
if(0 < len)
16+
arr[0] = 0;
17+
if(1 < len)
18+
arr[1] = 0;
19+
if(2 < len)
20+
arr[2] = 0;
21+
if(3 < len)
22+
arr[3] = 0;
23+
if(4 < len)
24+
arr[4] = 0;
25+
if(5 < len)
26+
arr[5] = 0;
27+
if(6 < len)
28+
arr[6] = 0;
29+
if(7 < len)
30+
arr[7] = 0;
31+
if(8 < len)
32+
arr[8] = 0;
33+
if(9 < len)
34+
arr[9] = 0;
35+
2036
return 0;
2137
}
2238

regression/contracts/quantifiers-forall-ensures-enforce/test.desc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[postcondition.\d+\] file main.c line \d+ Check ensures clause: SUCCESS$
7-
^\[f1.\d+\] line \d+ Check that arr\[\(.*\)i\] is assignable: SUCCESS$
7+
^\[f1.\d+\] line \d+ Check that arr\[\(.*\)\d\] is assignable: SUCCESS$
88
^VERIFICATION SUCCESSFUL$
99
--
1010
^warning: ignoring
11+
^\[f1.\d+\] line \d+ Check that arr\[\(.*\)\d\] is assignable: FAILURE$
1112
--
1213
The purpose of this test is to ensure that we can safely use __CPROVER_forall
1314
within positive contexts (enforced ENSURES clauses).

regression/contracts/quantifiers-forall-requires-enforce/main.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,16 @@ bool f1(int *arr)
1212
// clang-format on
1313
{
1414
bool is_identity = true;
15-
for(int i = 0; i < 10; ++i)
16-
is_identity &= (arr[i] == i);
15+
is_identity &= (arr[0] == 0);
16+
is_identity &= (arr[1] == 1);
17+
is_identity &= (arr[2] == 2);
18+
is_identity &= (arr[3] == 3);
19+
is_identity &= (arr[4] == 4);
20+
is_identity &= (arr[5] == 5);
21+
is_identity &= (arr[6] == 6);
22+
is_identity &= (arr[7] == 7);
23+
is_identity &= (arr[8] == 8);
24+
is_identity &= (arr[9] == 9);
1725
return is_identity;
1826
}
1927

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@ int f1(int *arr)
1111
})
1212
// clang-format on
1313
{
14-
for(int i = 0; i < 10; i++)
15-
{
16-
arr[i] = i;
17-
}
14+
arr[0] = 0;
15+
arr[1] = 1;
16+
arr[2] = 2;
17+
arr[3] = 3;
18+
arr[4] = 4;
19+
arr[5] = 5;
20+
arr[6] = 6;
21+
arr[7] = 7;
22+
arr[8] = 8;
23+
arr[9] = 9;
1824

1925
return 0;
2026
}

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ __CPROVER_assigns(__CPROVER_POINTER_OBJECT(arr))
1010
)
1111
// clang-format on
1212
{
13-
for(int i = 0; i < 10; i++)
14-
{
15-
arr[i] = i;
16-
}
13+
arr[0] = 0;
14+
arr[1] = 1;
15+
arr[2] = 2;
16+
arr[3] = 3;
17+
arr[4] = 4;
18+
arr[5] = 5;
19+
arr[6] = 6;
20+
arr[7] = 7;
21+
arr[8] = 8;
22+
arr[9] = 9;
1723

1824
return 0;
1925
}

src/goto-instrument/contracts/contracts.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,9 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
11281128
return true;
11291129
}
11301130

1131-
if(check_for_looped_mallocs(function_obj->second.body))
1131+
auto &function_body = function_obj->second.body;
1132+
1133+
if(check_for_looped_mallocs(function_body))
11321134
{
11331135
return true;
11341136
}
@@ -1142,21 +1144,24 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
11421144
function,
11431145
symbol_table);
11441146

1145-
// detect and add static local variables
1147+
// Detect and add static local variables
11461148
assigns.add_static_locals_to_write_set(goto_functions, function);
11471149

11481150
// Add formal parameters to write set
11491151
for(const auto &param : to_code_type(target.type).parameters())
11501152
assigns.add_to_write_set(ns.lookup(param.get_identifier()).symbol_expr());
11511153

1152-
auto instruction_it = function_obj->second.body.instructions.begin();
1154+
auto instruction_it = function_body.instructions.begin();
11531155
for(const auto &car : assigns.get_write_set())
11541156
{
11551157
auto snapshot_instructions = car.generate_snapshot_instructions();
11561158
insert_before_swap_and_advance(
1157-
function_obj->second.body, instruction_it, snapshot_instructions);
1159+
function_body, instruction_it, snapshot_instructions);
11581160
};
11591161

1162+
// Restore internal coherence in the programs
1163+
goto_functions.update();
1164+
11601165
// Full inlining of the function body
11611166
// Inlining is performed so that function calls to a same function
11621167
// occurring under different write sets get instrumented specifically
@@ -1168,15 +1173,23 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
11681173
decorated.get_recursive_function_warnings_count() == 0,
11691174
"Recursive functions found during inlining");
11701175

1171-
// restore internal invariants
1176+
// Clean up possible fake loops that are due to `IF 0!=0 GOTO i` instructions
1177+
simplify_gotos(function_body, ns);
1178+
1179+
// Restore internal coherence in the programs
11721180
goto_functions.update();
11731181

1182+
INVARIANT(
1183+
is_loop_free(function_body, ns, log),
1184+
"Loops remain in function '" + id2string(function) +
1185+
"', assigns clause checking instrumentation cannot be applied.");
1186+
11741187
// Insert write set inclusion checks.
11751188
check_frame_conditions(
1176-
function_obj->first,
1177-
function_obj->second.body,
1189+
function,
1190+
function_body,
11781191
instruction_it,
1179-
function_obj->second.body.instructions.end(),
1192+
function_body.instructions.end(),
11801193
assigns,
11811194
// skip checks on function parameter assignments
11821195
true);

0 commit comments

Comments
 (0)