Skip to content

Commit

Permalink
Function pointer removal: create fall-back function call
Browse files Browse the repository at this point in the history
The case where a function pointer matches none of the candidate
functions now introduces a call to a new function. No implementation of
this function is provided, leaving the choice to the user in case they
choose to use goto-instrument's generate-function-body.

As doing so requires updates to goto_functions by the caller, two unused
API variants of remove_function_pointers were removed.

Fixes: #6983
  • Loading branch information
tautschnig committed Jul 5, 2022
1 parent c00319e commit 8c9b603
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 151 deletions.
12 changes: 7 additions & 5 deletions regression/cbmc/Function_Pointer18/test.desc
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
CORE
main.c

^EXIT=0$
^SIGNAL=0$
\[f2.assertion.1\] line [0-9]+ assertion 0: SUCCESS
\[main.assertion.1\] line [0-9]+ assertion x == 1: SUCCESS
^\*\*\*\* WARNING: no body for function main::fptr_call
^\*\*\*\* WARNING: no body for function main::fptr_call\$0
\[f2.assertion.1\] line [0-9]+ assertion 0: FAILURE
\[main.assertion.1\] line [0-9]+ assertion x == 1: FAILURE
\[main.assertion.2\] line [0-9]+ assertion x == 2: SUCCESS
^VERIFICATION SUCCESSFUL$
^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
26 changes: 26 additions & 0 deletions regression/cbmc/Function_Pointer20/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <assert.h>

struct PtrWrapper
{
char *value_c;
};

void fn(struct PtrWrapper wrapper)
{
assert(wrapper.value_c == 'B');
}

void indirect(int (*fn_ptr)(char *), char *data)
{
fn_ptr(data);
assert(0);
}

int main()
{
struct PtrWrapper wrapper;
wrapper.value_c = 'A';

int (*alias)(char *) = (int (*)(char *))fn;
indirect(alias, &wrapper.value_c);
}
10 changes: 10 additions & 0 deletions regression/cbmc/Function_Pointer20/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CORE
main.c

^\*\*\*\* WARNING: no body for function indirect::fptr_call
^\[indirect.assertion.1\] line 16 assertion 0: FAILURE$
^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
^warning: ignoring
4 changes: 1 addition & 3 deletions regression/cbmc/Function_Pointer_Init_No_Candidate/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ typedef int (*other_function_type)(int n);

void foo(other_function_type other_function)
{
// returning from the function call is unreachable -> the following assertion
// should succeed
// requesting `pointer-check` will then catch the fact that there is no valid
// requesting `pointer-check` will catch the fact that there is no valid
// candidate function to call resulting in an invalid function pointer
// failure
assert(other_function(4) > 5);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CORE
main.c
--function foo --pointer-check
^\[foo.assertion.\d+\] line \d+ assertion other_function\(4\) > 5: SUCCESS$
^\[foo.assertion.\d+\] line \d+ assertion other_function\(4\) > 5: FAILURE$
^\[foo.pointer_dereference.\d+\] line \d+ no candidates for dereferenced function pointer: FAILURE$
^EXIT=10$
^SIGNAL=0$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ main.c
^main::1::fun1 \(\) -> value-set-begin: ptr ->\(f\) :value-set-end
^main::1::fun2_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
^main::1::fun3_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
^fun_global_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
^fun_global_show \(\) -> value-set-begin: TOP :value-set-end
^EXIT=0$
^SIGNAL=0$
--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ test.c
^SIGNAL=0$
^file test.c line 19 function main: replacing function pointer by 0 possible targets$
--
--
This test checks that the value-set-fi-based function pointer removal
precisely identifies the function to call for a particular function pointer
call.
15 changes: 12 additions & 3 deletions src/goto-instrument/value_set_fi_fp_removal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void value_set_fi_fp_removal(
message.status() << "Instrumenting" << messaget::eom;

// now replace aliases by addresses
std::list<irep_idt> fall_back_fns;
for(auto &f : goto_model.goto_functions.function_map)
{
for(auto target = f.second.body.instructions.begin();
Expand Down Expand Up @@ -69,18 +70,26 @@ void value_set_fi_fp_removal(

if(functions.size() > 0)
{
remove_function_pointer(
fall_back_fns.push_back(remove_function_pointer(
message_handler,
goto_model.symbol_table,
f.second.body,
f.first,
target,
functions,
true);
true));
}
}
}
}
}
goto_model.goto_functions.update();

for(const auto &id : fall_back_fns)
{
goto_model.goto_functions.function_map[id].set_parameter_identifiers(
to_code_type(ns.lookup(id).type));
}

if(!fall_back_fns.empty())
goto_model.goto_functions.update();
}
Loading

0 comments on commit 8c9b603

Please sign in to comment.