Skip to content

Commit 9573395

Browse files
authored
Merge pull request #12005 from MathiasVP/flow-out-of-invalid-functions
C++: Flow out of invalid functions
2 parents e48c93a + 2b47e15 commit 9573395

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
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
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ int intOutparamSourceMissingReturn(int *p) {
510510
void viaOutparamMissingReturn() {
511511
int x = 0;
512512
intOutparamSourceMissingReturn(&x);
513-
sink(x); // $ ast MISSING: ir
513+
sink(x); // $ ast,ir
514514
}
515515

516516
void uncertain_definition() {

0 commit comments

Comments
 (0)