Skip to content

Commit 8467ad7

Browse files
committed
Java: Add AnnotatedExitNodes to the CFG.
1 parent 321a4af commit 8467ad7

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

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

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
*/
8181

8282
import java
83+
private import codeql.util.Boolean
8384
private import Completion
8485
private import controlflow.internal.Preconditions
8586
private import controlflow.internal.SwitchCases
@@ -100,6 +101,7 @@ module ControlFlow {
100101
private newtype TNode =
101102
TExprNode(Expr e) { hasControlFlow(e) } or
102103
TStmtNode(Stmt s) or
104+
TAnnotatedExitNode(Callable c, Boolean normal) { exists(c.getBody()) } or
103105
TExitNode(Callable c) { exists(c.getBody()) } or
104106
TAssertThrowNode(AssertStmt s)
105107

@@ -189,6 +191,38 @@ module ControlFlow {
189191
override Location getLocation() { result = s.getLocation() }
190192
}
191193

194+
/** A control flow node indicating the normal or exceptional termination of a callable. */
195+
class AnnotatedExitNode extends Node, TAnnotatedExitNode {
196+
Callable c;
197+
boolean normal;
198+
199+
AnnotatedExitNode() { this = TAnnotatedExitNode(c, normal) }
200+
201+
override Callable getEnclosingCallable() { result = c }
202+
203+
override ExprParent getAstNode() { result = c }
204+
205+
/** Gets a textual representation of this element. */
206+
override string toString() {
207+
normal = true and result = "Normal Exit"
208+
or
209+
normal = false and result = "Exceptional Exit"
210+
}
211+
212+
/** Gets the source location for this element. */
213+
override Location getLocation() { result = c.getLocation() }
214+
}
215+
216+
/** A control flow node indicating normal termination of a callable. */
217+
class NormalExitNode extends AnnotatedExitNode {
218+
NormalExitNode() { this = TAnnotatedExitNode(_, true) }
219+
}
220+
221+
/** A control flow node indicating exceptional termination of a callable. */
222+
class ExceptionalExitNode extends AnnotatedExitNode {
223+
ExceptionalExitNode() { this = TAnnotatedExitNode(_, false) }
224+
}
225+
192226
/** A control flow node indicating the termination of a callable. */
193227
class ExitNode extends Node, TExitNode {
194228
Callable c;
@@ -1264,11 +1298,17 @@ private module ControlFlowGraphImpl {
12641298
*/
12651299
cached
12661300
Node succ(Node n, Completion completion) {
1267-
// After executing the callable body, the final node is the exit node.
1301+
// After executing the callable body, the final nodes are first the
1302+
// annotated exit node and then the final exit node.
12681303
exists(Callable c | last(c.getBody(), n, completion) |
1269-
result.(ExitNode).getEnclosingCallable() = c
1304+
if completion instanceof ThrowCompletion
1305+
then result.(ExceptionalExitNode).getEnclosingCallable() = c
1306+
else result.(NormalExitNode).getEnclosingCallable() = c
12701307
)
12711308
or
1309+
completion = NormalCompletion() and
1310+
n.(AnnotatedExitNode).getEnclosingCallable() = result.(ExitNode).getEnclosingCallable()
1311+
or
12721312
// Logic expressions and conditional expressions execute in AST pre-order.
12731313
completion = NormalCompletion() and
12741314
(

java/ql/lib/semmle/code/java/security/PathSanitizer.qll

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,10 @@ private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
2929
* Holds if `m` validates its `arg`th parameter by using `validationGuard`.
3030
*/
3131
private predicate validationMethod(Method m, int arg) {
32-
exists(
33-
Guard g, SsaImplicitInit var, ControlFlow::ExitNode exit, ControlFlowNode normexit,
34-
boolean branch
35-
|
32+
exists(Guard g, SsaImplicitInit var, ControlFlow::NormalExitNode normexit, boolean branch |
3633
validationGuard(g, var.getAUse(), branch) and
3734
var.isParameterDefinition(m.getParameter(arg)) and
38-
exit.getEnclosingCallable() = m and
39-
normexit.getANormalSuccessor() = exit and
40-
1 = strictcount(ControlFlowNode n | n.getANormalSuccessor() = exit)
41-
|
42-
exists(ConditionNode conditionNode |
43-
g = conditionNode.getCondition() and conditionNode.getABranchSuccessor(branch) = exit
44-
)
45-
or
35+
normexit.getEnclosingCallable() = m and
4636
g.controls(normexit.getBasicBlock(), branch)
4737
)
4838
}

0 commit comments

Comments
 (0)