cprover
simple_method_stubbing.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Simple Java method stubbing
4 
5 Author: Diffblue Ltd.
6 
7 \*******************************************************************/
8 
11 
12 #include "simple_method_stubbing.h"
13 
16 
17 #include <util/fresh_symbol.h>
18 #include <util/invariant_utils.h>
19 #include <util/namespace.h>
20 #include <util/std_code.h>
21 #include <util/std_expr.h>
22 
24 {
25 public:
27  symbol_table_baset &_symbol_table,
28  bool _assume_non_null,
29  const java_object_factory_parameterst &_object_factory_parameters,
30  message_handlert &_message_handler)
31  : symbol_table(_symbol_table),
32  assume_non_null(_assume_non_null),
33  object_factory_parameters(_object_factory_parameters),
34  message_handler(_message_handler)
35  {
36  }
37 
39  const typet &expected_type,
40  const exprt &ptr,
41  const source_locationt &loc,
42  const irep_idt &function_id,
43  code_blockt &parent_block,
44  unsigned insert_before_index,
45  bool is_constructor,
46  bool update_in_place);
47 
48  void create_method_stub(symbolt &symbol);
49 
50  void check_method_stub(const irep_idt &);
51 
52 protected:
57 };
58 
80  const typet &expected_type,
81  const exprt &ptr,
82  const source_locationt &loc,
83  const irep_idt &function_id,
84  code_blockt &parent_block,
85  const unsigned insert_before_index,
86  const bool is_constructor,
87  const bool update_in_place)
88 {
89  // At this point we know 'ptr' points to an opaque-typed object.
90  // We should nondet-initialize it and insert the instructions *after*
91  // the offending call at (*parent_block)[insert_before_index].
92 
94  expected_type.id() == ID_pointer,
95  "Nondet initializer result type: expected a pointer",
96  expected_type);
97 
99 
100  const auto &expected_base = ns.follow(expected_type.subtype());
101  if(expected_base.id() != ID_struct)
102  return;
103 
104  const exprt cast_ptr =
105  make_clean_pointer_cast(ptr, to_pointer_type(expected_type), ns);
106 
107  exprt to_init = cast_ptr;
108  // If it's a constructor the thing we're constructing has already
109  // been allocated by this point.
110  if(is_constructor)
111  to_init = dereference_exprt(to_init, expected_base);
112 
114  if(assume_non_null)
115  parameters.min_null_tree_depth = 1;
116 
117  // Generate new instructions.
118  code_blockt new_instructions;
119  parameters.function_id = function_id;
121  to_init,
122  new_instructions,
123  symbol_table,
124  loc,
127  parameters,
130 
131  // Insert new_instructions into parent block.
132  if(!new_instructions.statements().empty())
133  {
134  auto insert_position = parent_block.statements().begin();
135  std::advance(insert_position, insert_before_index);
136  parent_block.statements().insert(
137  insert_position,
138  new_instructions.statements().begin(),
139  new_instructions.statements().end());
140  }
141 }
142 
148 {
149  code_blockt new_instructions;
150  const java_method_typet &required_type = to_java_method_type(symbol.type);
151 
152  // synthetic source location that contains the opaque function name only
153  source_locationt synthesized_source_location;
154  synthesized_source_location.set_function(symbol.name);
155 
156  // Initialize the return value or `this` parameter under construction.
157  // Note symbol.type is required_type, but with write access
158  // Probably required_type should not be const
159  const bool is_constructor = required_type.get_is_constructor();
160  if(is_constructor)
161  {
162  const auto &this_argument = required_type.parameters()[0];
163  const typet &this_type = this_argument.type();
164  symbolt &init_symbol = get_fresh_aux_symbol(
165  this_type,
166  id2string(symbol.name),
167  "to_construct",
168  synthesized_source_location,
169  ID_java,
170  symbol_table);
171  const symbol_exprt &init_symbol_expression = init_symbol.symbol_expr();
172  code_assignt get_argument(
173  init_symbol_expression, symbol_exprt(this_argument.get_identifier()));
174  get_argument.add_source_location() = synthesized_source_location;
175  new_instructions.add(get_argument);
177  this_type,
178  init_symbol_expression,
179  synthesized_source_location,
180  symbol.name,
181  new_instructions,
182  1,
183  true,
184  false);
185  }
186  else
187  {
188  const typet &required_return_type = required_type.return_type();
189  if(required_return_type != empty_typet())
190  {
191  symbolt &to_return_symbol = get_fresh_aux_symbol(
192  required_return_type,
193  id2string(symbol.name),
194  "to_return",
195  synthesized_source_location,
196  ID_java,
197  symbol_table);
198  const exprt &to_return = to_return_symbol.symbol_expr();
199  if(to_return_symbol.type.id() != ID_pointer)
200  {
202  if(assume_non_null)
203  parameters.min_null_tree_depth = 1;
204 
206  to_return,
207  new_instructions,
208  symbol_table,
210  false,
211  allocation_typet::LOCAL, // Irrelevant as type is primitive
212  parameters,
214  }
215  else
217  required_return_type,
218  to_return,
219  synthesized_source_location,
220  symbol.name,
221  new_instructions,
222  0,
223  false,
224  false);
225  new_instructions.add(code_returnt(to_return));
226  }
227  }
228 
229  symbol.value = new_instructions;
230 }
231 
236 {
237  const symbolt &sym = *symbol_table.lookup(symname);
238  if(!sym.is_type && sym.value.id() == ID_nil &&
239  sym.type.id() == ID_code &&
240  // do not stub internal locking calls as 'create_method_stub' does not
241  // automatically create the appropriate symbols for the formal parameters.
242  // This means that symex will (rightfully) crash when it encounters the
243  // function call as it will not be able to find symbols for the fromal
244  // parameters.
245  sym.name !=
246  "java::java.lang.Object.monitorenter:(Ljava/lang/Object;)V" &&
247  sym.name !=
248  "java::java.lang.Object.monitorexit:(Ljava/lang/Object;)V")
249  {
251  }
252 }
253 
255  const irep_idt &function_name,
256  symbol_table_baset &symbol_table,
257  bool assume_non_null,
258  const java_object_factory_parameterst &object_factory_parameters,
259  message_handlert &message_handler)
260 {
261  java_simple_method_stubst stub_generator(
262  symbol_table, assume_non_null, object_factory_parameters, message_handler);
263 
264  stub_generator.check_method_stub(function_name);
265 }
266 
277  symbol_table_baset &symbol_table,
278  bool assume_non_null,
279  const java_object_factory_parameterst &object_factory_parameters,
280  message_handlert &message_handler)
281 {
282  // The intent here is to apply stub_generator.check_method_stub() to
283  // all the identifiers in the symbol table. However this method may alter the
284  // symbol table and iterating over a container which is being modified has
285  // undefined behaviour. Therefore in order for this to work reliably, we must
286  // take a copy of the identifiers in the symbol table and iterate over that,
287  // instead of iterating over the symbol table itself.
288  std::vector<irep_idt> identifiers;
289  identifiers.reserve(symbol_table.symbols.size());
290  for(const auto &symbol : symbol_table)
291  identifiers.push_back(symbol.first);
292 
293  java_simple_method_stubst stub_generator(
294  symbol_table, assume_non_null, object_factory_parameters, message_handler);
295 
296  for(const auto &identifier : identifiers)
297  {
298  stub_generator.check_method_stub(identifier);
299  }
300 }
#define loc()
The type of an expression, extends irept.
Definition: type.h:27
irep_idt name
The unique identifier.
Definition: symbol.h:40
irep_idt function_id
Function id, used as a prefix for identifiers of temporaries.
void set_function(const irep_idt &function)
void create_method_stub(symbolt &symbol)
Replaces sym&#39;s value with an opaque method stub.
static bool is_constructor(const irep_idt &method_name)
void java_generate_simple_method_stubs(symbol_table_baset &symbol_table, bool assume_non_null, const java_object_factory_parameterst &object_factory_parameters, message_handlert &message_handler)
Generates function stubs for most undefined functions in the symbol table, except as forbidden in jav...
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
This module is responsible for the synthesis of code (in the form of a sequence of codet statements) ...
code_operandst & statements()
Definition: std_code.h:159
virtual symbolt * get_writeable(const irep_idt &name)=0
Find a symbol in the symbol table for read-write access.
Fresh auxiliary symbol creation.
Allocate local stacked objects.
Java simple opaque stub generation.
exprt value
Initial value of symbol.
Definition: symbol.h:34
void create_method_stub_at(const typet &expected_type, const exprt &ptr, const source_locationt &loc, const irep_idt &function_id, code_blockt &parent_block, unsigned insert_before_index, bool is_constructor, bool update_in_place)
Nondet-initialize an object, including allocating referees for reference fields and nondet-initialisi...
java_simple_method_stubst(symbol_table_baset &_symbol_table, bool _assume_non_null, const java_object_factory_parameterst &_object_factory_parameters, message_handlert &_message_handler)
Symbol table entry.
Definition: symbol.h:27
bool get_is_constructor() const
Definition: std_types.h:923
#define INVARIANT_WITH_IREP(CONDITION, DESCRIPTION, IREP)
Equivalent to INVARIANT_STRUCTURED(CONDITION, invariant_failedt, pretty_print_invariant_with_irep(IRE...
const irep_idt & id() const
Definition: irep.h:259
void add(const codet &code)
Definition: std_code.h:189
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
The empty type.
Definition: std_types.h:48
Operator to dereference a pointer.
Definition: std_expr.h:3355
API to expression classes.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:93
const java_object_factory_parameterst & object_factory_parameters
dstringt has one field, an unsigned integer no which is an index into a static table of strings...
Definition: dstring.h:35
const symbolst & symbols
size_t min_null_tree_depth
To force a certain depth of non-null objects.
typet type
Type of symbol.
Definition: symbol.h:31
Allocate dynamic objects (using MALLOC)
const java_method_typet & to_java_method_type(const typet &type)
Definition: java_types.h:338
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with the requested name pattern.
Base class for all expressions.
Definition: expr.h:54
const parameterst & parameters() const
Definition: std_types.h:893
The symbol table base class interface.
JAVA Pointer Casts.
void gen_nondet_init(const exprt &expr, code_blockt &init_code, symbol_table_baset &symbol_table, const source_locationt &loc, bool skip_classid, allocation_typet alloc_type, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, update_in_placet update_in_place)
Initializes a primitive-typed or reference-typed object tree rooted at expr, allocating child objects...
source_locationt & add_source_location()
Definition: expr.h:233
A codet representing sequential composition of program statements.
Definition: std_code.h:150
Expression to hold a symbol (variable)
Definition: std_expr.h:143
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: std_types.h:1544
codet representation of a "return from a function" statement.
Definition: std_code.h:1191
bool is_type
Definition: symbol.h:61
const typet & subtype() const
Definition: type.h:38
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
const typet & return_type() const
Definition: std_types.h:883
void java_generate_simple_method_stub(const irep_idt &function_name, symbol_table_baset &symbol_table, bool assume_non_null, const java_object_factory_parameterst &object_factory_parameters, message_handlert &message_handler)
A codet representing an assignment in the program.
Definition: std_code.h:256
void check_method_stub(const irep_idt &)
Replaces sym with a function stub per the function above if it is of suitable type.
exprt make_clean_pointer_cast(const exprt &rawptr, const pointer_typet &target_type, const namespacet &ns)