CBMC
java_trace_validation.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Java trace validation
4 
5 Author: Jeannie Moulton
6 
7 \*******************************************************************/
8 
10 
11 #include <algorithm>
12 
14 
15 #include <util/byte_operators.h>
16 #include <util/expr_util.h>
17 #include <util/pointer_expr.h>
18 #include <util/simplify_expr.h>
19 #include <util/std_expr.h>
20 
21 bool check_symbol_structure(const exprt &expr)
22 {
23  const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr);
24  return symbol && !symbol->get_identifier().empty();
25 }
26 
29 static bool may_be_lvalue(const exprt &expr)
30 {
31  return can_cast_expr<member_exprt>(expr) ||
37 }
38 
39 std::optional<symbol_exprt> get_inner_symbol_expr(exprt expr)
40 {
41  while(expr.has_operands())
42  {
43  expr = to_multi_ary_expr(expr).op0();
44  if(!may_be_lvalue(expr))
45  return {};
46  }
47  if(!check_symbol_structure(expr))
48  return {};
49  return *expr_try_dynamic_cast<symbol_exprt>(expr);
50 }
51 
53 {
54  if(!expr.has_operands())
55  return false;
56  const auto symbol_operand = get_inner_symbol_expr(expr);
57  return symbol_operand.has_value();
58 }
59 
61 {
65 }
66 
68 {
76 }
77 
78 bool can_evaluate_to_constant(const exprt &expression)
79 {
80  return can_cast_expr<constant_exprt>(skip_typecast(expression)) ||
84 }
85 
86 bool check_index_structure(const exprt &index_expr)
87 {
88  return (can_cast_expr<index_exprt>(index_expr) ||
89  can_cast_expr<byte_extract_exprt>(index_expr)) &&
90  index_expr.operands().size() == 2 &&
91  check_symbol_structure(to_binary_expr(index_expr).op0()) &&
92  can_evaluate_to_constant(to_binary_expr(index_expr).op1());
93 }
94 
96 {
97  if(!expr.has_operands())
98  return false;
99  if(const auto sub_struct = expr_try_dynamic_cast<struct_exprt>(expr.op0()))
100  check_struct_structure(*sub_struct);
101  else if(
104  {
105  return false;
106  }
107 
108  return expr.operands().size() == 1 ||
109  std::all_of(
110  std::next(expr.operands().begin()),
111  expr.operands().end(),
112  [&](const exprt &operand) {
113  return can_cast_expr<constant_exprt>(operand) ||
114  can_cast_expr<annotated_pointer_constant_exprt>(operand);
115  });
116 }
117 
119 {
120  const auto symbol_expr = get_inner_symbol_expr(address);
121  return symbol_expr && check_symbol_structure(*symbol_expr);
122 }
123 
124 bool check_constant_structure(const constant_exprt &constant_expr)
125 {
126  if(constant_expr.has_operands())
127  return false;
128  // All value types used in Java must be non-empty except string_typet:
129  return !constant_expr.get_value().empty() ||
130  constant_expr.type() == string_typet();
131 }
132 
134  const annotated_pointer_constant_exprt &constant_expr)
135 {
136  const auto &operand = skip_typecast(constant_expr.symbolic_pointer());
137  return can_cast_expr<constant_exprt>(operand) ||
139  can_cast_expr<plus_exprt>(operand);
140 }
141 
143  const exprt &lhs,
144  const namespacet &ns,
145  const validation_modet vm)
146 {
148  vm,
150  "LHS",
151  lhs.pretty(),
152  "Unsupported expression.");
153  // check member lhs structure
154  if(const auto member = expr_try_dynamic_cast<member_exprt>(lhs))
155  {
157  vm,
158  check_member_structure(*member),
159  "LHS",
160  lhs.pretty(),
161  "Expecting a member with nested symbol operand.");
162  }
163  // check symbol lhs structure
164  else if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(lhs))
165  {
167  vm,
168  check_symbol_structure(*symbol),
169  "LHS",
170  lhs.pretty(),
171  "Expecting a symbol with non-empty identifier.");
172  }
173  // check index lhs structure
174  else if(const auto index = expr_try_dynamic_cast<index_exprt>(lhs))
175  {
177  vm,
178  check_index_structure(*index),
179  "LHS",
180  lhs.pretty(),
181  "Expecting an index expression with a symbol array and constant or "
182  "symbol index value.");
183  }
184  // check byte extract lhs structure
185  else if(const auto byte = expr_try_dynamic_cast<byte_extract_exprt>(lhs))
186  {
188  vm,
189  check_index_structure(*byte),
190  "LHS",
191  lhs.pretty(),
192  "Expecting a byte extract expression with a symbol array and constant or "
193  "symbol index value.");
194  }
195  else
196  {
198  vm,
199  false,
200  "LHS",
201  lhs.pretty(),
202  "Expression does not meet any trace assumptions.");
203  }
204 }
205 
207  const exprt &rhs,
208  const namespacet &ns,
209  const validation_modet vm)
210 {
212  vm,
214  "RHS",
215  rhs.pretty(),
216  "Unsupported expression.");
217  // check address_of rhs structure (String only)
218  if(const auto address = expr_try_dynamic_cast<address_of_exprt>(rhs))
219  {
221  vm,
222  check_address_structure(*address),
223  "RHS",
224  rhs.pretty(),
225  "Expecting an address of with nested symbol.");
226  }
227  // check symbol rhs structure (String only)
228  else if(const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(rhs))
229  {
231  vm,
232  check_symbol_structure(*symbol_expr),
233  "RHS",
234  rhs.pretty(),
235  "Expecting a symbol with non-empty identifier.");
236  }
237  // check struct rhs structure
238  else if(const auto struct_expr = expr_try_dynamic_cast<struct_exprt>(rhs))
239  {
241  vm,
242  check_struct_structure(*struct_expr),
243  "RHS",
244  rhs.pretty(),
245  "Expecting all non-base class operands to be constants.");
246  }
247  // check array rhs structure
248  else if(can_cast_expr<array_exprt>(rhs))
249  {
250  // seems no check is required.
251  }
252  // check array rhs structure
253  else if(can_cast_expr<array_list_exprt>(rhs))
254  {
255  // seems no check is required.
256  }
257  // check constant rhs structure
258  else if(const auto constant_expr = expr_try_dynamic_cast<constant_exprt>(rhs))
259  {
261  vm,
262  check_constant_structure(*constant_expr),
263  "RHS",
264  rhs.pretty(),
265  "Expecting a constant expression to have no operands and a non-empty "
266  "value.");
267  }
268  // check pointer constant rhs structure
269  else if(
270  const auto constant_expr =
271  expr_try_dynamic_cast<annotated_pointer_constant_exprt>(rhs))
272  {
274  vm,
276  "RHS",
277  rhs.pretty(),
278  "Expecting the operand of an annotated pointer constant expression "
279  "to be a constant, address_of, or plus expression.");
280  }
281  // check byte extract rhs structure
282  else if(const auto byte = expr_try_dynamic_cast<byte_extract_exprt>(rhs))
283  {
284  check_rhs_assumptions(simplify_expr(byte->op(), ns), ns, vm);
286  vm,
287  can_cast_expr<constant_exprt>(simplify_expr(byte->offset(), ns)),
288  "RHS",
289  rhs.pretty(),
290  "Expecting a byte extract with constant index.");
291  }
292  else
293  {
295  vm,
296  false,
297  "RHS",
298  rhs.pretty(),
299  "Expression does not meet any trace assumptions.");
300  }
301 }
302 
304  const goto_trace_stept &step,
305  const namespacet &ns,
306  const validation_modet vm)
307 {
308  if(!step.is_assignment() && !step.is_decl())
309  return;
312 }
313 
315  const goto_tracet &trace,
316  const namespacet &ns,
317  const messaget &log,
318  const bool run_check,
319  const validation_modet vm)
320 {
321  if(!run_check)
322  return;
323  for(const auto &step : trace.steps)
324  check_step_assumptions(step, ns, vm);
325  log.status() << "Trace validation successful" << messaget::eom;
326 }
Expression classes for byte-level operators.
bool can_cast_expr< byte_extract_exprt >(const exprt &base)
Operator to return the address of an object.
Definition: pointer_expr.h:540
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
A constant literal expression.
Definition: std_expr.h:3000
const irep_idt & get_value() const
Definition: std_expr.h:3008
bool empty() const
Definition: dstring.h:89
Base class for all expressions.
Definition: expr.h:56
bool has_operands() const
Return true if there is at least one operand.
Definition: expr.h:91
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
Step of the trace of a GOTO program.
Definition: goto_trace.h:50
bool is_assignment() const
Definition: goto_trace.h:55
exprt full_lhs_value
Definition: goto_trace.h:133
bool is_decl() const
Definition: goto_trace.h:65
Trace of a GOTO program.
Definition: goto_trace.h:177
stepst steps
Definition: goto_trace.h:180
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:482
Extract member of struct or union.
Definition: std_expr.h:2854
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
static eomt eom
Definition: message.h:289
exprt & op0()
Definition: std_expr.h:932
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
String type.
Definition: std_types.h:966
Struct constructor from list of elements.
Definition: std_expr.h:1877
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:193
Deprecated expression utility functions.
Traces of GOTO Programs.
bool valid_lhs_expr_high_level(const exprt &lhs)
static void check_step_assumptions(const goto_trace_stept &step, const namespacet &ns, const validation_modet vm)
bool check_address_structure(const address_of_exprt &address)
bool valid_rhs_expr_high_level(const exprt &rhs)
bool check_member_structure(const member_exprt &expr)
static bool check_annotated_pointer_constant_structure(const annotated_pointer_constant_exprt &constant_expr)
bool check_index_structure(const exprt &index_expr)
bool check_symbol_structure(const exprt &expr)
static bool may_be_lvalue(const exprt &expr)
void check_trace_assumptions(const goto_tracet &trace, const namespacet &ns, const messaget &log, const bool run_check, const validation_modet vm)
Checks that the structure of each step of the trace matches certain criteria.
bool check_constant_structure(const constant_exprt &constant_expr)
static void check_lhs_assumptions(const exprt &lhs, const namespacet &ns, const validation_modet vm)
static void check_rhs_assumptions(const exprt &rhs, const namespacet &ns, const validation_modet vm)
std::optional< symbol_exprt > get_inner_symbol_expr(exprt expr)
Recursively extracts the first operand of an expression until it reaches a symbol and returns it,...
bool can_evaluate_to_constant(const exprt &expression)
bool check_struct_structure(const struct_exprt &expr)
double log(double x)
Definition: math.c:2776
API to expression classes for Pointers.
bool can_cast_expr< annotated_pointer_constant_exprt >(const exprt &base)
bool can_cast_expr< address_of_exprt >(const exprt &base)
Definition: pointer_expr.h:561
exprt simplify_expr(exprt src, const namespacet &ns)
API to expression classes.
bool can_cast_expr< typecast_exprt >(const exprt &base)
Definition: std_expr.h:2091
bool can_cast_expr< struct_exprt >(const exprt &base)
Definition: std_expr.h:1889
bool can_cast_expr< mult_exprt >(const exprt &base)
Definition: std_expr.h:1121
bool can_cast_expr< plus_exprt >(const exprt &base)
Definition: std_expr.h:1025
bool can_cast_expr< constant_exprt >(const exprt &base)
Definition: std_expr.h:3039
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:987
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:715
bool can_cast_expr< index_exprt >(const exprt &base)
Definition: std_expr.h:1522
bool can_cast_expr< symbol_exprt >(const exprt &base)
Definition: std_expr.h:256
bool can_cast_expr< member_exprt >(const exprt &base)
Definition: std_expr.h:2930
bool can_cast_expr< array_list_exprt >(const exprt &base)
Definition: std_expr.h:1706
bool can_cast_expr< array_exprt >(const exprt &base)
Definition: std_expr.h:1654
#define DATA_CHECK_WITH_DIAGNOSTICS(vm, condition, message,...)
Definition: validate.h:37
validation_modet