Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7f3ae94

Browse files
committed
Tweak the WhenExpr CFG and QL class
1 parent f95934a commit 7f3ae94

2 files changed

Lines changed: 49 additions & 17 deletions

File tree

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ private module ControlFlowGraphImpl {
309309
or
310310
exists(WhenExpr whenexpr |
311311
inBooleanContext(whenexpr) and
312-
whenexpr.getBranch(_).getResult() = b)
312+
whenexpr.getBranch(_).getAResult() = b)
313313
}
314314

315315
/**
@@ -417,9 +417,7 @@ private module ControlFlowGraphImpl {
417417
exists(WhenExpr whenexpr | whenexpr = result |
418418
whenexpr.getBranch(_).isElseBranch() and
419419
forex(WhenBranch whenbranch | whenbranch = whenexpr.getBranch(_) |
420-
whenbranch.getResult() = nonReturningExpr()
421-
or
422-
whenbranch.getResult() = nonReturningStmt()))
420+
whenbranch.getRhs() = nonReturningStmt()))
423421
}
424422

425423
/**
@@ -907,20 +905,42 @@ private module ControlFlowGraphImpl {
907905
)
908906
or
909907
// The last node in a `when` expression is the last node in any of its branches or
910-
// the last node of the condition in the absence of an else-branch.
908+
// the last node of the condition of the last branch in the absence of an else-branch.
911909
exists(WhenExpr whenexpr | whenexpr = n |
910+
// If we have no branches then we are the last node
912911
last = n and
913912
completion = NormalCompletion() and
914-
not whenexpr.getBranch(_).isElseBranch()
913+
not exists(whenexpr.getBranch(_))
914+
or
915+
// If our last branch condition is false then we are done
916+
exists(int i |
917+
last(whenexpr.getBranch(i), last, BooleanCompletion(false, _)) and
918+
completion = NormalCompletion() and
919+
not exists(whenexpr.getBranch(i + 1)))
920+
or
921+
// Any branch getting an abnormal completion is propogated
922+
last(whenexpr.getBranch(_), last, completion) and
923+
not completion instanceof YieldCompletion and
924+
not completion instanceof NormalOrBooleanCompletion
915925
or
916-
last(whenexpr.getBranch(_).getResult(), last, completion)
926+
// The last node in any branch. This will be wrapped up as a
927+
// YieldCompletion, so we need to unwrap it here.
928+
last(whenexpr.getBranch(_), last, YieldCompletion(completion))
917929
)
918930
or
919931
exists(WhenBranch whenbranch | whenbranch = n |
920-
last(whenbranch.getCondition(), last, BooleanCompletion(false, _)) and
921-
completion = NormalCompletion()
922-
or
923-
last(whenbranch.getResult(), last, completion)
932+
// If the condition completes with anything other than true
933+
// (e.g. false or an exception), then the branch is done
934+
last(whenbranch.getCondition(), last, completion) and
935+
completion != BooleanCompletion(true, _)
936+
or
937+
// Otherwise we wrap the completion up in a YieldCompletion
938+
// so that the `when` expression can tell that we have finished,
939+
// and it shouldn't go on to the next branch.
940+
exists(Completion branchCompletion |
941+
last(whenbranch.getRhs(), last, branchCompletion) and
942+
completion = YieldCompletion(branchCompletion)
943+
)
924944
)
925945
}
926946

@@ -1191,19 +1211,20 @@ private module ControlFlowGraphImpl {
11911211
completion = NormalCompletion()
11921212
or
11931213
exists(int i |
1194-
last(whenexpr.getBranch(i).getCondition(), n, completion) and
1214+
last(whenexpr.getBranch(i), n, completion) and
11951215
completion = BooleanCompletion(false, _) and
11961216
result = first(whenexpr.getBranch(i + 1)))
11971217
)
11981218
or
11991219
// When branches:
1200-
exists(WhenBranch whenbranch | n = whenbranch |
1220+
exists(WhenBranch whenbranch |
1221+
n = whenbranch and
12011222
completion = NormalCompletion() and
12021223
result = first(whenbranch.getCondition())
12031224
or
12041225
last(whenbranch.getCondition(), n, completion) and
12051226
completion = BooleanCompletion(true, _) and
1206-
result = first(whenbranch.getResult())
1227+
result = first(whenbranch.getRhs())
12071228
)
12081229
}
12091230

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,9 +2158,13 @@ class WhenBranch extends Top, @whenbranch {
21582158
Expr getCondition() { result.isNthChildOf(this, 0) }
21592159

21602160
/** Gets the result of this branch. */
2161-
Top getResult() {
2162-
result.(Expr).isNthChildOf(this, 1) or
2163-
result.(Stmt).isNthChildOf(this, 1)
2161+
Stmt getRhs() {
2162+
result.isNthChildOf(this, 1)
2163+
}
2164+
2165+
/** Gets a result expression of this `when` branch. */
2166+
Expr getAResult() {
2167+
result = getAResult(this.getRhs())
21642168
}
21652169

21662170
/** Holds if this is an `else` branch. */
@@ -2173,6 +2177,13 @@ class WhenBranch extends Top, @whenbranch {
21732177
override string getAPrimaryQlClass() { result = "WhenBranch" }
21742178
}
21752179

2180+
// TODO: This might need more cases. It might be better as a predicate
2181+
// on Stmt, overridden in each subclass.
2182+
private Expr getAResult(Stmt s) {
2183+
result = s.(ExprStmt).getExpr() or
2184+
result = getAResult(s.(BlockStmt).getLastStmt())
2185+
}
2186+
21762187
/** A Kotlin `::class` expression. */
21772188
class ClassExpr extends Expr, @getclassexpr {
21782189
/** Gets the expression whose class is being returned. */

0 commit comments

Comments
 (0)