Skip to content

Commit 8081a9a

Browse files
Merge pull request #738 from allredj/test-gen-support-string-additional-options-2
Test gen support string additional options 2
2 parents 03891c9 + 91d07b1 commit 8081a9a

10 files changed

+347
-85
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
320320
if(cmdline.isset("refine-strings"))
321321
{
322322
options.set_option("refine-strings", true);
323+
options.set_option("string-non-empty", cmdline.isset("string-non-empty"));
324+
options.set_option("string-printable", cmdline.isset("string-printable"));
325+
if(cmdline.isset("string-max-length"))
326+
options.set_option(
327+
"string-max-length", cmdline.get_value("string-max-length"));
323328
}
324329

325330
if(cmdline.isset("max-node-refinement"))
@@ -1207,6 +1212,9 @@ void cbmc_parse_optionst::help()
12071212
" --z3 use Z3\n"
12081213
" --refine use refinement procedure (experimental)\n"
12091214
" --refine-strings use string refinement (experimental)\n"
1215+
" --string-non-empty add constraint that strings are non empty (experimental)\n" // NOLINT(*)
1216+
" --string-printable add constraint that strings are printable (experimental)\n" // NOLINT(*)
1217+
" --string-max-length add constraint on the length of strings (experimental)\n" // NOLINT(*)
12101218
" --outfile filename output formula to given file\n"
12111219
" --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*)
12121220
" --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*)

src/cbmc/cbmc_parse_options.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class optionst;
3939
"(no-pretty-names)(beautify)" \
4040
"(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\
4141
"(refine-strings)" \
42+
"(string-non-empty)" \
43+
"(string-printable)" \
44+
"(string-max-length):" \
4245
"(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \
4346
"(little-endian)(big-endian)" \
4447
"(show-goto-functions)(show-loops)" \

src/cbmc/cbmc_solvers.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,16 @@ cbmc_solverst::solvert* cbmc_solverst::get_string_refinement()
232232
string_refinementt *string_refinement=new string_refinementt(
233233
ns, *prop, MAX_NB_REFINEMENT);
234234
string_refinement->set_ui(ui);
235+
236+
string_refinement->do_concretizing=options.get_bool_option("trace");
237+
if(options.get_bool_option("string-max-length"))
238+
string_refinement->set_max_string_length(
239+
options.get_signed_int_option("string-max-length"));
240+
if(options.get_bool_option("string-non-empty"))
241+
string_refinement->enforce_non_empty_string();
242+
if(options.get_bool_option("string-printable"))
243+
string_refinement->enforce_printable_characters();
244+
235245
return new solvert(string_refinement, prop);
236246
}
237247

src/solvers/refinement/string_constraint_generator.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Romain Brenguier, [email protected]
1313
#ifndef CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H
1414
#define CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H
1515

16+
#include <limits>
1617
#include <util/string_expr.h>
1718
#include <util/replace_expr.h>
1819
#include <util/refined_string_type.h>
@@ -22,21 +23,19 @@ class string_constraint_generatort
2223
{
2324
public:
2425
// This module keeps a list of axioms. It has methods which generate
25-
// string constraints for different string funcitons and add them
26+
// string constraints for different string functions and add them
2627
// to the axiom list.
2728

2829
string_constraint_generatort():
29-
mode(ID_unknown)
30+
max_string_length(std::numeric_limits<size_t>::max()),
31+
force_printable_characters(false)
3032
{ }
3133

32-
void set_mode(irep_idt _mode)
33-
{
34-
// only C and java modes supported
35-
assert((_mode==ID_java) || (_mode==ID_C));
36-
mode=_mode;
37-
}
34+
// Constraints on the maximal length of strings
35+
size_t max_string_length;
3836

39-
irep_idt &get_mode() { return mode; }
37+
// Should we add constraints on the characters
38+
bool force_printable_characters;
4039

4140
// Axioms are of three kinds: universally quantified string constraint,
4241
// not contains string constraints and simple formulas.
@@ -74,6 +73,8 @@ class string_constraint_generatort
7473
// Maps unresolved symbols to the string_exprt that was created for them
7574
std::map<irep_idt, string_exprt> unresolved_symbols;
7675

76+
// Set of strings that have been created by the generator
77+
std::set<string_exprt> created_strings;
7778

7879
string_exprt find_or_add_string_of_symbol(
7980
const symbol_exprt &sym,
@@ -100,6 +101,7 @@ class string_constraint_generatort
100101

101102
static irep_idt extract_java_string(const symbol_exprt &s);
102103

104+
void add_default_axioms(const string_exprt &s);
103105
exprt axiom_for_is_positive_index(const exprt &x);
104106

105107
// The following functions add axioms for the returned value

src/solvers/refinement/string_constraint_generator_concat.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ string_exprt string_constraint_generatort::add_axioms_for_concat(
3535
// a4 : forall i<|s1|. res[i]=s1[i]
3636
// a5 : forall i<|s2|. res[i+|s1|]=s2[i]
3737

38-
res.length()=plus_exprt_with_overflow_check(s1.length(), s2.length());
38+
equal_exprt a1(
39+
res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length()));
40+
axioms.push_back(a1);
3941
axioms.push_back(s1.axiom_for_is_shorter_than(res));
4042
axioms.push_back(s2.axiom_for_is_shorter_than(res));
4143

src/solvers/refinement/string_constraint_generator_insert.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,32 @@ Function: string_constraint_generatort::add_axioms_for_insert
4040
4141
Outputs: a new string expression
4242
43-
Purpose: add axioms corresponding to the StringBuilder.insert(String) java
44-
function
43+
Purpose: add axioms corresponding to the
44+
StringBuilder.insert(int, CharSequence)
45+
and StringBuilder.insert(int, CharSequence, int, int)
46+
java functions
4547
4648
\*******************************************************************/
4749

4850
string_exprt string_constraint_generatort::add_axioms_for_insert(
4951
const function_application_exprt &f)
5052
{
51-
string_exprt s1=get_string_expr(args(f, 3)[0]);
52-
string_exprt s2=get_string_expr(args(f, 3)[2]);
53-
return add_axioms_for_insert(s1, s2, args(f, 3)[1]);
53+
assert(f.arguments().size()>=3);
54+
string_exprt s1=get_string_expr(f.arguments()[0]);
55+
string_exprt s2=get_string_expr(f.arguments()[2]);
56+
const exprt &offset=f.arguments()[1];
57+
if(f.arguments().size()==5)
58+
{
59+
const exprt &start=f.arguments()[3];
60+
const exprt &end=f.arguments()[4];
61+
string_exprt substring=add_axioms_for_substring(s2, start, end);
62+
return add_axioms_for_insert(s1, substring, offset);
63+
}
64+
else
65+
{
66+
assert(f.arguments().size()==3);
67+
return add_axioms_for_insert(s1, s2, offset);
68+
}
5469
}
5570

5671
/*******************************************************************\

src/solvers/refinement/string_constraint_generator_main.cpp

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,11 @@ Function: string_constraint_generatort::fresh_string
173173
string_exprt string_constraint_generatort::fresh_string(
174174
const refined_string_typet &type)
175175
{
176-
symbol_exprt length=
177-
fresh_symbol("string_length", type.get_index_type());
176+
symbol_exprt length=fresh_symbol("string_length", type.get_index_type());
178177
symbol_exprt content=fresh_symbol("string_content", type.get_content_type());
179-
return string_exprt(length, content, type);
178+
string_exprt str(length, content, type);
179+
created_strings.insert(str);
180+
return str;
180181
}
181182

182183
/*******************************************************************\
@@ -223,7 +224,6 @@ Function: string_constraint_generatort::convert_java_string_to_string_exprt
223224
string_exprt string_constraint_generatort::convert_java_string_to_string_exprt(
224225
const exprt &jls)
225226
{
226-
assert(get_mode()==ID_java);
227227
assert(jls.id()==ID_struct);
228228

229229
exprt length(to_struct_expr(jls).op1());
@@ -246,6 +246,45 @@ string_exprt string_constraint_generatort::convert_java_string_to_string_exprt(
246246

247247
/*******************************************************************\
248248
249+
Function: string_constraint_generatort::add_default_constraints
250+
251+
Inputs:
252+
s - a string expression
253+
254+
Outputs: a string expression that is linked to the argument through
255+
axioms that are added to the list
256+
257+
Purpose: adds standard axioms about the length of the string and
258+
its content:
259+
* its length should be positive
260+
* it should not exceed max_string_length
261+
* if force_printable_characters is true then all characters
262+
should belong to the range of ASCII characters between ' ' and '~'
263+
264+
265+
\*******************************************************************/
266+
267+
void string_constraint_generatort::add_default_axioms(
268+
const string_exprt &s)
269+
{
270+
s.axiom_for_is_longer_than(from_integer(0, s.length().type()));
271+
if(max_string_length!=std::numeric_limits<size_t>::max())
272+
axioms.push_back(s.axiom_for_is_shorter_than(max_string_length));
273+
274+
if(force_printable_characters)
275+
{
276+
symbol_exprt qvar=fresh_univ_index("printable", s.length().type());
277+
exprt chr=s[qvar];
278+
and_exprt printable(
279+
binary_relation_exprt(chr, ID_ge, from_integer(' ', chr.type())),
280+
binary_relation_exprt(chr, ID_le, from_integer('~', chr.type())));
281+
string_constraintt sc(qvar, s.length(), printable);
282+
axioms.push_back(sc);
283+
}
284+
}
285+
286+
/*******************************************************************\
287+
249288
Function: string_constraint_generatort::add_axioms_for_refined_string
250289
251290
Inputs: an expression of refined string type
@@ -258,7 +297,6 @@ Function: string_constraint_generatort::add_axioms_for_refined_string
258297
259298
\*******************************************************************/
260299

261-
262300
string_exprt string_constraint_generatort::add_axioms_for_refined_string(
263301
const exprt &string)
264302
{
@@ -272,15 +310,13 @@ string_exprt string_constraint_generatort::add_axioms_for_refined_string(
272310
{
273311
const symbol_exprt &sym=to_symbol_expr(string);
274312
string_exprt s=find_or_add_string_of_symbol(sym, type);
275-
axioms.push_back(
276-
s.axiom_for_is_longer_than(from_integer(0, s.length().type())));
313+
add_default_axioms(s);
277314
return s;
278315
}
279316
else if(string.id()==ID_nondet_symbol)
280317
{
281318
string_exprt s=fresh_string(type);
282-
axioms.push_back(
283-
s.axiom_for_is_longer_than(from_integer(0, s.length().type())));
319+
add_default_axioms(s);
284320
return s;
285321
}
286322
else if(string.id()==ID_if)
@@ -290,8 +326,7 @@ string_exprt string_constraint_generatort::add_axioms_for_refined_string(
290326
else if(string.id()==ID_struct)
291327
{
292328
const string_exprt &s=to_string_expr(string);
293-
axioms.push_back(
294-
s.axiom_for_is_longer_than(from_integer(0, s.length().type())));
329+
add_default_axioms(s);
295330
return s;
296331
}
297332
else
@@ -397,7 +432,6 @@ exprt string_constraint_generatort::add_axioms_for_function_application(
397432
// TODO: This part needs some improvement.
398433
// Stripping the symbol name is not a very robust process.
399434
new_expr.function() = symbol_exprt(str_id.substr(0, pos+4));
400-
assert(get_mode()==ID_java);
401435
new_expr.type() = refined_string_typet(java_int_type(), java_char_type());
402436

403437
auto res_it=function_application_cache.insert(std::make_pair(new_expr,

0 commit comments

Comments
 (0)