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 
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)) ||
83 }
84 
85 bool check_index_structure(const exprt &index_expr)
86 {
87  return (can_cast_expr<index_exprt>(index_expr) ||
88  can_cast_expr<byte_extract_exprt>(index_expr)) &&
89  index_expr.operands().size() == 2 &&
90  check_symbol_structure(to_binary_expr(index_expr).op0()) &&
91  can_evaluate_to_constant(to_binary_expr(index_expr).op1());
92 }
93 
95 {
96  if(!expr.has_operands())
97  return false;
98  if(const auto sub_struct = expr_try_dynamic_cast<struct_exprt>(expr.op0()))
99  check_struct_structure(*sub_struct);
100  else if(
103  {
104  return false;
105  }
106  if(
107  expr.operands().size() > 1 && std::any_of(
108  ++expr.operands().begin(),
109  expr.operands().end(),
110  [&](const exprt &operand) {
111  return operand.id() != ID_constant &&
112  operand.id() !=
113  ID_annotated_pointer_constant;
114  }))
115  {
116  return false;
117  }
118  return true;
119 }
120 
122 {
123  const auto symbol_expr = get_inner_symbol_expr(address);
124  return symbol_expr && check_symbol_structure(*symbol_expr);
125 }
126 
127 bool check_constant_structure(const constant_exprt &constant_expr)
128 {
129  if(constant_expr.has_operands())
130  return false;
131  // All value types used in Java must be non-empty except string_typet:
132  return !constant_expr.get_value().empty() ||
133  constant_expr.type() == string_typet();
134 }
135 
137  const annotated_pointer_constant_exprt &constant_expr)
138 {
139  const auto &operand = skip_typecast(constant_expr.symbolic_pointer());
140  return can_cast_expr<constant_exprt>(operand) ||
142  can_cast_expr<plus_exprt>(operand);
143 }
144 
146  const exprt &lhs,
147  const namespacet &ns,
148  const validation_modet vm)
149 {
151  vm,
153  "LHS",
154  lhs.pretty(),
155  "Unsupported expression.");
156  // check member lhs structure
157  if(const auto member = expr_try_dynamic_cast<member_exprt>(lhs))
158  {
160  vm,
161  check_member_structure(*member),
162  "LHS",
163  lhs.pretty(),
164  "Expecting a member with nested symbol operand.");
165  }
166  // check symbol lhs structure
167  else if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(lhs))
168  {
170  vm,
171  check_symbol_structure(*symbol),
172  "LHS",
173  lhs.pretty(),
174  "Expecting a symbol with non-empty identifier.");
175  }
176  // check index lhs structure
177  else if(const auto index = expr_try_dynamic_cast<index_exprt>(lhs))
178  {
180  vm,
181  check_index_structure(*index),
182  "LHS",
183  lhs.pretty(),
184  "Expecting an index expression with a symbol array and constant or "
185  "symbol index value.");
186  }
187  // check byte extract lhs structure
188  else if(const auto byte = expr_try_dynamic_cast<byte_extract_exprt>(lhs))
189  {
191  vm,
192  check_index_structure(*byte),
193  "LHS",
194  lhs.pretty(),
195  "Expecting a byte extract expression with a symbol array and constant or "
196  "symbol index value.");
197  }
198  else
199  {
201  vm,
202  false,
203  "LHS",
204  lhs.pretty(),
205  "Expression does not meet any trace assumptions.");
206  }
207 }
208 
210  const exprt &rhs,
211  const namespacet &ns,
212  const validation_modet vm)
213 {
215  vm,
217  "RHS",
218  rhs.pretty(),
219  "Unsupported expression.");
220  // check address_of rhs structure (String only)
221  if(const auto address = expr_try_dynamic_cast<address_of_exprt>(rhs))
222  {
224  vm,
225  check_address_structure(*address),
226  "RHS",
227  rhs.pretty(),
228  "Expecting an address of with nested symbol.");
229  }
230  // check symbol rhs structure (String only)
231  else if(const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(rhs))
232  {
234  vm,
235  check_symbol_structure(*symbol_expr),
236  "RHS",
237  rhs.pretty(),
238  "Expecting a symbol with non-empty identifier.");
239  }
240  // check struct rhs structure
241  else if(const auto struct_expr = expr_try_dynamic_cast<struct_exprt>(rhs))
242  {
244  vm,
245  check_struct_structure(*struct_expr),
246  "RHS",
247  rhs.pretty(),
248  "Expecting all non-base class operands to be constants.");
249  }
250  // check array rhs structure
251  else if(can_cast_expr<array_exprt>(rhs))
252  {
253  // seems no check is required.
254  }
255  // check array rhs structure
256  else if(can_cast_expr<array_list_exprt>(rhs))
257  {
258  // seems no check is required.
259  }
260  // check constant rhs structure
261  else if(const auto constant_expr = expr_try_dynamic_cast<constant_exprt>(rhs))
262  {
264  vm,
265  check_constant_structure(*constant_expr),
266  "RHS",
267  rhs.pretty(),
268  "Expecting a constant expression to have no operands and a non-empty "
269  "value.");
270  }
271  // check pointer constant rhs structure
272  else if(
273  const auto constant_expr =
274  expr_try_dynamic_cast<annotated_pointer_constant_exprt>(rhs))
275  {
277  vm,
279  "RHS",
280  rhs.pretty(),
281  "Expecting the operand of an annotated pointer constant expression "
282  "to be a constant, address_of, or plus expression.");
283  }
284  // check byte extract rhs structure
285  else if(const auto byte = expr_try_dynamic_cast<byte_extract_exprt>(rhs))
286  {
288  vm,
289  byte->operands().size() == 2,
290  "RHS",
291  rhs.pretty(),
292  "Expecting a byte extract with two operands.");
294  vm,
296  "RHS",
297  rhs.pretty(),
298  "Expecting a byte extract with constant value.");
300  vm,
301  can_cast_expr<constant_exprt>(simplify_expr(byte->offset(), ns)),
302  "RHS",
303  rhs.pretty(),
304  "Expecting a byte extract with constant index.");
305  }
306  else
307  {
309  vm,
310  false,
311  "RHS",
312  rhs.pretty(),
313  "Expression does not meet any trace assumptions.");
314  }
315 }
316 
318  const goto_trace_stept &step,
319  const namespacet &ns,
320  const validation_modet vm)
321 {
322  if(!step.is_assignment() && !step.is_decl())
323  return;
326 }
327 
329  const goto_tracet &trace,
330  const namespacet &ns,
331  const messaget &log,
332  const bool run_check,
333  const validation_modet vm)
334 {
335  if(!run_check)
336  return;
337  for(const auto &step : trace.steps)
338  check_step_assumptions(step, ns, vm);
339  log.status() << "Trace validation successful" << messaget::eom;
340 }
messaget
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
can_cast_expr< symbol_exprt >
bool can_cast_expr< symbol_exprt >(const exprt &base)
Definition: std_expr.h:206
check_trace_assumptions
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.
Definition: java_trace_validation.cpp:328
goto_trace_stept::full_lhs_value
exprt full_lhs_value
Definition: goto_trace.h:132
can_cast_expr< array_list_exprt >
bool can_cast_expr< array_list_exprt >(const exprt &base)
Definition: std_expr.h:1644
skip_typecast
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
Definition: expr_util.cpp:217
get_inner_symbol_expr
optionalt< symbol_exprt > get_inner_symbol_expr(exprt expr)
Recursively extracts the first operand of an expression until it reaches a symbol and returns it,...
Definition: java_trace_validation.cpp:39
check_step_assumptions
static void check_step_assumptions(const goto_trace_stept &step, const namespacet &ns, const validation_modet vm)
Definition: java_trace_validation.cpp:317
can_cast_expr< address_of_exprt >
bool can_cast_expr< address_of_exprt >(const exprt &base)
Definition: pointer_expr.h:392
irept::pretty
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:495
java_trace_validation.h
messaget::status
mstreamt & status() const
Definition: message.h:414
check_struct_structure
bool check_struct_structure(const struct_exprt &expr)
Definition: java_trace_validation.cpp:94
valid_lhs_expr_high_level
bool valid_lhs_expr_high_level(const exprt &lhs)
Definition: java_trace_validation.cpp:60
check_annotated_pointer_constant_structure
static bool check_annotated_pointer_constant_structure(const annotated_pointer_constant_exprt &constant_expr)
Definition: java_trace_validation.cpp:136
check_symbol_structure
bool check_symbol_structure(const exprt &expr)
Definition: java_trace_validation.cpp:21
goto_tracet::steps
stepst steps
Definition: goto_trace.h:178
exprt
Base class for all expressions.
Definition: expr.h:55
DATA_CHECK_WITH_DIAGNOSTICS
#define DATA_CHECK_WITH_DIAGNOSTICS(vm, condition, message,...)
Definition: validate.h:37
messaget::eom
static eomt eom
Definition: message.h:297
goto_trace_stept
Step of the trace of a GOTO program.
Definition: goto_trace.h:49
can_cast_expr< byte_extract_exprt >
bool can_cast_expr< byte_extract_exprt >(const exprt &base)
Definition: byte_operators.h:51
can_cast_expr< array_exprt >
bool can_cast_expr< array_exprt >(const exprt &base)
Definition: std_expr.h:1592
can_cast_expr< member_exprt >
bool can_cast_expr< member_exprt >(const exprt &base)
Definition: std_expr.h:2870
goto_trace_stept::is_decl
bool is_decl() const
Definition: goto_trace.h:65
check_lhs_assumptions
static void check_lhs_assumptions(const exprt &lhs, const namespacet &ns, const validation_modet vm)
Definition: java_trace_validation.cpp:145
to_binary_expr
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition: std_expr.h:660
goto_trace_stept::is_assignment
bool is_assignment() const
Definition: goto_trace.h:55
goto_trace.h
struct_exprt
Struct constructor from list of elements.
Definition: std_expr.h:1818
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
byte_operators.h
Expression classes for byte-level operators.
check_index_structure
bool check_index_structure(const exprt &index_expr)
Definition: java_trace_validation.cpp:85
can_evaluate_to_constant
bool can_evaluate_to_constant(const exprt &expression)
Definition: java_trace_validation.cpp:78
exprt::has_operands
bool has_operands() const
Return true if there is at least one operand.
Definition: expr.h:91
can_cast_expr< plus_exprt >
bool can_cast_expr< plus_exprt >(const exprt &base)
Definition: std_expr.h:970
pointer_expr.h
goto_trace_stept::full_lhs
exprt full_lhs
Definition: goto_trace.h:126
check_member_structure
bool check_member_structure(const member_exprt &expr)
Definition: java_trace_validation.cpp:52
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
check_rhs_assumptions
static void check_rhs_assumptions(const exprt &rhs, const namespacet &ns, const validation_modet vm)
Definition: java_trace_validation.cpp:209
validation_modet
validation_modet
Definition: validation_mode.h:12
dstringt::empty
bool empty() const
Definition: dstring.h:88
annotated_pointer_constant_exprt
Pointer-typed bitvector constant annotated with the pointer expression that the bitvector is the nume...
Definition: pointer_expr.h:817
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
check_address_structure
bool check_address_structure(const address_of_exprt &address)
Definition: java_trace_validation.cpp:121
simplify_expr.h
can_cast_expr< index_exprt >
bool can_cast_expr< index_exprt >(const exprt &base)
Definition: std_expr.h:1462
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
expr_util.h
Deprecated expression utility functions.
valid_rhs_expr_high_level
bool valid_rhs_expr_high_level(const exprt &rhs)
Definition: java_trace_validation.cpp:67
may_be_lvalue
static bool may_be_lvalue(const exprt &expr)
Definition: java_trace_validation.cpp:29
string_typet
String type.
Definition: std_types.h:912
goto_tracet
Trace of a GOTO program.
Definition: goto_trace.h:174
can_cast_expr< annotated_pointer_constant_exprt >
bool can_cast_expr< annotated_pointer_constant_exprt >(const exprt &base)
Definition: pointer_expr.h:850
can_cast_expr< typecast_exprt >
bool can_cast_expr< typecast_exprt >(const exprt &base)
Definition: std_expr.h:2035
check_constant_structure
bool check_constant_structure(const constant_exprt &constant_expr)
Definition: java_trace_validation.cpp:127
can_cast_expr< constant_exprt >
bool can_cast_expr< constant_exprt >(const exprt &base)
Definition: std_expr.h:2976
exprt::operands
operandst & operands()
Definition: expr.h:94
address_of_exprt
Operator to return the address of an object.
Definition: pointer_expr.h:370
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
multi_ary_exprt::op0
exprt & op0()
Definition: std_expr.h:877
can_cast_expr< struct_exprt >
bool can_cast_expr< struct_exprt >(const exprt &base)
Definition: std_expr.h:1831
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
std_expr.h
constant_exprt::get_value
const irep_idt & get_value() const
Definition: std_expr.h:2950
annotated_pointer_constant_exprt::symbolic_pointer
exprt & symbolic_pointer()
Definition: pointer_expr.h:838