Skip to content

Commit a196fd0

Browse files
committed
goto-instrument/model_argc_argv: add new option: --add-cmd-line-arg
1 parent 79515a4 commit a196fd0

File tree

2 files changed

+113
-23
lines changed

2 files changed

+113
-23
lines changed

src/goto-instrument/model_argc_argv.cpp

Lines changed: 101 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,51 @@ Date: April 2016
3030
#include <goto-programs/goto_model.h>
3131
#include <goto-programs/remove_skip.h>
3232

33-
/// Set up argv with up to max_argc pointers into an array of 4096 bytes.
33+
// Escape selected character in specified string with backslashes.
34+
//
35+
// \param input_string: string where character will be escaped.
36+
// \param find_substring: character to escape, e.g. \"
37+
// \param replace_substring: string, e.g. \\\"
38+
std::string escape_char(
39+
std::string input_string,
40+
std::string find_substring,
41+
std::string replace_substring){
42+
size_t index = 0;
43+
while (true) {
44+
/* Locate the substring to replace. */
45+
index = input_string.find(find_substring, index);
46+
47+
if (index == std::string::npos) break;
48+
49+
/* Make the replacement. */
50+
input_string.replace(index,
51+
replace_substring.size(),
52+
replace_substring);
53+
54+
/* Advance index forward so the next iteration
55+
* doesn't pick it up as well. */
56+
index += replace_substring.size();
57+
}
58+
return input_string;
59+
}
60+
61+
/// Set up argv to user-specified values (when model_argv is FALSE) or
62+
/// (when model_argv is TRUE) set up argv with up to max_argc pointers
63+
/// into a char array of 4096 bytes.
64+
///
3465
/// \param goto_model: Contains the input program's symbol table and
3566
/// intermediate representation
36-
/// \param max_argc: User-specified maximum number of arguments to be modelled
67+
/// \param argv_args: User-specified cmd-line arguments (ARGV),
68+
/// when model_argv is TRUE then size of argv_args represents
69+
/// the maximum number of arguments to be modelled
70+
/// \param model_argv: If set to TRUE then modelling argv with up to
71+
/// max_argc pointers
3772
/// \param message_handler: message logging
3873
/// \return True, if and only if modelling succeeded
3974
bool model_argc_argv(
4075
goto_modelt &goto_model,
41-
unsigned max_argc,
76+
const std::list<std::string> &argv_args,
77+
bool model_argv,
4278
message_handlert &message_handler)
4379
{
4480
messaget message(message_handler);
@@ -83,25 +119,52 @@ bool model_argc_argv(
83119
// guaranteed by POSIX (_POSIX_ARG_MAX):
84120
// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
85121
std::ostringstream oss;
86-
oss << "int ARGC;\n"
87-
<< "char *ARGV[1];\n"
88-
<< "void " << goto_model.goto_functions.entry_point() << "()\n"
89-
<< "{\n"
90-
<< " unsigned next=0u;\n"
91-
<< " " CPROVER_PREFIX "assume(ARGC>=1);\n"
92-
<< " " CPROVER_PREFIX "assume(ARGC<=" << max_argc << ");\n"
93-
<< " char arg_string[4096];\n"
94-
<< " " CPROVER_PREFIX "input(\"arg_string\", &arg_string[0]);\n"
95-
<< " for(int i=0; i<ARGC && i<" << max_argc << "; ++i)\n"
96-
<< " {\n"
97-
<< " unsigned len;\n"
98-
<< " " CPROVER_PREFIX "assume(len<4096);\n"
99-
<< " " CPROVER_PREFIX "assume(next+len<4096);\n"
100-
<< " " CPROVER_PREFIX "assume(arg_string[next+len]==0);\n"
101-
<< " ARGV[i]=&(arg_string[next]);\n"
102-
<< " next+=len+1;\n"
103-
<< " }\n"
104-
<< "}";
122+
unsigned max_argc = argv_args.size();
123+
unsigned argc = argv_args.size();
124+
125+
if(model_argv)
126+
{
127+
oss << "int ARGC;\n"
128+
<< "char *ARGV[1];\n"
129+
<< "void " << goto_model.goto_functions.entry_point() << "()\n"
130+
<< "{\n"
131+
<< " unsigned next=0u;\n"
132+
<< " " CPROVER_PREFIX "assume(ARGC>=1);\n"
133+
<< " " CPROVER_PREFIX "assume(ARGC<=" << max_argc << ");\n"
134+
<< " char arg_string[4096];\n"
135+
<< " " CPROVER_PREFIX "input(\"arg_string\", &arg_string[0]);\n"
136+
<< " for(int i=0; i<ARGC && i<" << max_argc << "; ++i)\n"
137+
<< " {\n"
138+
<< " unsigned len;\n"
139+
<< " " CPROVER_PREFIX "assume(len<4096);\n"
140+
<< " " CPROVER_PREFIX "assume(next+len<4096);\n"
141+
<< " " CPROVER_PREFIX "assume(arg_string[next+len]==0);\n"
142+
<< " ARGV[i]=&(arg_string[next]);\n"
143+
<< " next+=len+1;\n"
144+
<< " }\n"
145+
<< "}";
146+
}
147+
else
148+
{ // model_argv = false, set each argv[i] explicitly
149+
oss << "int ARGC = " << argc << ";\n"
150+
<< "char *ARGV[" << argc << "];\n"
151+
<< "void " << goto_model.goto_functions.entry_point() << "()\n"
152+
<< "{\n"
153+
<< "ARGC = " << argc << ";\n";
154+
int i = 0;
155+
for(auto &arg : argv_args)
156+
{
157+
oss << "ARGV[" << i << "]=\"" << escape_char(
158+
escape_char(
159+
escape_char(arg, "\\","\\\\"),
160+
"\'","\\\'"),
161+
"\"","\\\"")
162+
<< "\";\n";
163+
i++;
164+
}
165+
oss << "}";
166+
}
167+
105168
std::istringstream iss(oss.str());
106169

107170
ansi_c_languaget ansi_c_language;
@@ -169,6 +232,22 @@ bool model_argc_argv(
169232
main_call!=end;
170233
++main_call)
171234
{
235+
//Turn into skip instr. the INPUT(argc ...) instruction
236+
if (main_call->is_other() &&
237+
main_call->get_other().get_statement() == ID_input &&
238+
"argc\'" == id2string(to_symbol_expr(
239+
main_call->get_other().op1()).get_identifier())) {
240+
main_call->turn_into_skip();
241+
}
242+
243+
//Turn into skip instr. the ASSUME(argc ...) instruction
244+
if(main_call->is_assume() &&
245+
"argc\'" == id2string(to_symbol_expr(
246+
main_call->condition().operands()[0]).get_identifier())){
247+
248+
main_call->turn_into_skip();
249+
}
250+
172251
if(main_call->is_function_call())
173252
{
174253
const exprt &func = main_call->call_function();

src/goto-instrument/model_argc_argv.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@ Date: April 2016
1414
#ifndef CPROVER_GOTO_INSTRUMENT_MODEL_ARGC_ARGV_H
1515
#define CPROVER_GOTO_INSTRUMENT_MODEL_ARGC_ARGV_H
1616

17+
#include <list>
18+
#include <string>
19+
1720
class goto_modelt;
1821
class message_handlert;
1922

2023
bool model_argc_argv(
2124
goto_modelt &,
22-
unsigned max_argc,
25+
const std::list<std::string> &argv_args,
26+
bool model_argv,
2327
message_handlert &);
2428

29+
#define OPT_ARGC_ARGV "(model-argc-argv):(add-cmd-line-arg):"
30+
31+
#define HELP_ARGC_ARGV \
32+
" --model-argc-argv <n> model up to <n> command line arguments\n" \
33+
" --add-cmd-line-arg <arg> add command line argument (may be " \
34+
"repeated)\n"
35+
2536
#endif // CPROVER_GOTO_INSTRUMENT_MODEL_ARGC_ARGV_H

0 commit comments

Comments
 (0)