Skip to content

Commit 36edcfe

Browse files
committed
Function pointer removal: create fall-back function call
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
1 parent 365871d commit 36edcfe

File tree

12 files changed

+187
-151
lines changed

12 files changed

+187
-151
lines changed
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
CORE
22
main.c
33

4-
^EXIT=0$
5-
^SIGNAL=0$
6-
\[f2.assertion.1\] line [0-9]+ assertion 0: SUCCESS
7-
\[main.assertion.1\] line [0-9]+ assertion x == 1: SUCCESS
4+
^\*\*\*\* WARNING: no body for function main::fptr_call
5+
^\*\*\*\* WARNING: no body for function main::fptr_call\$0
6+
\[f2.assertion.1\] line [0-9]+ assertion 0: FAILURE
7+
\[main.assertion.1\] line [0-9]+ assertion x == 1: FAILURE
88
\[main.assertion.2\] line [0-9]+ assertion x == 2: SUCCESS
9-
^VERIFICATION SUCCESSFUL$
9+
^VERIFICATION FAILED$
10+
^EXIT=10$
11+
^SIGNAL=0$
1012
--
1113
^warning: ignoring
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
3+
struct PtrWrapper
4+
{
5+
char *value_c;
6+
};
7+
8+
void fn(struct PtrWrapper wrapper)
9+
{
10+
assert(wrapper.value_c == 'B');
11+
}
12+
13+
void indirect(int (*fn_ptr)(char *), char *data)
14+
{
15+
fn_ptr(data);
16+
assert(0);
17+
}
18+
19+
int main()
20+
{
21+
struct PtrWrapper wrapper;
22+
wrapper.value_c = 'A';
23+
24+
int (*alias)(char *) = (int (*)(char *))fn;
25+
indirect(alias, &wrapper.value_c);
26+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
4+
^\*\*\*\* WARNING: no body for function indirect::fptr_call
5+
^\[indirect.assertion.1\] line 16 assertion 0: FAILURE$
6+
^VERIFICATION FAILED$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring

regression/cbmc/Function_Pointer_Init_No_Candidate/main.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ typedef int (*other_function_type)(int n);
44

55
void foo(other_function_type other_function)
66
{
7-
// returning from the function call is unreachable -> the following assertion
8-
// should succeed
9-
// requesting `pointer-check` will then catch the fact that there is no valid
7+
// requesting `pointer-check` will catch the fact that there is no valid
108
// candidate function to call resulting in an invalid function pointer
119
// failure
1210
assert(other_function(4) > 5);

regression/cbmc/Function_Pointer_Init_No_Candidate/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.c
33
--function foo --pointer-check
4-
^\[foo.assertion.\d+\] line \d+ assertion other_function\(4\) > 5: SUCCESS$
4+
^\[foo.assertion.\d+\] line \d+ assertion other_function\(4\) > 5: FAILURE$
55
^\[foo.pointer_dereference.\d+\] line \d+ no candidates for dereferenced function pointer: FAILURE$
66
^EXIT=10$
77
^SIGNAL=0$

regression/goto-analyzer/value-set-function-pointers-simple/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ main.c
1010
^main::1::fun1 \(\) -> value-set-begin: ptr ->\(f\) :value-set-end
1111
^main::1::fun2_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
1212
^main::1::fun3_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
13-
^fun_global_show \(\) -> value-set-begin: ptr ->\(f\), ptr ->\(g\) :value-set-end
13+
^fun_global_show \(\) -> value-set-begin: TOP :value-set-end
1414
^EXIT=0$
1515
^SIGNAL=0$
1616
--

regression/goto-instrument/value-set-fi-fp-removal4/test.desc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test.c
55
^SIGNAL=0$
66
^file test.c line 20 function main: replacing function pointer by 2 possible targets$
77
--
8+
--
89
This test checks that the value-set-fi-based function pointer removal
910
precisely identifies the function to call for a particular function pointer
1011
call.

regression/goto-instrument/value-set-fi-fp-removal5/test.desc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test.c
55
^SIGNAL=0$
66
^file test.c line 19 function main: replacing function pointer by 0 possible targets$
77
--
8+
--
89
This test checks that the value-set-fi-based function pointer removal
910
precisely identifies the function to call for a particular function pointer
1011
call.

src/goto-instrument/value_set_fi_fp_removal.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ void value_set_fi_fp_removal(
3131
message.status() << "Instrumenting" << messaget::eom;
3232

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

7071
if(functions.size() > 0)
7172
{
72-
remove_function_pointer(
73+
fall_back_fns.push_back(remove_function_pointer(
7374
message_handler,
7475
goto_model.symbol_table,
7576
f.second.body,
7677
f.first,
7778
target,
7879
functions,
79-
true);
80+
true));
8081
}
8182
}
8283
}
8384
}
8485
}
85-
goto_model.goto_functions.update();
86+
87+
for(const auto &id : fall_back_fns)
88+
{
89+
goto_model.goto_functions.function_map[id].set_parameter_identifiers(
90+
to_code_type(ns.lookup(id).type));
91+
}
92+
93+
if(!fall_back_fns.empty())
94+
goto_model.goto_functions.update();
8695
}

0 commit comments

Comments
 (0)