Skip to content

Commit 8e158b5

Browse files
committed
Add --nondet-static-except flag to goto-instrument
--nondet-static-except behaves as --nondet-static but allows to filter the symbols which are effected by --nondet-static. Every symbol that is effected by nondet-static and is not in the comma separated symbol list passed to --nondet-static-except will be nondet when using this flag. All symbols in the list keep their concret initalization.
1 parent bf5f7f7 commit 8e158b5

File tree

13 files changed

+203
-13
lines changed

13 files changed

+203
-13
lines changed

regression/goto-instrument/chain.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,24 @@ cbmc=$3
88
is_windows=$4
99

1010
name=${*:$#}
11-
name=${name%.c}
11+
12+
if [[ x$name == x ]]; then
13+
name=${name%.c}
14+
fi
1215

1316
args=${*:5:$#-5}
1417

15-
if [[ "${is_windows}" == "true" ]]; then
18+
if [[ "${is_windows}" == "true" && x$name != x ]]; then
19+
$goto_cc "main.gb" ${name}
20+
name="main"
21+
mv "${name}.exe" "${name}.gb"
22+
elif [[ "${is_windows}" == "true" ]]; then
1623
$goto_cc "${name}.c"
1724
mv "${name}.exe" "${name}.gb"
25+
elif [[ x$name != x ]]; then
26+
$goto_cc -o "main.gb" ${name}
27+
echo "name: ${name}"
28+
name="main"
1829
else
1930
$goto_cc -o "${name}.gb" "${name}.c"
2031
fi
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "package1/file.c"
2+
#include "package2/file.c"
3+
4+
void main()
5+
{
6+
method1();
7+
method2();
8+
return 0;
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
static int myVal = 3;
2+
static int myVal2 = 4;
3+
4+
void method2()
5+
{
6+
__CPROVER_assert(myVal == 3, "method2 myVal");
7+
__CPROVER_assert(myVal2 == 4, "method2 myVal2");
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
static int myVal = 3;
2+
static int myVal2 = 4;
3+
4+
void method1()
5+
{
6+
__CPROVER_assert(myVal == 3, "method1 myVal");
7+
__CPROVER_assert(myVal2 == 4, "method1 myVal2");
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
package1/file.c package2/file.c main.c
3+
--nondet-static-exclude package1/file.c:myVal --nondet-static-exclude package2/file.c:myVal2
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
method2 myVal: SUCCESS
8+
method2 myVal2: FAILURE
9+
method1 myVal: FAILURE
10+
method1 myVal2: SUCCESS
11+
--
12+
--
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#define NULL 0
2+
3+
struct aStruct
4+
{
5+
int a;
6+
int b;
7+
};
8+
9+
struct aStruct *test1 = NULL;
10+
11+
struct aStruct test2 = {.a = 5, .b = 2};
12+
struct aStruct test3 = {.a = 1, .b = 4};
13+
struct aStruct *test4 = &test3;
14+
struct aStruct *test5 = &test2;
15+
16+
static int value = 7;
17+
18+
#include "main_1.h"
19+
#include <assert.h>
20+
21+
int main(int argc, char **argv)
22+
{
23+
assert(test1 == NULL);
24+
assert(test2.a == 5);
25+
assert(test3.a == 1);
26+
assert(test3.b == 4);
27+
assert(test4->a == 1);
28+
assert(test4->b == 4);
29+
30+
assert(test5->a == 5);
31+
assert(test5->b == 2);
32+
33+
assert(value == 7);
34+
35+
setup();
36+
37+
return 0;
38+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
static int value = 5;
2+
3+
#include <assert.h>
4+
5+
void setup()
6+
{
7+
assert(value == 5);
8+
return 0;
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void setup();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CORE
2+
main_1.c main.c
3+
--nondet-static --nondet-static-exclude test1 --nondet-static-exclude test3 --nondet-static-exclude test4 --nondet-static-exclude main_1.c:value
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
assertion test1 == (NULL|0): SUCCESS
8+
assertion test2.a == 5: FAILURE
9+
assertion test3.a == 1: SUCCESS
10+
assertion test3.b == 4: SUCCESS
11+
assertion test4->a == 1: SUCCESS
12+
assertion test4->b == 4: SUCCESS
13+
assertion test5->a == 5: FAILURE
14+
assertion test5->b == 2: FAILURE
15+
assertion value == 7: FAILURE
16+
assertion value == 5: SUCCESS
17+
--
18+
--

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,10 +1205,19 @@ void goto_instrument_parse_optionst::instrument_goto_program()
12051205

12061206
// ignore default/user-specified initialization of variables with static
12071207
// lifetime
1208-
if(cmdline.isset("nondet-static"))
1208+
if(cmdline.isset("nondet-static-exclude"))
12091209
{
1210-
log.status() << "Adding nondeterministic initialization of static/global "
1211-
"variables"
1210+
log.status() << "Adding nondeterministic initialization "
1211+
"of static/global variables except for "
1212+
"the specified ones."
1213+
<< messaget::eom;
1214+
1215+
nondet_static(goto_model, cmdline.get_values("nondet-static-exclude"));
1216+
}
1217+
else if(cmdline.isset("nondet-static"))
1218+
{
1219+
log.status() << "Adding nondeterministic initialization "
1220+
"of static/global variables"
12121221
<< messaget::eom;
12131222
nondet_static(goto_model);
12141223
}
@@ -1607,6 +1616,8 @@ void goto_instrument_parse_optionst::help()
16071616
" --isr <function> instruments an interrupt service routine\n"
16081617
" --mmio instruments memory-mapped I/O\n"
16091618
" --nondet-static add nondeterministic initialization of variables with static lifetime\n" // NOLINT(*)
1619+
" --nondet-static-exclude e same as nondet-static except for the variable e\n" //NOLINT(*)
1620+
" (use multiple times if required)\n"
16101621
" --check-invariant function instruments invariant checking function\n"
16111622
" --remove-pointers converts pointer arithmetic to base+offset expressions\n" // NOLINT(*)
16121623
" --splice-call caller,callee prepends a call to callee in the body of caller\n" // NOLINT(*)

src/goto-instrument/goto_instrument_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Author: Daniel Kroening, [email protected]
6262
"(no-po-rendering)(render-cluster-file)(render-cluster-function)" \
6363
"(nondet-volatile)(isr):" \
6464
"(stack-depth):(nondet-static)" \
65+
"(nondet-static-exclude):" \
6566
"(function-enter):(function-exit):(branch):" \
6667
OPT_SHOW_GOTO_FUNCTIONS \
6768
OPT_SHOW_PROPERTIES \

src/goto-instrument/nondet_static.cpp

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ bool is_nondet_initializable_static(
4646

4747
const symbolt &symbol = ns.lookup(id);
4848

49+
// is the symbol explicitly marked as not to be nondet initialized?
50+
if(symbol.value.get_bool(ID_C_no_nondet_initialization))
51+
{
52+
return false;
53+
}
54+
4955
// is the type explicitly marked as not to be nondet initialized?
5056
if(symbol.type.get_bool(ID_C_no_nondet_initialization))
5157
return false;
@@ -110,24 +116,22 @@ void nondet_static(
110116
nondet_static(ns, goto_functions, fsym.get_identifier());
111117
}
112118
}
119+
120+
// update counters etc.
121+
goto_functions.update();
113122
}
114123

115124
/// Nondeterministically initializes global scope variables in
116125
/// CPROVER_initialize function.
117126
/// \param ns: Namespace for resolving type information.
118127
/// \param [out] goto_functions: Existing goto-functions to be updated.
119-
void nondet_static(
120-
const namespacet &ns,
121-
goto_functionst &goto_functions)
128+
void nondet_static(const namespacet &ns, goto_functionst &goto_functions)
122129
{
123130
nondet_static(ns, goto_functions, INITIALIZE_FUNCTION);
124-
125-
// update counters etc.
126-
goto_functions.update();
127131
}
128132

129-
/// Main entry point of the module. Nondeterministically initializes global
130-
/// scope variables, except for constants (such as string literals, final
133+
/// First main entry point of the module. Nondeterministically initializes
134+
/// global scope variables, except for constants (such as string literals, final
131135
/// fields) and internal variables (such as CPROVER and symex variables,
132136
/// language specific internal variables).
133137
/// \param [out] goto_model: Existing goto-model to be updated.
@@ -136,3 +140,59 @@ void nondet_static(goto_modelt &goto_model)
136140
const namespacet ns(goto_model.symbol_table);
137141
nondet_static(ns, goto_model.goto_functions);
138142
}
143+
144+
/// Second main entry point of the module. Nondeterministically initializes
145+
/// global scope variables, except for constants (such as string literals, final
146+
/// fields), internal variables (such as CPROVER and symex variables,
147+
/// language specific internal variables) and variables passed to except_value.
148+
/// \param [out] goto_model: Existing goto-model to be updated.
149+
/// \param except_values: list of symbol names that should not be updated.
150+
void nondet_static(
151+
goto_modelt &goto_model,
152+
const optionst::value_listt &except_values)
153+
{
154+
const namespacet ns(goto_model.symbol_table);
155+
std::set<std::string> to_exclude;
156+
157+
for(auto const &except : except_values)
158+
{
159+
const bool file_prefix_found = except.find(":") != std::string::npos;
160+
161+
if(file_prefix_found)
162+
{
163+
to_exclude.insert(except);
164+
if(has_prefix(except, "./"))
165+
{
166+
to_exclude.insert(except.substr(2, except.length() - 2));
167+
}
168+
else
169+
{
170+
to_exclude.insert("./" + except);
171+
}
172+
}
173+
else
174+
{
175+
irep_idt symbol_name(except);
176+
symbolt lookup_results = ns.lookup(symbol_name);
177+
to_exclude.insert(
178+
id2string(lookup_results.location.get_file()) + ":" + except);
179+
}
180+
}
181+
182+
symbol_tablet &symbol_table = goto_model.symbol_table;
183+
184+
for(symbol_tablet::iteratort symbol_it = symbol_table.begin();
185+
symbol_it != symbol_table.end();
186+
symbol_it++)
187+
{
188+
symbolt &symbol = symbol_it.get_writeable_symbol();
189+
std::string qualified_name = id2string(symbol.location.get_file()) + ":" +
190+
id2string(symbol.display_name());
191+
if(to_exclude.find(qualified_name) != to_exclude.end())
192+
{
193+
symbol.value.set(ID_C_no_nondet_initialization, 1);
194+
}
195+
}
196+
197+
nondet_static(ns, goto_model.goto_functions, INITIALIZE_FUNCTION);
198+
}

src/goto-instrument/nondet_static.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Date: November 2011
2020
#ifndef CPROVER_GOTO_INSTRUMENT_NONDET_STATIC_H
2121
#define CPROVER_GOTO_INSTRUMENT_NONDET_STATIC_H
2222

23+
#include <util/options.h>
24+
2325
class goto_modelt;
2426
class namespacet;
2527
class goto_functionst;
@@ -35,4 +37,6 @@ void nondet_static(
3537

3638
void nondet_static(goto_modelt &);
3739

40+
void nondet_static(goto_modelt &, const optionst::value_listt &);
41+
3842
#endif // CPROVER_GOTO_INSTRUMENT_NONDET_STATIC_H

0 commit comments

Comments
 (0)