CBMC
string_concatenation_builtin_function.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Builtin functions for string concatenations
4 
5 Author: Romain Brenguier, Joel Allred
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <algorithm>
15 
17  const exprt &return_code,
18  const std::vector<exprt> &fun_args,
19  array_poolt &array_pool)
20  : string_insertion_builtin_functiont(return_code, array_pool)
21 {
22  PRECONDITION(fun_args.size() >= 4 && fun_args.size() <= 6);
23  const auto arg1 = expr_checked_cast<struct_exprt>(fun_args[2]);
24  input1 = array_pool.find(arg1.op1(), arg1.op0());
25  const auto arg2 = expr_checked_cast<struct_exprt>(fun_args[3]);
26  input2 = array_pool.find(arg2.op1(), arg2.op0());
27  result = array_pool.find(fun_args[1], fun_args[0]);
28  args.insert(args.end(), fun_args.begin() + 4, fun_args.end());
29 }
30 
52 std::pair<exprt, string_constraintst>
54  const array_string_exprt &res,
55  const array_string_exprt &s1,
56  const array_string_exprt &s2,
57  const exprt &start_index,
58  const exprt &end_index)
59 {
60  string_constraintst constraints;
61  const typet &index_type = start_index.type();
62  const exprt start1 = maximum(start_index, from_integer(0, index_type));
63  const exprt end1 =
64  maximum(minimum(end_index, array_pool.get_or_create_length(s2)), start1);
65 
66  // Axiom 1.
68  res, s1, s2, start_index, end_index, array_pool));
69 
70  // Axiom 2.
71  constraints.universal.push_back([&] {
72  const symbol_exprt idx = fresh_symbol("QA_index_concat", res.length_type());
73  return string_constraintt(
74  idx,
76  equal_exprt(s1[idx], res[idx]),
78  }());
79 
80  // Axiom 3.
81  constraints.universal.push_back([&] {
82  const symbol_exprt idx2 =
83  fresh_symbol("QA_index_concat2", res.length_type());
84  const equal_exprt res_eq(
86  s2[plus_exprt(start1, idx2)]);
87  const minus_exprt upper_bound(
90  return string_constraintt(
91  idx2, zero_if_negative(upper_bound), res_eq, message_handler);
92  }());
93 
94  return {from_integer(0, get_return_code_type()), std::move(constraints)};
95 }
96 
103  const array_string_exprt &res,
104  const array_string_exprt &s1,
105  const array_string_exprt &s2,
106  const exprt &start,
107  const exprt &end,
108  array_poolt &array_pool)
109 {
110  PRECONDITION(res.length_type().id() == ID_signedbv);
111  const exprt start1 = maximum(start, from_integer(0, start.type()));
112  const exprt end1 =
113  maximum(minimum(end, array_pool.get_or_create_length(s2)), start1);
114  const plus_exprt res_length(
115  array_pool.get_or_create_length(s1), minus_exprt(end1, start1));
116  const exprt overflow = sum_overflows(res_length);
117  const exprt max_int = to_signedbv_type(res.length_type()).largest_expr();
118  return equal_exprt(
119  array_pool.get_or_create_length(res),
120  if_exprt(overflow, max_int, res_length));
121 }
122 
126  const array_string_exprt &res,
127  const array_string_exprt &s1,
128  const array_string_exprt &s2,
129  array_poolt &array_pool)
130 {
131  return equal_exprt(
132  array_pool.get_or_create_length(res),
133  plus_exprt(
134  array_pool.get_or_create_length(s1),
135  array_pool.get_or_create_length(s2)));
136 }
137 
141  const array_string_exprt &res,
142  const array_string_exprt &s1,
143  array_poolt &array_pool)
144 {
145  return equal_exprt(
146  array_pool.get_or_create_length(res),
147  plus_exprt(
148  array_pool.get_or_create_length(s1), from_integer(1, s1.length_type())));
149 }
150 
159 std::pair<exprt, string_constraintst>
161  const array_string_exprt &res,
162  const array_string_exprt &s1,
163  const array_string_exprt &s2)
164 {
165  exprt index_zero = from_integer(0, s2.length_type());
167  res, s1, s2, index_zero, array_pool.get_or_create_length(s2));
168 }
169 
174 std::pair<exprt, string_constraintst>
177 {
178  PRECONDITION(f.arguments().size() == 4);
179  const array_string_exprt res =
180  array_pool.find(f.arguments()[1], f.arguments()[0]);
182  const typet &char_type = to_type_with_subtype(s1.content().type()).subtype();
183  const typet &index_type = s1.length_type();
184  const array_string_exprt code_point =
185  array_pool.fresh_string(index_type, char_type);
186  return combine_results(
187  add_axioms_for_code_point(code_point, f.arguments()[3]),
188  add_axioms_for_concat(res, s1, code_point));
189 }
190 
192  const std::vector<mp_integer> &input1_value,
193  const std::vector<mp_integer> &input2_value,
194  const std::vector<mp_integer> &args_value) const
195 {
196  const auto start_index =
197  args_value.size() > 0 && args_value[0] > 0 ? args_value[0] : mp_integer(0);
198  const mp_integer input2_size(input2_value.size());
199  const auto end_index =
200  args_value.size() > 1
201  ? std::max(std::min(args_value[1], input2_size), start_index)
202  : input2_size;
203 
204  std::vector<mp_integer> eval_result(input1_value);
205  eval_result.insert(
206  eval_result.end(),
207  input2_value.begin() + numeric_cast_v<std::size_t>(start_index),
208  input2_value.begin() + numeric_cast_v<std::size_t>(end_index));
209  return eval_result;
210 }
211 
213  string_constraint_generatort &generator,
214  message_handlert &message_handler) const
215 
216 {
217  auto pair = [&]() -> std::pair<exprt, string_constraintst> {
218  if(args.size() == 0)
219  return generator.add_axioms_for_concat(result, input1, input2);
220  if(args.size() == 2)
221  {
222  return generator.add_axioms_for_concat_substr(
223  result, input1, input2, args[0], args[1]);
224  }
225  UNREACHABLE;
226  }();
227  pair.second.existential.push_back(equal_exprt(pair.first, return_code));
228  return pair.second;
229 }
230 
232 {
233  if(args.size() == 0)
235  if(args.size() == 2)
237  result, input1, input2, args[0], args[1], array_pool);
238  UNREACHABLE;
239 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
array_string_exprt get_string_expr(array_poolt &array_pool, const exprt &expr)
Fetch the string_exprt corresponding to the given refined_string_exprt.
Definition: array_pool.cpp:199
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
int16_t s2
Definition: bytecode_info.h:60
int8_t s1
Definition: bytecode_info.h:59
bitvector_typet char_type()
Definition: c_types.cpp:106
Correspondance between arrays and pointers string representations.
Definition: array_pool.h:42
exprt get_or_create_length(const array_string_exprt &s)
Get the length of an array_string_exprt from the array_pool.
Definition: array_pool.cpp:26
array_string_exprt fresh_string(const typet &index_type, const typet &char_type)
Construct a string expression whose length and content are new variables.
Definition: array_pool.cpp:57
array_string_exprt find(const exprt &pointer, const exprt &length)
Creates a new array if the pointer is not pointing to an array.
Definition: array_pool.cpp:184
const typet & length_type() const
Definition: string_expr.h:70
Equality.
Definition: std_expr.h:1361
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
Application of (mathematical) function.
The trinary if-then-else operator.
Definition: std_expr.h:2370
constant_exprt largest_expr() const
Return an expression representing the largest value of this type.
const irep_idt & id() const
Definition: irep.h:384
Binary minus.
Definition: std_expr.h:1061
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
string_constraintst constraints(string_constraint_generatort &generator, message_handlert &message_handler) const override
Add constraints ensuring that the value of result expression of the builtin function corresponds to t...
string_concatenation_builtin_functiont(const exprt &return_code, const std::vector< exprt > &fun_args, array_poolt &array_pool)
Constructor from arguments of a function application.
std::vector< mp_integer > eval(const std::vector< mp_integer > &input1_value, const std::vector< mp_integer > &input2_value, const std::vector< mp_integer > &args_value) const override
Evaluate the result from a concrete valuation of the arguments.
exprt length_constraint() const override
Constraint ensuring that the length of the strings are coherent with the function call.
std::pair< exprt, string_constraintst > add_axioms_for_concat(const array_string_exprt &res, const array_string_exprt &s1, const array_string_exprt &s2)
Add axioms enforcing that res is equal to the concatenation of s1 and s2.
std::pair< exprt, string_constraintst > add_axioms_for_concat_substr(const array_string_exprt &res, const array_string_exprt &s1, const array_string_exprt &s2, const exprt &start_index, const exprt &end_index)
Add axioms enforcing that res is the concatenation of s1 with the substring of s2 starting at index ‘...
std::pair< exprt, string_constraintst > add_axioms_for_code_point(const array_string_exprt &res, const exprt &code_point)
add axioms for the conversion of an integer representing a java code point to a utf-16 string
std::pair< exprt, string_constraintst > add_axioms_for_concat_code_point(const function_application_exprt &f)
Add axioms corresponding to the StringBuilder.appendCodePoint(I) function.
std::pair< exprt, string_constraintst > combine_results(std::pair< exprt, string_constraintst > result1, std::pair< exprt, string_constraintst > result2)
Combine the results of two add_axioms function by taking the maximum of the return codes and merging ...
String inserting a string into another one.
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const typet & subtype() const
Definition: type.h:187
The type of an expression, extends irept.
Definition: type.h:29
BigInt mp_integer
Definition: smt_terms.h:17
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
exprt length_constraint_for_concat(const array_string_exprt &res, const array_string_exprt &s1, const array_string_exprt &s2, array_poolt &array_pool)
Add axioms enforcing that the length of res is that of the concatenation of s1 with s2
exprt length_constraint_for_concat_char(const array_string_exprt &res, const array_string_exprt &s1, array_poolt &array_pool)
Add axioms enforcing that the length of res is that of the concatenation of s1 with.
exprt length_constraint_for_concat_substr(const array_string_exprt &res, const array_string_exprt &s1, const array_string_exprt &s2, const exprt &start, const exprt &end, array_poolt &array_pool)
Add axioms enforcing that the length of res is that of the concatenation of s1 with the substring of ...
Builtin functions for string concatenations.
exprt sum_overflows(const plus_exprt &sum)
exprt maximum(const exprt &a, const exprt &b)
exprt minimum(const exprt &a, const exprt &b)
exprt zero_if_negative(const exprt &expr)
Returns a non-negative version of the argument.
signedbv_typet get_return_code_type()
Collection of constraints of different types: existential formulas, universal formulas,...
std::vector< exprt > existential
std::vector< string_constraintt > universal
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208