Skip to content

Commit ec7b406

Browse files
committed
C++: Generate flow out of parameters whose enclosing function is missing a return statement.
1 parent bfe9ae2 commit ec7b406

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,20 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
360360
override predicate isCertain() { any() }
361361

362362
override predicate hasIndexInBlock(IRBlock block, int index) {
363-
exists(ReturnInstruction return |
363+
// Ideally, this should always be a `ReturnInstruction`, but if
364+
// someone forgets to write a `return` statement in a function
365+
// with a non-void return type we generate an `UnreachedInstruction`.
366+
// In this case we still want to generate flow out of such functions
367+
// if they write to a parameter. So we pick the index of the
368+
// `UnreachedInstruction` as the index of this use.
369+
// Note that a function may have both a `ReturnInstruction` and an
370+
// `UnreachedInstruction`. If that's the case this predicate will
371+
// return multiple results. I don't think this is detrimental to
372+
// performance, however.
373+
exists(Instruction return |
374+
return instanceof ReturnInstruction or
375+
return instanceof UnreachedInstruction
376+
|
364377
block.getInstruction(index) = return and
365378
return.getEnclosingFunction() = p.getFunction()
366379
)

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,21 @@ private class FinalParameterUse extends UseImpl, TFinalParameterUse {
155155
override string toString() { result = p.toString() }
156156

157157
final override predicate hasIndexInBlock(IRBlock block, int index) {
158-
exists(ReturnInstruction return |
159-
block.getInstruction(index + 1) = return and
158+
// Ideally, this should always be a `ReturnInstruction`, but if
159+
// someone forgets to write a `return` statement in a function
160+
// with a non-void return type we generate an `UnreachedInstruction`.
161+
// In this case we still want to generate flow out of such functions
162+
// if they write to a parameter. So we pick the index of the
163+
// `UnreachedInstruction` as the index of this use.
164+
// Note that a function may have both a `ReturnInstruction` and an
165+
// `UnreachedInstruction`. If that's the case this predicate will
166+
// return multiple results. I don't think this is detrimental to
167+
// performance, however.
168+
exists(Instruction return |
169+
return instanceof ReturnInstruction or
170+
return instanceof UnreachedInstruction
171+
|
172+
block.getInstruction(index) = return and
160173
return.getEnclosingFunction() = p.getFunction()
161174
)
162175
}

0 commit comments

Comments
 (0)