Skip to content

Commit 332f94b

Browse files
committed
Sanity check user specified havoc parameters
1: check the function actually takes that many parameters 2: check the parameter type is a pointer Adds tests and extends the documentation.
1 parent 2bef1f0 commit 332f94b

File tree

5 files changed

+55
-4
lines changed

5 files changed

+55
-4
lines changed

doc/cprover-manual/goto-instrument.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ int main() {
118118
}
119119
```
120120
121+
Note that only parameters of pointer type can be havoc(ed) and CBMC will produce
122+
an error report if given a parameter number associated with a non-pointer
123+
parameter. Requesting to havoc a parameter with a number higher than the number
124+
of parameters a given function takes will also results in an error report.
125+
121126
### Loop Transformations
122127
123128
### Memory Model Instrumentations

regression/goto-instrument/generate-function-body-havoc-params-call-sites/main.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@ struct S
66
char *j;
77
};
88

9-
void touches_parameter(int *param, int *const_param, struct S *struct_param);
9+
void touches_parameter(
10+
int *param,
11+
int *const_param,
12+
struct S *struct_param,
13+
int non_pointer_param);
1014

1115
int main(void)
1216
{
1317
int parameter = 10;
1418
int unchanged_parameter = 10;
1519
struct S my_struct = {.i = 10, .j = "10"};
16-
touches_parameter(&parameter, &unchanged_parameter, &my_struct);
20+
touches_parameter(&parameter, &unchanged_parameter, &my_struct, 4);
1721
assert(parameter == 10);
1822
assert(unchanged_parameter == 10);
1923
assert(my_struct.i == 10);
@@ -23,7 +27,7 @@ int main(void)
2327
unchanged_parameter = 10;
2428
my_struct.i = 10;
2529
my_struct.j = "10";
26-
touches_parameter(&parameter, &unchanged_parameter, &my_struct);
30+
touches_parameter(&parameter, &unchanged_parameter, &my_struct, 4);
2731
assert(parameter == 10);
2832
assert(unchanged_parameter == 10);
2933
assert(my_struct.i == 10);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--generate-havocing-body 'touches_parameter,1,params:0;3,2,params:1'
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
^Reason: argument number 3 of function touches_parameter.1 is not a pointer$
7+
--
8+
^warning: ignoring
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--generate-havocing-body 'touches_parameter,1,params:0;5,2,params:1'
4+
^EXIT=1$
5+
^SIGNAL=0$
6+
^Reason: function touches_parameter.1 does not take 6 arguments$
7+
--
8+
^warning: ignoring

src/goto-instrument/generate_function_bodies.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,33 @@ class havoc_generate_function_bodiest : public generate_function_bodiest
236236
symbol_tablet &symbol_table,
237237
const irep_idt &function_name) const override
238238
{
239+
const namespacet ns(symbol_table);
240+
// some user input checking
241+
if(param_numbers_to_havoc.has_value() && !param_numbers_to_havoc->empty())
242+
{
243+
auto max_param_number = std::max_element(
244+
param_numbers_to_havoc->begin(), param_numbers_to_havoc->end());
245+
if(*max_param_number >= function.parameter_identifiers.size())
246+
{
247+
throw invalid_command_line_argument_exceptiont{
248+
"function " + id2string(function_name) + " does not take " +
249+
std::to_string(*max_param_number + 1) + " arguments",
250+
"--generate-havocing-body"};
251+
}
252+
for(const auto number : *param_numbers_to_havoc)
253+
{
254+
const auto &parameter = function.parameter_identifiers[number];
255+
const symbolt &parameter_symbol = ns.lookup(parameter);
256+
if(parameter_symbol.type.id() != ID_pointer)
257+
{
258+
throw invalid_command_line_argument_exceptiont{
259+
"argument number " + std::to_string(number) + " of function " +
260+
id2string(function_name) + " is not a pointer",
261+
"--generate-havocing-body"};
262+
}
263+
}
264+
}
265+
239266
auto const &function_symbol = symbol_table.lookup_ref(function_name);
240267
// NOLINTNEXTLINE
241268
auto add_instruction = [&](goto_programt::instructiont &&i) {
@@ -244,7 +271,6 @@ class havoc_generate_function_bodiest : public generate_function_bodiest
244271
return instruction;
245272
};
246273

247-
const namespacet ns(symbol_table);
248274
for(std::size_t i = 0; i < function.parameter_identifiers.size(); ++i)
249275
{
250276
const auto &parameter = function.parameter_identifiers[i];

0 commit comments

Comments
 (0)