Skip to content

Commit 3e56e23

Browse files
committed
goto symex now handles function pointers
1 parent 80186e3 commit 3e56e23

File tree

3 files changed

+59
-40
lines changed

3 files changed

+59
-40
lines changed

src/goto-programs/process_goto_program.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ bool process_goto_program(
3838
string_instrumentation(goto_model);
3939

4040
// remove function pointers
41-
log.status() << "Removal of function pointers and virtual functions"
42-
<< messaget::eom;
43-
remove_function_pointers(
44-
log.get_message_handler(),
45-
goto_model,
46-
options.get_bool_option("pointer-check"));
41+
if(options.get_bool_option("remove-function-pointers"))
42+
{
43+
log.status() << "Removal of function pointers and virtual functions"
44+
<< messaget::eom;
45+
remove_function_pointers(
46+
log.get_message_handler(),
47+
goto_model,
48+
options.get_bool_option("pointer-check"));
49+
}
4750

4851
mm_io(goto_model);
4952

src/goto-symex/goto_symex.h

+9-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919

2020
class address_of_exprt;
2121
class code_function_callt;
22+
class dereference_exprt;
2223
class function_application_exprt;
2324
class goto_symex_statet;
2425
class path_storaget;
@@ -445,19 +446,19 @@ class goto_symext
445446
/// \param state: Symbolic execution state for current instruction
446447
virtual void symex_end_of_function(statet &);
447448

448-
/// Symbolic execution of a call to a function call.
449+
/// Symbolic execution of a call to a function given via a pointer.
449450
/// \param get_goto_function: The delegate to retrieve function bodies (see
450451
/// \ref get_goto_functiont)
451452
/// \param state: Symbolic execution state for current instruction
452-
/// \param lhs: nil or the lhs of the function call instruction
453-
/// \param function: the symbol of the function to call
454-
/// \param arguments: the arguments of the function call
455-
virtual void symex_function_call_symbol(
453+
/// \param lhs: nil or the lhs of the function call instruction, cleaned
454+
/// \param function: the dereference expression for the function to call, cleaned
455+
/// \param arguments: the arguments of the function call, cleaned
456+
void symex_function_call_post_clean_rec(
456457
const get_goto_functiont &get_goto_function,
457458
statet &state,
458-
const exprt &lhs,
459-
const symbol_exprt &function,
460-
const exprt::operandst &arguments);
459+
const exprt &cleaned_lhs,
460+
const exprt &cleaned_function,
461+
const exprt::operandst &cleaned_arguments);
461462

462463
/// Symbolic execution of a function call by inlining.
463464
/// Records the call in \p target by appending a function call step and:

src/goto-symex/symex_function_call.cpp

+41-26
Original file line numberDiff line numberDiff line change
@@ -178,44 +178,59 @@ void goto_symext::symex_function_call(
178178
{
179179
const exprt &function = instruction.call_function();
180180

181-
// If at some point symex_function_call can support more
182-
// expression ids(), like ID_Dereference, please expand the
183-
// precondition appropriately.
184-
PRECONDITION(function.id() == ID_symbol);
185-
186-
symex_function_call_symbol(
187-
get_goto_function,
188-
state,
189-
instruction.call_lhs(),
190-
to_symbol_expr(instruction.call_function()),
191-
instruction.call_arguments());
192-
}
181+
PRECONDITION(function.id() == ID_symbol || function.id() == ID_dereference);
193182

194-
void goto_symext::symex_function_call_symbol(
195-
const get_goto_functiont &get_goto_function,
196-
statet &state,
197-
const exprt &lhs,
198-
const symbol_exprt &function,
199-
const exprt::operandst &arguments)
200-
{
183+
// clean lhs
201184
exprt cleaned_lhs;
202185

203-
if(lhs.is_nil())
204-
cleaned_lhs = lhs;
186+
if(instruction.call_lhs().is_nil())
187+
cleaned_lhs = nil_exprt();
205188
else
206-
cleaned_lhs = clean_expr(lhs, state, true);
189+
cleaned_lhs = clean_expr(instruction.call_lhs(), state, true);
207190

208-
// no need to clean the function, which is a symbol only
191+
// need to clean the function expression in case it's a dereference
192+
auto cleaned_function = clean_expr(function, state, false);
209193

194+
// clean the arguments
210195
exprt::operandst cleaned_arguments;
211196

212-
for(auto &argument : arguments)
197+
for(auto &argument : instruction.call_arguments())
213198
cleaned_arguments.push_back(clean_expr(argument, state, false));
214199

215200
target.location(state.guard.as_expr(), state.source);
216201

217-
symex_function_call_post_clean(
218-
get_goto_function, state, cleaned_lhs, function, cleaned_arguments);
202+
// We get an if-then-else nest that contains symbols
203+
// in the case of function pointers, and we traverse that recursively.
204+
symex_function_call_post_clean_rec(
205+
get_goto_function, state, cleaned_lhs, cleaned_function, cleaned_arguments);
206+
}
207+
208+
void goto_symext::symex_function_call_post_clean_rec(
209+
const get_goto_functiont &get_goto_function,
210+
statet &state,
211+
const exprt &cleaned_lhs,
212+
const exprt &cleaned_function,
213+
const exprt::operandst &cleaned_arguments)
214+
{
215+
if(cleaned_function.id() == ID_symbol)
216+
{
217+
symex_function_call_post_clean(
218+
get_goto_function,
219+
state,
220+
cleaned_lhs,
221+
to_symbol_expr(cleaned_function),
222+
cleaned_arguments);
223+
}
224+
else if(cleaned_function.id() == ID_if)
225+
{
226+
DATA_INVARIANT_WITH_DIAGNOSTICS(
227+
false, "todo", irep_pretty_diagnosticst(cleaned_function));
228+
}
229+
else
230+
DATA_INVARIANT_WITH_DIAGNOSTICS(
231+
false,
232+
"cleaned function is expected to consist of if and symbol",
233+
irep_pretty_diagnosticst(cleaned_function));
219234
}
220235

221236
void goto_symext::symex_function_call_post_clean(

0 commit comments

Comments
 (0)