Skip to content

Commit f3311a1

Browse files
committed
C++: Support 'ReturnValue' in both sources and sinks.
1 parent ea70e5c commit f3311a1

1 file changed

Lines changed: 66 additions & 12 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ private class ConversionCall extends Call {
139139
private module Input2 implements Impl::Private::InputSig2 {
140140
private import codeql.util.Void
141141

142+
pragma[nomagic]
143+
private predicate hasFunctionAndIndirectionIndex(
144+
Function f, int indirectionIndex, Ssa::ExplicitDefinition def
145+
) {
146+
def.getFunction() = f and
147+
def.getSourceVariable().getIRVariable() instanceof IRReturnVariable and
148+
def.getIndirectionIndex() = indirectionIndex
149+
}
150+
151+
/** Holds if `def` defines `e` as a returned value with return kind `rk`. */
152+
bindingset[rk, e]
153+
private predicate isReturnExpr(Function f, ReturnKind rk, Expr e) {
154+
exists(Ssa::ExplicitDefinition def |
155+
hasFunctionAndIndirectionIndex(f, rk.getIndirectionIndex(), def) and
156+
e =
157+
def.getAssignedInstruction()
158+
.(StoreInstruction)
159+
.getSourceValue()
160+
.getUnconvertedResultExpression()
161+
)
162+
}
163+
142164
class SourceSinkReportingElement extends Element {
143165
SourceSinkReportingElement() { this instanceof Expr or this instanceof Parameter }
144166

@@ -159,13 +181,25 @@ private module Input2 implements Impl::Private::InputSig2 {
159181
result = this.(ConversionCall).getQualifier().(LambdaExpression).getLambdaFunction()
160182
}
161183

184+
/** Gets the function invoked when this element is used as a callback. */
185+
private Function getCallbackFunction() {
186+
// Taking the address of a function
187+
result = this.(FunctionAccess).getTarget()
188+
or
189+
// Passing an object with an overloaded `operator()`
190+
result = this.getOperatorCallFunction()
191+
}
192+
162193
SourceSinkReportingElement getASuccessor(Impl::Private::SummaryComponent sc) {
163-
exists(ParameterPosition pos | sc = Impl::Private::SummaryComponent::parameter(pos) |
164-
// Taking the address of a function
165-
result = pos.getParameter(this.(FunctionAccess).getTarget())
194+
exists(Function f | f = this.getCallbackFunction() |
195+
exists(ParameterPosition pos | sc = Impl::Private::SummaryComponent::parameter(pos) |
196+
result = pos.getParameter(f)
197+
)
166198
or
167-
// Passing an object with an overloaded `operator()`
168-
result = pos.getParameter(this.getOperatorCallFunction())
199+
exists(ReturnKind rk |
200+
sc = Impl::Private::SummaryComponent::return(rk) and
201+
isReturnExpr(f, rk, result)
202+
)
169203
)
170204
}
171205
}
@@ -197,6 +231,12 @@ private module Input2 implements Impl::Private::InputSig2 {
197231
pragma[only_bind_out](rk.getIndirectionIndex())
198232
}
199233

234+
pragma[nomagic]
235+
private predicate hasKindAndEnclosingFunction(Function f, ReturnKind rk, ReturnNode r) {
236+
r.getEnclosingCallable().asSourceCallable() = f and
237+
r.getKind() = rk
238+
}
239+
200240
bindingset[e, sc]
201241
Node getSourceDataFlowNode(SourceSinkReportingElement e, Impl::Private::SummaryComponent sc) {
202242
exists(DataFlowCall call |
@@ -210,14 +250,22 @@ private module Input2 implements Impl::Private::InputSig2 {
210250
result.(PostUpdateNode).getPreUpdateNode().asIndirectExpr(pos.getIndirectionIndex()) = e
211251
)
212252
or
213-
exists(ReturnKind rk |
214-
sc = Impl::Private::SummaryComponent::return(rk) and
215-
e = call.asCallInstruction().getUnconvertedResultExpression()
216-
|
217-
rk.getIndirectionIndex() = 0 and
218-
simpleOutNode(result, call.asCallInstruction())
253+
exists(ReturnKind rk | sc = Impl::Private::SummaryComponent::return(rk) |
254+
// When `e` is a call the node becomes an `OutNode`.
255+
e = call.asCallInstruction().getUnconvertedResultExpression() and
256+
(
257+
rk.getIndirectionIndex() = 0 and
258+
simpleOutNode(result, call.asCallInstruction())
259+
or
260+
result = getIndirectReturn(call.asCallInstruction(), rk)
261+
)
219262
or
220-
result = getIndirectReturn(call.asCallInstruction(), rk)
263+
exists(Function f |
264+
// And when `e` is the returned expression from a function the node
265+
// is the `ReturnNode`.
266+
isReturnExpr(f, rk, e) and
267+
hasKindAndEnclosingFunction(f, rk, result)
268+
)
221269
)
222270
)
223271
or
@@ -246,6 +294,12 @@ private module Input2 implements Impl::Private::InputSig2 {
246294
pos.getArgument(call.getUnconvertedResultExpression()) = e and
247295
result.(ArgumentNode).sourceArgumentOf(call, pos)
248296
)
297+
or
298+
exists(Function f, ReturnKind rk |
299+
sc = Impl::Private::SummaryComponent::return(rk) and
300+
isReturnExpr(f, rk, e) and
301+
hasKindAndEnclosingFunction(f, rk, result)
302+
)
249303
}
250304
}
251305

0 commit comments

Comments
 (0)