Skip to content

Commit d494bf6

Browse files
author
Daniel Kroening
authored
Merge pull request #55 from tautschnig/model-argc-argv
goto-instrument --model-argc-argv: Explicitly initialise argc, argv
2 parents 2ff33ef + ed92d87 commit d494bf6

File tree

7 files changed

+235
-4
lines changed

7 files changed

+235
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
3+
int main(int argc, char* argv[])
4+
{
5+
if(argc>=2)
6+
assert(argv[1]!=0);
7+
8+
return 0;
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--model-argc-argv 2
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/goto-instrument/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ SRC = goto_instrument_parse_options.cpp rw_set.cpp \
2323
wmm/event_graph.cpp wmm/pair_collection.cpp \
2424
goto_instrument_main.cpp horn_encoding.cpp \
2525
thread_instrumentation.cpp skip_loops.cpp loop_utils.cpp \
26-
code_contracts.cpp cover.cpp
26+
code_contracts.cpp cover.cpp model_argc_argv.cpp
2727

2828
OBJ += ../ansi-c/ansi-c$(LIBEXT) \
2929
../cpp/cpp$(LIBEXT) \

src/goto-instrument/goto_instrument_parse_options.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Author: Daniel Kroening, [email protected]
8585
#include "skip_loops.h"
8686
#include "code_contracts.h"
8787
#include "unwind.h"
88+
#include "model_argc_argv.h"
8889

8990
/*******************************************************************\
9091
@@ -920,6 +921,24 @@ void goto_instrument_parse_optionst::instrument_goto_program()
920921
throw 0;
921922
}
922923

924+
namespacet ns(symbol_table);
925+
926+
// initialize argv with valid pointers
927+
if(cmdline.isset("model-argc-argv"))
928+
{
929+
unsigned max_argc=
930+
safe_string2unsigned(cmdline.get_value("model-argc-argv"));
931+
932+
status() << "Adding up to " << max_argc
933+
<< " command line arguments" << eom;
934+
if(model_argc_argv(
935+
symbol_table,
936+
goto_functions,
937+
max_argc,
938+
get_message_handler()))
939+
throw 0;
940+
}
941+
923942
// we add the library in some cases, as some analyses benefit
924943

925944
if(cmdline.isset("add-library") ||
@@ -933,8 +952,6 @@ void goto_instrument_parse_optionst::instrument_goto_program()
933952
link_to_library(symbol_table, goto_functions, ui_message_handler);
934953
}
935954

936-
namespacet ns(symbol_table);
937-
938955
// now do full inlining, if requested
939956
if(cmdline.isset("inline"))
940957
{
@@ -1501,6 +1518,7 @@ void goto_instrument_parse_optionst::help()
15011518
" --log <file> log in json format which code segments were inlined, use with --function-inline\n" // NOLINT(*)
15021519
" --remove-function-pointers replace function pointers by case statement over function calls\n" // NOLINT(*)
15031520
" --add-library add models of C library functions\n"
1521+
" --model-argc-argv <n> model up to <n> command line arguments\n"
15041522
"\n"
15051523
"Other options:\n"
15061524
" --use-system-headers with --dump-c/--dump-cpp: generate C source with includes\n" // NOLINT(*)

src/goto-instrument/goto_instrument_parse_options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Author: Daniel Kroening, [email protected]
6565
"(interpreter)(show-reaching-definitions)(count-eloc)(list-eloc)" \
6666
"(list-symbols)(list-undefined-functions)" \
6767
"(z3)(add-library)(show-dependence-graph)" \
68-
"(horn)(skip-loops):(apply-code-contracts)"
68+
"(horn)(skip-loops):(apply-code-contracts)(model-argc-argv):"
6969

7070
class goto_instrument_parse_optionst:
7171
public parse_options_baset,
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/*******************************************************************\
2+
3+
Module: Initialize command line arguments
4+
5+
Author: Michael Tautschnig
6+
7+
Date: April 2016
8+
9+
\*******************************************************************/
10+
11+
#include <sstream>
12+
13+
#include <util/cprover_prefix.h>
14+
#include <util/message.h>
15+
#include <util/namespace.h>
16+
#include <util/config.h>
17+
#include <util/replace_symbol.h>
18+
#include <util/symbol_table.h>
19+
#include <util/prefix.h>
20+
21+
#include <ansi-c/ansi_c_language.h>
22+
23+
#include <goto-programs/goto_convert.h>
24+
#include <goto-programs/goto_functions.h>
25+
#include <goto-programs/remove_skip.h>
26+
27+
#include "model_argc_argv.h"
28+
29+
/*******************************************************************\
30+
31+
Function: model_argc_argv
32+
33+
Inputs:
34+
35+
Outputs:
36+
37+
Purpose:
38+
39+
\*******************************************************************/
40+
41+
bool model_argc_argv(
42+
symbol_tablet &symbol_table,
43+
goto_functionst &goto_functions,
44+
unsigned max_argc,
45+
message_handlert &message_handler)
46+
{
47+
messaget message(message_handler);
48+
const namespacet ns(symbol_table);
49+
50+
const symbolt *init_symbol=0;
51+
if(ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
52+
{
53+
message.error() << "Linking not done, missing "
54+
<< CPROVER_PREFIX "initialize" << messaget::eom;
55+
return true;
56+
}
57+
58+
if(init_symbol->mode!=ID_C)
59+
{
60+
message.error() << "argc/argv modelling is C specific"
61+
<< messaget::eom;
62+
return true;
63+
}
64+
65+
goto_functionst::function_mapt::iterator init_entry=
66+
goto_functions.function_map.find(CPROVER_PREFIX "initialize");
67+
assert(
68+
init_entry!=goto_functions.function_map.end() &&
69+
init_entry->second.body_available());
70+
71+
goto_programt &init=init_entry->second.body;
72+
goto_programt::targett init_end=init.instructions.end();
73+
--init_end;
74+
assert(init_end->is_end_function());
75+
assert(init_end!=init.instructions.begin());
76+
--init_end;
77+
78+
const symbolt &main_symbol=
79+
ns.lookup(config.main.empty()?ID_main:config.main);
80+
81+
const code_typet::parameterst &parameters=
82+
to_code_type(main_symbol.type).parameters();
83+
if(parameters.size()!=2 &&
84+
parameters.size()!=3)
85+
{
86+
message.warning() << "main expected to take 2 or 3 arguments,"
87+
<< " argc/argv instrumentation skipped"
88+
<< messaget::eom;
89+
return false;
90+
}
91+
92+
// set the size of ARGV storage to 4096, which matches the minimum
93+
// guaranteed by POSIX (_POSIX_ARG_MAX):
94+
// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
95+
std::ostringstream oss;
96+
oss <<
97+
"int ARGC;\n\
98+
char *ARGV[1];\n\
99+
void " CPROVER_PREFIX "initialize()\n\
100+
{\n\
101+
unsigned next=0u;\n\
102+
" CPROVER_PREFIX "assume(ARGC>=1);\n\
103+
" CPROVER_PREFIX "assume(ARGC<=" << max_argc << ");\n\
104+
" CPROVER_PREFIX "thread_local static char arg_string[4096];\n\
105+
for(unsigned i=0u; i<ARGC && i<" << max_argc << "; ++i)\n\
106+
{\n\
107+
unsigned len;\n\
108+
" CPROVER_PREFIX "assume(len<4096);\n\
109+
" CPROVER_PREFIX "assume(next+len<4096);\n\
110+
" CPROVER_PREFIX "assume(arg_string[next+len]==0);\n\
111+
ARGV[i]=&(arg_string[next]);\n\
112+
next+=len+1;\n\
113+
}\n\
114+
}";
115+
std::istringstream iss(oss.str());
116+
117+
ansi_c_languaget ansi_c_language;
118+
ansi_c_language.set_message_handler(message_handler);
119+
configt::ansi_ct::preprocessort pp=config.ansi_c.preprocessor;
120+
config.ansi_c.preprocessor=configt::ansi_ct::preprocessort::NONE;
121+
ansi_c_language.parse(iss, "");
122+
config.ansi_c.preprocessor=pp;
123+
124+
symbol_tablet tmp_symbol_table;
125+
ansi_c_language.typecheck(tmp_symbol_table, "<built-in-library>");
126+
127+
goto_programt tmp;
128+
exprt value=nil_exprt();
129+
// locate the body of the newly built initialize function as well
130+
// as any additional declarations we might need; the body will then
131+
// be converted and appended to the existing initialize function
132+
forall_symbols(it, tmp_symbol_table.symbols)
133+
{
134+
// add __CPROVER_assume if necessary (it might exist already)
135+
if(it->first==CPROVER_PREFIX "assume")
136+
symbol_table.add(it->second);
137+
else if(it->first==CPROVER_PREFIX "initialize")
138+
{
139+
value=it->second.value;
140+
141+
replace_symbolt replace;
142+
replace.insert("ARGC", ns.lookup("argc'").symbol_expr());
143+
replace.insert("ARGV", ns.lookup("argv'").symbol_expr());
144+
replace(value);
145+
}
146+
else if(has_prefix(id2string(it->first),
147+
CPROVER_PREFIX "initialize::") &&
148+
symbol_table.add(it->second))
149+
assert(false);
150+
}
151+
152+
assert(value.is_not_nil());
153+
goto_convert(
154+
to_code(value),
155+
symbol_table,
156+
tmp,
157+
message_handler);
158+
Forall_goto_program_instructions(it, tmp)
159+
{
160+
it->source_location.set_file("<built-in-library>");
161+
it->function=CPROVER_PREFIX "initialize";
162+
}
163+
init.insert_before_swap(init_end, tmp);
164+
165+
// update counters etc.
166+
remove_skip(init);
167+
init.compute_loop_numbers();
168+
goto_functions.update();
169+
170+
return false;
171+
}
172+

src/goto-instrument/model_argc_argv.h

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*******************************************************************\
2+
3+
Module: Initialize command line arguments
4+
5+
Author: Michael Tautschnig
6+
7+
Date: April 2016
8+
9+
\*******************************************************************/
10+
11+
#ifndef CPROVER_MODEL_ARGC_ARGV_H
12+
#define CPROVER_MODEL_ARGC_ARGV_H
13+
14+
class goto_functionst;
15+
class message_handlert;
16+
class symbol_tablet;
17+
18+
bool model_argc_argv(
19+
symbol_tablet &symbol_table,
20+
goto_functionst &goto_functions,
21+
unsigned max_argc,
22+
message_handlert &message_handler);
23+
24+
#endif

0 commit comments

Comments
 (0)