Skip to content

Commit 33070cc

Browse files
authored
Merge pull request #2678 from MathiasVP/union-access-global-virtual-dispatch
C++: IR virtual dispatch through union field access
2 parents 0627fad + 5fd1c6f commit 33070cc

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,24 @@ private module VirtualDispatch {
8383
)
8484
or
8585
// Flow through global variable
86-
exists(StoreInstruction store, Variable var |
86+
exists(StoreInstruction store |
8787
store = src.asInstruction() and
88-
var = store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() and
89-
this.flowsFromGlobal(var) and
88+
(
89+
exists(Variable var |
90+
var = store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() and
91+
this.flowsFromGlobal(var)
92+
)
93+
or
94+
exists(Variable var, FieldAccess a |
95+
var = store
96+
.getDestinationAddress()
97+
.(FieldAddressInstruction)
98+
.getObjectAddress()
99+
.(VariableAddressInstruction)
100+
.getASTVariable() and
101+
this.flowsFromGlobalUnionField(var, a)
102+
)
103+
) and
90104
allowFromArg = true
91105
)
92106
}
@@ -97,6 +111,19 @@ private module VirtualDispatch {
97111
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var
98112
)
99113
}
114+
115+
private predicate flowsFromGlobalUnionField(Variable var, FieldAccess a) {
116+
a.getTarget().getDeclaringType() instanceof Union and
117+
exists(LoadInstruction load |
118+
this.flowsFrom(DataFlow::instructionNode(load), _) and
119+
load
120+
.getSourceAddress()
121+
.(FieldAddressInstruction)
122+
.getObjectAddress()
123+
.(VariableAddressInstruction)
124+
.getASTVariable() = var
125+
)
126+
}
100127
}
101128

102129
/** Call through a function pointer. */

cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,46 @@ namespace virtual_inheritance {
130130
sink(topRef.isSource()); // flow [NOT DETECTED]
131131
}
132132
}
133+
134+
union union_with_sink_fun_ptrs {
135+
SinkFunctionType f;
136+
SinkFunctionType g;
137+
} u;
138+
139+
void call_sink_through_union_field_f(SinkFunctionType func) {
140+
func(source());
141+
}
142+
143+
void call_sink_through_union_field_g(SinkFunctionType func) {
144+
func(source());
145+
}
146+
147+
void set_global_union_field_f() {
148+
u.f = callSink;
149+
}
150+
151+
void test_call_sink_through_union() {
152+
set_global_union_field_f();
153+
call_sink_through_union_field_f(u.f);
154+
call_sink_through_union_field_g(u.g);
155+
}
156+
157+
union { union_with_sink_fun_ptrs u; } u2;
158+
159+
void call_sink_through_union_field_u_g(SinkFunctionType func) {
160+
func(source());
161+
}
162+
163+
void call_sink_through_union_field_u_f(SinkFunctionType func) {
164+
func(source());
165+
}
166+
167+
void set_global_union_field_u_f() {
168+
u2.u.f = callSink;
169+
}
170+
171+
void test_call_sink_through_union_2() {
172+
set_global_union_field_u_f();
173+
call_sink_through_union_field_u_f(u2.u.f); // flow [NOT DETECTED]
174+
call_sink_through_union_field_u_g(u2.u.g); // flow [NOT DETECTED]
175+
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
| dispatch.cpp:73:14:73:19 | dispatch.cpp:23:38:23:38 | IR only |
1919
| dispatch.cpp:81:13:81:18 | dispatch.cpp:23:38:23:38 | IR only |
2020
| dispatch.cpp:107:17:107:22 | dispatch.cpp:96:8:96:8 | IR only |
21+
| dispatch.cpp:140:8:140:13 | dispatch.cpp:96:8:96:8 | IR only |
22+
| dispatch.cpp:144:8:144:13 | dispatch.cpp:96:8:96:8 | IR only |
2123
| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only |
2224
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
2325
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |

cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
| dispatch.cpp:55:22:55:30 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
2929
| dispatch.cpp:58:28:58:36 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
3030
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
31+
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:140:8:140:13 | call to source |
32+
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:144:8:144:13 | call to source |
3133
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
3234
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
3335
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |

0 commit comments

Comments
 (0)