Skip to content

Commit 763b8d1

Browse files
Add support for nondet initialisation of strings.
Add support for nondet-initialisation of strings in the function-call goto-harness leveraging pointer nondet initialisation. Co-authored-by: Fotis Koutoulakis <[email protected]> Co-authored-by: Hannes Steffenhagen <[email protected]>
1 parent 5598410 commit 763b8d1

File tree

6 files changed

+157
-18
lines changed

6 files changed

+157
-18
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <assert.h>
2+
3+
void function(char *pointer, int size)
4+
{
5+
assert(pointer[size-1] == '\0');
6+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--harness-type call-function --function function --treat-pointer-as-cstring pointer --associated-array-size pointer:size
4+
\[function.assertion.\d+\] line \d+ assertion pointer\[size-1\] == \'\\0\': SUCCESS
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--

src/goto-harness/function_call_harness_generator.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct function_call_harness_generatort::implt
4848
std::set<irep_idt> function_parameters_to_treat_as_arrays;
4949
std::set<irep_idt> function_arguments_to_treat_as_arrays;
5050

51+
std::set<irep_idt> function_parameters_to_treat_as_cstrings;
52+
std::set<irep_idt> function_arguments_to_treat_as_cstrings;
53+
5154
std::map<irep_idt, irep_idt> function_argument_to_associated_array_size;
5255
std::map<irep_idt, irep_idt> function_parameter_to_associated_array_size;
5356

@@ -182,6 +185,15 @@ void function_call_harness_generatort::handle_option(
182185
}
183186
}
184187
}
188+
else if(option == FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_CSTRING)
189+
{
190+
std::copy(
191+
values.begin(),
192+
values.end(),
193+
std::inserter(
194+
p_impl->function_parameters_to_treat_as_cstrings,
195+
p_impl->function_parameters_to_treat_as_cstrings.end()));
196+
}
185197
else
186198
{
187199
throw invalid_command_line_argument_exceptiont{
@@ -216,6 +228,8 @@ void function_call_harness_generatort::implt::generate(
216228
function_arguments_to_treat_as_arrays;
217229
recursive_initialization_config.array_name_to_associated_array_size_variable =
218230
function_argument_to_associated_array_size;
231+
recursive_initialization_config.pointers_to_treat_as_cstrings =
232+
function_arguments_to_treat_as_cstrings;
219233
std::transform(
220234
function_argument_to_associated_array_size.begin(),
221235
function_argument_to_associated_array_size.end(),
@@ -393,6 +407,14 @@ function_call_harness_generatort::implt::declare_arguments(
393407
{
394408
function_arguments_to_treat_as_arrays.insert(argument_name);
395409
}
410+
411+
if(
412+
function_parameters_to_treat_as_cstrings.find(parameter_name) !=
413+
function_parameters_to_treat_as_cstrings.end())
414+
{
415+
function_arguments_to_treat_as_cstrings.insert(argument_name);
416+
}
417+
396418
auto it = function_parameter_to_associated_array_size.find(parameter_name);
397419
if(it != function_parameter_to_associated_array_size.end())
398420
{

src/goto-harness/function_harness_generator_options.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Author: Diffblue Ltd.
2020
"treat-pointer-as-array"
2121
#define FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT \
2222
"associated-array-size"
23+
#define FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_CSTRING \
24+
"treat-pointer-as-cstring"
2325

2426
// clang-format off
2527
#define FUNCTION_HARNESS_GENERATOR_OPTIONS \
@@ -31,6 +33,7 @@ Author: Diffblue Ltd.
3133
"(" FUNCTION_HARNESS_GENERATOR_MAX_ARRAY_SIZE_OPT "):" \
3234
"(" FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_ARRAY_OPT "):" \
3335
"(" FUNCTION_HARNESS_GENERATOR_ASSOCIATED_ARRAY_SIZE_OPT "):" \
36+
"(" FUNCTION_HARNESS_GENERATOR_TREAT_POINTER_AS_CSTRING "):" \
3437
// FUNCTION_HARNESS_GENERATOR_OPTIONS
3538

3639
// clang-format on

src/goto-harness/recursive_initialization.cpp

Lines changed: 95 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Author: Diffblue Ltd.
1717
#include <util/std_code.h>
1818
#include <util/std_expr.h>
1919

20+
#include <functional>
21+
2022
recursive_initializationt::recursive_initializationt(
2123
recursive_initialization_configt initialization_config,
2224
goto_modelt &goto_model)
@@ -38,20 +40,27 @@ void recursive_initializationt::initialize(
3840
}
3941
else if(type.id() == ID_pointer)
4042
{
41-
if(
42-
lhs.id() == ID_symbol &&
43-
should_be_treated_as_array(to_symbol_expr(lhs).get_identifier()))
43+
if(lhs.id() == ID_symbol)
4444
{
45-
initialize_dynamic_array(lhs, depth, known_tags, body);
46-
}
47-
else
48-
{
49-
initialize_pointer(lhs, depth, known_tags, body);
45+
auto const &lhs_symbol = to_symbol_expr(lhs);
46+
if(should_be_treated_as_cstring(lhs_symbol.get_identifier()))
47+
{
48+
initialize_cstring(lhs, depth, known_tags, body);
49+
return;
50+
}
51+
else if(should_be_treated_as_array(lhs_symbol.get_identifier()))
52+
{
53+
initialize_dynamic_array(
54+
lhs, depth, known_tags, body, default_array_member_initialization());
55+
return;
56+
}
5057
}
58+
initialize_pointer(lhs, depth, known_tags, body);
5159
}
5260
else if(type.id() == ID_array)
5361
{
54-
initialize_array(lhs, depth, known_tags, body);
62+
initialize_array(
63+
lhs, depth, known_tags, body, default_array_member_initialization());
5564
}
5665
else
5766
{
@@ -163,19 +172,17 @@ void recursive_initializationt::initialize_array(
163172
const exprt &array,
164173
std::size_t depth,
165174
const recursion_sett &known_tags,
166-
code_blockt &body)
175+
code_blockt &body,
176+
array_convertert array_member_initialization)
167177
{
168178
PRECONDITION(array.type().id() == ID_array);
169179
const auto &array_type = to_array_type(array.type());
170180
const auto array_size =
171181
numeric_cast_v<std::size_t>(to_constant_expr(array_type.size()));
172182
for(std::size_t index = 0; index < array_size; index++)
173183
{
174-
initialize(
175-
index_exprt(array, from_integer(index, size_type())),
176-
depth,
177-
known_tags,
178-
body);
184+
array_member_initialization(
185+
array, array_size, index, depth, known_tags, body);
179186
}
180187
}
181188

@@ -202,11 +209,20 @@ optionalt<irep_idt> recursive_initializationt::get_associated_size_variable(
202209
array_name);
203210
}
204211

212+
bool recursive_initializationt::should_be_treated_as_cstring(
213+
const irep_idt &pointer_name) const
214+
{
215+
return initialization_config.pointers_to_treat_as_cstrings.find(
216+
pointer_name) !=
217+
initialization_config.pointers_to_treat_as_cstrings.end();
218+
}
219+
205220
void recursive_initializationt::initialize_dynamic_array(
206221
const exprt &pointer,
207222
std::size_t depth,
208223
const recursion_sett &known_tags,
209-
code_blockt &body)
224+
code_blockt &body,
225+
array_convertert array_initialization)
210226
{
211227
PRECONDITION(pointer.type().id() == ID_pointer);
212228

@@ -264,7 +280,8 @@ void recursive_initializationt::initialize_dynamic_array(
264280
std::size_t array_counter = 0;
265281
for(const auto &array_variable : array_variables)
266282
{
267-
initialize(array_variable, depth + 1, known_tags, body);
283+
initialize_array(
284+
array_variable, depth + 1, known_tags, body, array_initialization);
268285
body.add(code_assignt{
269286
index_exprt{arrays, from_integer(array_counter++, size_type())},
270287
address_of_exprt{
@@ -296,6 +313,16 @@ void recursive_initializationt::initialize_dynamic_array(
296313
body.add(code_assignt{pointer, index_exprt{arrays, nondet_index}});
297314
}
298315

316+
void recursive_initializationt::initialize_cstring(
317+
const exprt &pointer,
318+
std::size_t depth,
319+
const recursion_sett &known_tags,
320+
code_blockt &body)
321+
{
322+
initialize_dynamic_array(
323+
pointer, depth, known_tags, body, cstring_member_initialization());
324+
}
325+
299326
std::string recursive_initialization_configt::to_string() const
300327
{
301328
std::ostringstream out{};
@@ -325,6 +352,57 @@ std::string recursive_initialization_configt::to_string() const
325352
<< associated_array_size.second;
326353
}
327354
out << "\n ]";
355+
out << "\n pointers_to_treat_as_cstrings = [";
356+
for(const auto &pointer_to_treat_as_string_name :
357+
pointers_to_treat_as_cstrings)
358+
{
359+
out << "\n " << pointer_to_treat_as_string_name << std::endl;
360+
}
361+
out << "\n ]";
328362
out << "\n}";
329363
return out.str();
330364
}
365+
366+
recursive_initializationt::array_convertert
367+
recursive_initializationt::default_array_member_initialization()
368+
{
369+
return [this](
370+
const exprt &array,
371+
const std::size_t length,
372+
const std::size_t current_index,
373+
const std::size_t depth,
374+
const recursion_sett &known_tags,
375+
code_blockt &body) {
376+
PRECONDITION(array.type().id() == ID_array);
377+
initialize(
378+
index_exprt{array, from_integer(current_index, size_type())},
379+
depth,
380+
known_tags,
381+
body);
382+
};
383+
}
384+
385+
recursive_initializationt::array_convertert
386+
recursive_initializationt::cstring_member_initialization()
387+
{
388+
return [this](
389+
const exprt &array,
390+
const std::size_t length,
391+
const std::size_t current_index,
392+
const std::size_t depth,
393+
const recursion_sett &known_tags,
394+
code_blockt &body) {
395+
PRECONDITION(array.type().id() == ID_array);
396+
PRECONDITION(array.type().subtype() == char_type());
397+
auto const member =
398+
index_exprt{array, from_integer(current_index, size_type())};
399+
if(current_index + 1 == length)
400+
{
401+
body.add(code_assignt{member, from_integer(0, array.type().subtype())});
402+
}
403+
else
404+
{
405+
initialize(member, depth, known_tags, body);
406+
}
407+
};
408+
}

src/goto-harness/recursive_initialization.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct recursive_initialization_configt
3232
std::set<irep_idt> variables_that_hold_array_sizes;
3333
std::map<irep_idt, irep_idt> array_name_to_associated_array_size_variable;
3434

35+
std::set<irep_idt> pointers_to_treat_as_cstrings;
36+
3537
std::string to_string() const; // for debugging purposes
3638
};
3739

@@ -81,12 +83,31 @@ class recursive_initializationt
8183
std::size_t depth,
8284
const recursion_sett &known_tags,
8385
code_blockt &body);
86+
87+
using array_convertert = std::function<void(
88+
const exprt &pointer,
89+
std::size_t length,
90+
std::size_t current_index,
91+
std::size_t depth,
92+
const recursion_sett &known_tags,
93+
code_blockt &body)>;
94+
array_convertert default_array_member_initialization();
95+
array_convertert cstring_member_initialization();
96+
8497
void initialize_array(
8598
const exprt &array,
8699
std::size_t depth,
87100
const recursion_sett &known_tags,
88-
code_blockt &body);
101+
code_blockt &body,
102+
array_convertert array_member_initialization);
89103
void initialize_dynamic_array(
104+
const exprt &pointer,
105+
std::size_t depth,
106+
const recursion_sett &known_tags,
107+
code_blockt &body,
108+
array_convertert array_member_initialization);
109+
110+
void initialize_cstring(
90111
const exprt &pointer,
91112
std::size_t depth,
92113
const recursion_sett &known_tags,
@@ -96,6 +117,7 @@ class recursive_initializationt
96117
bool is_array_size_parameter(const irep_idt &cmdline_arg) const;
97118
optionalt<irep_idt>
98119
get_associated_size_variable(const irep_idt &array_name) const;
120+
bool should_be_treated_as_cstring(const irep_idt &pointer_name) const;
99121
};
100122

101123
#endif // CPROVER_GOTO_HARNESS_RECURSIVE_INITIALIZATION_H

0 commit comments

Comments
 (0)