Merge tag 'codeql-cli/latest'

Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
Dilan
2025-01-09 21:59:09 +00:00
3257 changed files with 109906 additions and 18574 deletions

View File

@@ -40,6 +40,7 @@ load(
)
load("@rules_kotlin//kotlin:core.bzl", "kt_javac_options", "kt_kotlinc_options")
load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library")
load("@rules_python//python:defs.bzl", "py_binary")
package(default_visibility = ["//java/kotlin-extractor:__subpackages__"])

View File

@@ -1,7 +1,6 @@
import java
import semmle.code.java.ControlFlowGraph
predicate shouldBeDeadEnd(ControlFlowNode n) {
predicate shouldBeDeadEnd(ExprParent n) {
n instanceof BreakStmt and n.getFile().isKotlinSourceFile() // TODO
or
n instanceof Interface // TODO
@@ -55,8 +54,11 @@ predicate shouldBeDeadEnd(ControlFlowNode n) {
n = any(ConstCase c).getValue(_) // TODO
}
from ControlFlowNode n, string s
from ControlFlowNode n, ExprParent astnode, string s
where
// TODO: exists(n.getASuccessor()) and shouldBeDeadEnd(n) and s = "expected dead end"
not exists(n.getASuccessor()) and not shouldBeDeadEnd(n) and s = "unexpected dead end"
select n, n.getPrimaryQlClasses(), s
astnode = n.getAstNode() and
// TODO: exists(n.getASuccessor()) and shouldBeDeadEnd(n.getAstNode()) and s = "expected dead end"
not exists(n.getASuccessor()) and
not shouldBeDeadEnd(astnode) and
s = "unexpected dead end"
select n, astnode.getPrimaryQlClasses(), s

View File

@@ -1,6 +1,6 @@
import java
import semmle.code.java.dataflow.TaintTracking
import TestUtilities.InlineExpectationsTest
import utils.test.InlineExpectationsTest
private import semmle.code.java.dataflow.ExternalFlow
module Config implements DataFlow::ConfigSig {

View File

@@ -1,3 +1,24 @@
## 6.0.0
### Breaking Changes
* The class `ControlFlowNode` (and by extension `BasicBlock`) is no longer
directly equatable to `Expr` and `Stmt`. Any queries that have been
exploiting these equalities, for example by using casts, will need minor
updates in order to fix any compilation errors. Conversions can be inserted
in either direction depending on what is most convenient. Available
conversions include `Expr.getControlFlowNode()`, `Stmt.getControlFlowNode()`,
`ControlFlowNode.asExpr()`, `ControlFlowNode.asStmt()`, and
`ControlFlowNode.asCall()`. Exit nodes were until now modelled as a
`ControlFlowNode` equal to its enclosing `Callable`; these are now instead
modelled by the class `ControlFlow::ExitNode`.
### Minor Analysis Improvements
* Added `java.io.File.getName()` as a path injection sanitizer.
* The data flow library has been updated to track types in a slightly different way: The type of the tainted data (which may be stored into fields, etc.) is tracked more precisely, while the types of intermediate containers for nested contents is tracked less precisely. This may have a slight effect on false positives for complex flow paths.
* Added a sink for "Server-side request forgery" (`java/ssrf`) for the third parameter to org.springframework.web.client.RestTemplate.getForObject, when we cannot statically determine that it does not affect the host in the URL.
## 5.0.0
### Breaking Changes

View File

@@ -0,0 +1,20 @@
## 6.0.0
### Breaking Changes
* The class `ControlFlowNode` (and by extension `BasicBlock`) is no longer
directly equatable to `Expr` and `Stmt`. Any queries that have been
exploiting these equalities, for example by using casts, will need minor
updates in order to fix any compilation errors. Conversions can be inserted
in either direction depending on what is most convenient. Available
conversions include `Expr.getControlFlowNode()`, `Stmt.getControlFlowNode()`,
`ControlFlowNode.asExpr()`, `ControlFlowNode.asStmt()`, and
`ControlFlowNode.asCall()`. Exit nodes were until now modelled as a
`ControlFlowNode` equal to its enclosing `Callable`; these are now instead
modelled by the class `ControlFlow::ExitNode`.
### Minor Analysis Improvements
* Added `java.io.File.getName()` as a path injection sanitizer.
* The data flow library has been updated to track types in a slightly different way: The type of the tainted data (which may be stored into fields, etc.) is tracked more precisely, while the types of intermediate containers for nested contents is tracked less precisely. This may have a slight effect on false positives for complex flow paths.
* Added a sink for "Server-side request forgery" (`java/ssrf`) for the third parameter to org.springframework.web.client.RestTemplate.getForObject, when we cannot statically determine that it does not affect the host in the URL.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 5.0.0
lastReleaseVersion: 6.0.0

View File

@@ -1,5 +1,5 @@
name: codeql/java-all
version: 5.0.0
version: 6.0.0
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java

View File

@@ -1,10 +1,10 @@
/**
* Provides classes and predicates for computing expression-level intra-procedural control flow graphs.
*
* The only API exported by this library are the toplevel classes `ControlFlowNode`
* The only API exported by this library are the toplevel classes `ControlFlow::Node`
* and its subclass `ConditionNode`, which wrap the successor relation and the
* concept of true- and false-successors of conditions. A cfg node may either be a
* statement, an expression, or the enclosing callable, indicating that
* statement, an expression, or an exit node for a callable, indicating that
* execution of the callable terminates.
*/
@@ -84,45 +84,148 @@ private import Completion
private import controlflow.internal.Preconditions
private import controlflow.internal.SwitchCases
/** A node in the expression-level control-flow graph. */
class ControlFlowNode extends Top, @exprparent {
/** Gets the statement containing this node, if any. */
Stmt getEnclosingStmt() {
result = this or
result = this.(Expr).getEnclosingStmt()
/** Provides the definition of control flow nodes. */
module ControlFlow {
private predicate hasControlFlow(Expr e) {
not exists(ConstCase cc | e = cc.getValue(_)) and
not e.getParent*() instanceof Annotation and
not e instanceof TypeAccess and
not e instanceof ArrayTypeAccess and
not e instanceof UnionTypeAccess and
not e instanceof IntersectionTypeAccess and
not e instanceof WildcardTypeAccess and
not exists(AssignExpr ae | ae.getDest() = e)
}
/** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() {
result = this or
result = this.(Stmt).getEnclosingCallable() or
result = this.(Expr).getEnclosingCallable()
private newtype TNode =
TExprNode(Expr e) { hasControlFlow(e) } or
TStmtNode(Stmt s) or
TExitNode(Callable c) { exists(c.getBody()) }
/** A node in the expression-level control-flow graph. */
class Node extends TNode {
/** Gets an immediate successor of this node. */
Node getASuccessor() { result = succ(this) }
/** Gets an immediate predecessor of this node. */
Node getAPredecessor() { this = succ(result) }
/** Gets an exception successor of this node. */
Node getAnExceptionSuccessor() { result = succ(this, ThrowCompletion(_)) }
/** Gets a successor of this node that is neither an exception successor nor a jump (break, continue, return). */
Node getANormalSuccessor() {
result = succ(this, BooleanCompletion(_, _)) or
result = succ(this, NormalCompletion())
}
/** Gets the basic block that contains this node. */
BasicBlock getBasicBlock() { result.getANode() = this }
/** Gets the statement containing this node, if any. */
Stmt getEnclosingStmt() { none() }
/** Gets the immediately enclosing callable whose body contains this node. */
Callable getEnclosingCallable() { none() }
/** Gets the statement this `Node` corresponds to, if any. */
Stmt asStmt() { this = TStmtNode(result) }
/** Gets the expression this `Node` corresponds to, if any. */
Expr asExpr() { this = TExprNode(result) }
/** Gets the call this `Node` corresponds to, if any. */
Call asCall() {
result = this.asExpr() or
result = this.asStmt()
}
/** Gets a textual representation of this element. */
string toString() { none() }
/** Gets the source location for this element. */
Location getLocation() { none() }
/**
* Gets the most appropriate AST node for this control flow node, if any.
*/
ExprParent getAstNode() { none() }
}
/** Gets an immediate successor of this node. */
ControlFlowNode getASuccessor() { result = succ(this) }
/** A control-flow node that represents the evaluation of an expression. */
class ExprNode extends Node, TExprNode {
Expr e;
/** Gets an immediate predecessor of this node. */
ControlFlowNode getAPredecessor() { this = succ(result) }
ExprNode() { this = TExprNode(e) }
/** Gets an exception successor of this node. */
ControlFlowNode getAnExceptionSuccessor() { result = succ(this, ThrowCompletion(_)) }
override Stmt getEnclosingStmt() { result = e.getEnclosingStmt() }
/** Gets a successor of this node that is neither an exception successor nor a jump (break, continue, return). */
ControlFlowNode getANormalSuccessor() {
result = succ(this, BooleanCompletion(_, _)) or
result = succ(this, NormalCompletion())
override Callable getEnclosingCallable() { result = e.getEnclosingCallable() }
override ExprParent getAstNode() { result = e }
/** Gets a textual representation of this element. */
override string toString() { result = e.toString() }
/** Gets the source location for this element. */
override Location getLocation() { result = e.getLocation() }
}
/** Gets the basic block that contains this node. */
BasicBlock getBasicBlock() { result.getANode() = this }
/** A control-flow node that represents a statement. */
class StmtNode extends Node, TStmtNode {
Stmt s;
StmtNode() { this = TStmtNode(s) }
override Stmt getEnclosingStmt() { result = s }
override Callable getEnclosingCallable() { result = s.getEnclosingCallable() }
override ExprParent getAstNode() { result = s }
override string toString() { result = s.toString() }
override Location getLocation() { result = s.getLocation() }
}
/** A control flow node indicating the termination of a callable. */
class ExitNode extends Node, TExitNode {
Callable c;
ExitNode() { this = TExitNode(c) }
override Callable getEnclosingCallable() { result = c }
override ExprParent getAstNode() { result = c }
/** Gets a textual representation of this element. */
override string toString() { result = "Exit" }
/** Gets the source location for this element. */
override Location getLocation() { result = c.getLocation() }
}
}
class ControlFlowNode = ControlFlow::Node;
/** Gets the intra-procedural successor of `n`. */
private ControlFlowNode succ(ControlFlowNode n) { result = succ(n, _) }
cached
private module ControlFlowGraphImpl {
private import ControlFlow
private class AstNode extends ExprParent {
AstNode() { this instanceof Expr or this instanceof Stmt }
Stmt getEnclosingStmt() {
result = this or
result = this.(Expr).getEnclosingStmt()
}
Node getCfgNode() { result.asExpr() = this or result.asStmt() = this }
}
/**
* Gets a label that applies to this statement.
*/
@@ -167,7 +270,7 @@ private module ControlFlowGraphImpl {
* `ClassCastException` is expected, or because it is a Kotlin not-null check
* and a `NullPointerException` is expected.
*/
private predicate mayThrow(ControlFlowNode n, ThrowableType t) {
private predicate mayThrow(AstNode n, ThrowableType t) {
t = n.(ThrowStmt).getThrownExceptionType()
or
exists(Call c | c = n |
@@ -200,7 +303,7 @@ private module ControlFlowGraphImpl {
* Bind `t` to an unchecked exception that may transfer control to a finally
* block inside which `n` is nested.
*/
private predicate uncheckedExceptionFromFinally(ControlFlowNode n, ThrowableType t) {
private predicate uncheckedExceptionFromFinally(AstNode n, ThrowableType t) {
exists(TryStmt try |
n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or
n.(Expr).getParent*() = try.getAResource()
@@ -214,7 +317,7 @@ private module ControlFlowGraphImpl {
* Bind `t` to all unchecked exceptions that may be caught by some
* `try-catch` inside which `n` is nested.
*/
private predicate uncheckedExceptionFromCatch(ControlFlowNode n, ThrowableType t) {
private predicate uncheckedExceptionFromCatch(AstNode n, ThrowableType t) {
exists(TryStmt try, UncheckedThrowableSuperType caught |
n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or
n.(Expr).getParent*() = try.getAResource()
@@ -229,7 +332,7 @@ private module ControlFlowGraphImpl {
* body or the resources (if any) of `try`.
*/
private ThrowableType thrownInBody(TryStmt try) {
exists(ControlFlowNode n | mayThrow(n, result) |
exists(AstNode n | mayThrow(n, result) |
n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or
n.(Expr).getParent*() = try.getAResource()
)
@@ -287,7 +390,7 @@ private module ControlFlowGraphImpl {
* That is, contexts where the control-flow edges depend on `value` given that `b` ends
* with a `booleanCompletion(value, _)`.
*/
private predicate inBooleanContext(ControlFlowNode b) {
private predicate inBooleanContext(AstNode b) {
exists(LogicExpr logexpr |
logexpr.(BinaryExpr).getLeftOperand() = b
or
@@ -493,9 +596,7 @@ private module ControlFlowGraphImpl {
* immediately before either falling through to execute successor statements or execute a rule body
* if present. `completion` is the completion kind of the last operation.
*/
private predicate lastPatternCaseMatchingOp(
PatternCase pc, ControlFlowNode last, Completion completion
) {
private predicate lastPatternCaseMatchingOp(PatternCase pc, Node last, Completion completion) {
last(pc.getAPattern(), last, completion) and
completion = NormalCompletion() and
not exists(pc.getGuard())
@@ -514,7 +615,7 @@ private module ControlFlowGraphImpl {
* and `ThrowStmt`. CFG nodes without child nodes in the CFG that may complete
* normally are also included.
*/
private class PostOrderNode extends ControlFlowNode {
private class PostOrderNode extends AstNode {
PostOrderNode() {
// For VarAccess and ArrayAccess only read accesses (r-values) are included,
// as write accesses aren't included in the CFG.
@@ -576,7 +677,7 @@ private module ControlFlowGraphImpl {
}
/** Gets child nodes in their order of execution. Indexing starts at either -1 or 0. */
ControlFlowNode getChildNode(int index) {
AstNode getChildNode(int index) {
exists(ArrayAccess e | e = this |
index = 0 and result = e.getArray()
or
@@ -649,7 +750,7 @@ private module ControlFlowGraphImpl {
}
/** Gets the first child node, if any. */
ControlFlowNode firstChild() {
AstNode firstChild() {
result = this.getChildNode(-1)
or
result = this.getChildNode(0) and not exists(this.getChildNode(-1))
@@ -687,18 +788,18 @@ private module ControlFlowGraphImpl {
/**
* Determine the part of the AST node `n` that will be executed first.
*/
private ControlFlowNode first(ControlFlowNode n) {
result = n and n instanceof LogicExpr
private Node first(AstNode n) {
result.asExpr() = n and n instanceof LogicExpr
or
result = n and n instanceof ConditionalExpr
result.asExpr() = n and n instanceof ConditionalExpr
or
result = n and n instanceof WhenExpr
result.asExpr() = n and n instanceof WhenExpr
or
result = n and n instanceof WhenBranch
result.asStmt() = n and n instanceof WhenBranch
or
result = n and n instanceof StmtExpr
result.asExpr() = n and n instanceof StmtExpr
or
result = n and n.(PostOrderNode).isLeafNode()
result = n.getCfgNode() and n.(PostOrderNode).isLeafNode()
or
result = first(n.(PostOrderNode).firstChild())
or
@@ -706,12 +807,11 @@ private module ControlFlowGraphImpl {
or
result = first(n.(SynchronizedStmt).getExpr())
or
result = n and
n instanceof Stmt and
result.asStmt() = n and
not n instanceof PostOrderNode and
not n instanceof SynchronizedStmt
or
result = n and n instanceof SwitchExpr
result.asExpr() = n and n instanceof SwitchExpr
}
/**
@@ -722,9 +822,7 @@ private module ControlFlowGraphImpl {
* node in the `try` block that may not complete normally, or a node in
* the `try` block that has no control flow successors inside the block.
*/
private predicate catchOrFinallyCompletion(
TryStmt try, ControlFlowNode last, Completion completion
) {
private predicate catchOrFinallyCompletion(TryStmt try, Node last, Completion completion) {
last(try.getBlock(), last, completion)
or
last(try.getAResource(), last, completion) and completion = ThrowCompletion(_)
@@ -737,7 +835,7 @@ private module ControlFlowGraphImpl {
* In other words, if `last` throws an exception it is possibly not caught by any
* of the catch clauses.
*/
private predicate uncaught(TryStmt try, ControlFlowNode last, Completion completion) {
private predicate uncaught(TryStmt try, Node last, Completion completion) {
catchOrFinallyCompletion(try, last, completion) and
(
exists(ThrowableType thrown |
@@ -767,12 +865,12 @@ private module ControlFlowGraphImpl {
* This is similar to `uncaught`, but also includes final statements of `catch`
* clauses.
*/
private predicate finallyPred(TryStmt try, ControlFlowNode last, Completion completion) {
private predicate finallyPred(TryStmt try, Node last, Completion completion) {
uncaught(try, last, completion) or
last(try.getACatchClause(), last, completion)
}
private predicate lastInFinally(TryStmt try, ControlFlowNode last) {
private predicate lastInFinally(TryStmt try, Node last) {
last(try.getFinally(), last, NormalCompletion())
}
@@ -796,7 +894,7 @@ private module ControlFlowGraphImpl {
* A `booleanCompletion` implies that `n` is an `Expr`. Any abnormal
* completion besides `throwCompletion` implies that `n` is a `Stmt`.
*/
private predicate last(ControlFlowNode n, ControlFlowNode last, Completion completion) {
private predicate last(AstNode n, Node last, Completion completion) {
// Exceptions are propagated from any sub-expression.
// As are any break, yield, continue, or return completions.
exists(Expr e | e.getParent() = n |
@@ -853,15 +951,17 @@ private module ControlFlowGraphImpl {
)
or
exists(InstanceOfExpr ioe | ioe.isPattern() and ioe = n |
last = n and completion = basicBooleanCompletion(false)
last.asExpr() = n and completion = basicBooleanCompletion(false)
or
last(ioe.getPattern(), last, NormalCompletion()) and completion = basicBooleanCompletion(true)
)
or
// The last node of a node executed in post-order is the node itself.
n.(PostOrderNode).mayCompleteNormally() and last = n and completion = NormalCompletion()
exists(PostOrderNode p | p = n |
p.mayCompleteNormally() and last = p.getCfgNode() and completion = NormalCompletion()
)
or
last = n and completion = basicBooleanCompletion(n.(BooleanLiteral).getBooleanValue())
last.asExpr() = n and completion = basicBooleanCompletion(n.(BooleanLiteral).getBooleanValue())
or
// The last statement in a block is any statement that does not complete normally,
// or the last statement.
@@ -997,7 +1097,7 @@ private module ControlFlowGraphImpl {
// * On success of its guard test, if it is not a rule (boolean true)
// (the latter two cases are accounted for by lastPatternCaseMatchingOp)
exists(PatternCase pc | n = pc |
last = pc and completion = basicBooleanCompletion(false)
last.asStmt() = pc and completion = basicBooleanCompletion(false)
or
last(pc.getGuard(), last, completion) and
completion = BooleanCompletion(false, _)
@@ -1010,13 +1110,15 @@ private module ControlFlowGraphImpl {
last(n.(SynchronizedStmt).getBlock(), last, completion)
or
// `return` statements give rise to a `Return` completion
last = n.(ReturnStmt) and completion = ReturnCompletion()
last.asStmt() = n.(ReturnStmt) and completion = ReturnCompletion()
or
// `throw` statements or throwing calls give rise to ` Throw` completion
exists(ThrowableType tt | mayThrow(n, tt) | last = n and completion = ThrowCompletion(tt))
exists(ThrowableType tt | mayThrow(n, tt) |
last = n.getCfgNode() and completion = ThrowCompletion(tt)
)
or
// `break` statements give rise to a `Break` completion
exists(BreakStmt break | break = n and last = n |
exists(BreakStmt break | break = n and last.asStmt() = n |
completion = labelledBreakCompletion(MkLabel(break.getLabel()))
or
not exists(break.getLabel()) and completion = anonymousBreakCompletion()
@@ -1031,7 +1133,7 @@ private module ControlFlowGraphImpl {
)
or
// `continue` statements give rise to a `Continue` completion
exists(ContinueStmt cont | cont = n and last = n |
exists(ContinueStmt cont | cont = n and last.asStmt() = n |
completion = labelledContinueCompletion(MkLabel(cont.getLabel()))
or
not exists(cont.getLabel()) and completion = anonymousContinueCompletion()
@@ -1067,7 +1169,7 @@ private module ControlFlowGraphImpl {
// the last node of the condition of the last branch in the absence of an else-branch.
exists(WhenExpr whenexpr | whenexpr = n |
// If we have no branches then we are the last node
last = n and
last.asExpr() = n and
completion = NormalCompletion() and
not exists(whenexpr.getBranch(_))
or
@@ -1117,17 +1219,19 @@ private module ControlFlowGraphImpl {
* execution finishes with the given completion.
*/
cached
ControlFlowNode succ(ControlFlowNode n, Completion completion) {
// Callables serve as their own exit nodes.
exists(Callable c | last(c.getBody(), n, completion) | result = c)
Node succ(Node n, Completion completion) {
// After executing the callable body, the final node is the exit node.
exists(Callable c | last(c.getBody(), n, completion) |
result.(ExitNode).getEnclosingCallable() = c
)
or
// Logic expressions and conditional expressions execute in AST pre-order.
completion = NormalCompletion() and
(
result = first(n.(AndLogicalExpr).getLeftOperand()) or
result = first(n.(OrLogicalExpr).getLeftOperand()) or
result = first(n.(LogNotExpr).getExpr()) or
result = first(n.(ConditionalExpr).getCondition())
result = first(n.asExpr().(AndLogicalExpr).getLeftOperand()) or
result = first(n.asExpr().(OrLogicalExpr).getLeftOperand()) or
result = first(n.asExpr().(LogNotExpr).getExpr()) or
result = first(n.asExpr().(ConditionalExpr).getCondition())
)
or
// If a logic expression doesn't short-circuit then control flows from its left operand to its right.
@@ -1151,9 +1255,11 @@ private module ControlFlowGraphImpl {
)
or
exists(InstanceOfExpr ioe | ioe.isPattern() |
last(ioe.getExpr(), n, completion) and completion = NormalCompletion() and result = ioe
last(ioe.getExpr(), n, completion) and
completion = NormalCompletion() and
result.asExpr() = ioe
or
n = ioe and
n.asExpr() = ioe and
result = first(ioe.getPattern()) and
completion = basicBooleanCompletion(true)
)
@@ -1164,11 +1270,11 @@ private module ControlFlowGraphImpl {
|
result = first(p.getChildNode(i + 1))
or
not exists(p.getChildNode(i + 1)) and result = p
not exists(p.getChildNode(i + 1)) and result = p.getCfgNode()
)
or
// Statements within a block execute sequentially.
result = first(n.(BlockStmt).getStmt(0)) and completion = NormalCompletion()
result = first(n.asStmt().(BlockStmt).getStmt(0)) and completion = NormalCompletion()
or
exists(BlockStmt blk, int i |
last(blk.getStmt(i), n, completion) and
@@ -1178,7 +1284,7 @@ private module ControlFlowGraphImpl {
or
// Control flows to the corresponding branch depending on the boolean completion of the condition.
exists(IfStmt s |
n = s and result = first(s.getCondition()) and completion = NormalCompletion()
n.asStmt() = s and result = first(s.getCondition()) and completion = NormalCompletion()
or
last(s.getCondition(), n, completion) and
completion = BooleanCompletion(true, _) and
@@ -1190,7 +1296,7 @@ private module ControlFlowGraphImpl {
)
or
// For statements:
exists(ForStmt for, ControlFlowNode condentry |
exists(ForStmt for, Node condentry |
// Any part of the control flow that aims for the condition needs to hit either the condition...
condentry = first(for.getCondition())
or
@@ -1198,10 +1304,10 @@ private module ControlFlowGraphImpl {
not exists(for.getCondition()) and condentry = first(for.getStmt())
|
// From the entry point, which is the for statement itself, control goes to either the first init expression...
n = for and result = first(for.getInit(0)) and completion = NormalCompletion()
n.asStmt() = for and result = first(for.getInit(0)) and completion = NormalCompletion()
or
// ...or the condition if the for doesn't include init expressions.
n = for and
n.asStmt() = for and
not exists(for.getAnInit()) and
result = condentry and
completion = NormalCompletion()
@@ -1238,27 +1344,29 @@ private module ControlFlowGraphImpl {
// Enhanced for statements:
exists(EnhancedForStmt for |
// First the expression gets evaluated...
n = for and result = first(for.getExpr()) and completion = NormalCompletion()
n.asStmt() = for and result = first(for.getExpr()) and completion = NormalCompletion()
or
// ...then the variable gets assigned...
last(for.getExpr(), n, completion) and
completion = NormalCompletion() and
result = for.getVariable()
result.asExpr() = for.getVariable()
or
// ...and then control goes to the body of the loop.
n = for.getVariable() and result = first(for.getStmt()) and completion = NormalCompletion()
n.asExpr() = for.getVariable() and
result = first(for.getStmt()) and
completion = NormalCompletion()
or
// Finally, the back edge of the loop goes to reassign the variable.
last(for.getStmt(), n, completion) and
continues(completion, for) and
result = for.getVariable()
result.asExpr() = for.getVariable()
)
or
// While loops start at the condition...
result = first(n.(WhileStmt).getCondition()) and completion = NormalCompletion()
result = first(n.asStmt().(WhileStmt).getCondition()) and completion = NormalCompletion()
or
// ...and do-while loops start at the body.
result = first(n.(DoStmt).getStmt()) and completion = NormalCompletion()
result = first(n.asStmt().(DoStmt).getStmt()) and completion = NormalCompletion()
or
exists(LoopStmt loop | loop instanceof WhileStmt or loop instanceof DoStmt |
// Control goes from the condition via a true-completion to the body...
@@ -1282,7 +1390,7 @@ private module ControlFlowGraphImpl {
)
or
// After the last resource declaration, control transfers to the body.
exists(TryStmt try | n = try and completion = NormalCompletion() |
exists(TryStmt try | n.asStmt() = try and completion = NormalCompletion() |
result = first(try.getResource(0))
or
not exists(try.getAResource()) and result = first(try.getBlock())
@@ -1310,7 +1418,7 @@ private module ControlFlowGraphImpl {
or
// Catch clauses first assign their variable and then execute their block
exists(CatchClause cc | completion = NormalCompletion() |
n = cc and result = first(cc.getVariable())
n.asStmt() = cc and result = first(cc.getVariable())
or
last(cc.getVariable(), n, completion) and result = first(cc.getBlock())
)
@@ -1321,7 +1429,9 @@ private module ControlFlowGraphImpl {
switchExpr = switch.(SwitchStmt).getExpr() or switchExpr = switch.(SwitchExpr).getExpr()
|
// From the entry point control is transferred first to the expression...
n = switch and result = first(switchExpr) and completion = NormalCompletion()
n.getAstNode() = switch and
result = first(switchExpr) and
completion = NormalCompletion()
or
// ...and then to any case up to and including the first pattern case, if any.
last(switchExpr, n, completion) and
@@ -1345,7 +1455,7 @@ private module ControlFlowGraphImpl {
or
// A pattern case that completes boolean false (type test or guard failure) continues to consider other cases:
exists(PatternCase case | completion = BooleanCompletion(false, _) |
last(case, n, completion) and result = getASuccessorSwitchCase(case, switch)
last(case, n, completion) and result.asStmt() = getASuccessorSwitchCase(case, switch)
)
)
or
@@ -1358,7 +1468,7 @@ private module ControlFlowGraphImpl {
// * Variable declarations -normal-> rule execution (when there is no guard)
// * Guard success -true-> rule execution
exists(PatternCase pc |
n = pc and
n.asStmt() = pc and
completion = basicBooleanCompletion(true) and
result = first(pc.getAPattern())
or
@@ -1375,7 +1485,7 @@ private module ControlFlowGraphImpl {
)
or
// Non-pattern cases have an internal edge leading to their rule body if any when the case matches.
exists(SwitchCase case | n = case |
exists(SwitchCase case | n.asStmt() = case |
not case instanceof PatternCase and
completion = NormalCompletion() and
(
@@ -1387,32 +1497,32 @@ private module ControlFlowGraphImpl {
or
// Yield
exists(YieldStmt yield | completion = NormalCompletion() |
n = yield and result = first(yield.getValue())
n.asStmt() = yield and result = first(yield.getValue())
)
or
// Synchronized statements execute their expression _before_ synchronization, so the CFG reflects that.
exists(SynchronizedStmt synch | completion = NormalCompletion() |
last(synch.getExpr(), n, completion) and result = synch
last(synch.getExpr(), n, completion) and result.asStmt() = synch
or
n = synch and result = first(synch.getBlock())
n.asStmt() = synch and result = first(synch.getBlock())
)
or
result = first(n.(ExprStmt).getExpr()) and completion = NormalCompletion()
result = first(n.asStmt().(ExprStmt).getExpr()) and completion = NormalCompletion()
or
result = first(n.(StmtExpr).getStmt()) and completion = NormalCompletion()
result = first(n.asExpr().(StmtExpr).getStmt()) and completion = NormalCompletion()
or
result = first(n.(LabeledStmt).getStmt()) and completion = NormalCompletion()
result = first(n.asStmt().(LabeledStmt).getStmt()) and completion = NormalCompletion()
or
// Variable declarations in a variable declaration statement are executed sequentially.
exists(LocalVariableDeclStmt s | completion = NormalCompletion() |
n = s and result = first(s.getVariable(1))
n.asStmt() = s and result = first(s.getVariable(1))
or
exists(int i | last(s.getVariable(i), n, completion) and result = first(s.getVariable(i + 1)))
)
or
// When expressions:
exists(WhenExpr whenexpr |
n = whenexpr and
n.asExpr() = whenexpr and
result = first(whenexpr.getBranch(0)) and
completion = NormalCompletion()
or
@@ -1425,7 +1535,7 @@ private module ControlFlowGraphImpl {
or
// When branches:
exists(WhenBranch whenbranch |
n = whenbranch and
n.asStmt() = whenbranch and
completion = NormalCompletion() and
result = first(whenbranch.getCondition())
or
@@ -1463,7 +1573,7 @@ private module ControlFlowGraphImpl {
* predicate `finallyPred`, since their completion is resumed after normal
* completion of the `finally`.
*/
private Completion resumption(ControlFlowNode n) {
private Completion resumption(Node n) {
exists(TryStmt try | lastInFinally(try, n) and finallyPred(try, _, result))
or
not lastInFinally(_, n) and result = NormalCompletion()
@@ -1474,9 +1584,7 @@ private module ControlFlowGraphImpl {
*
* That is, the `booleanCompletion` is the label of the edge in the CFG.
*/
private ControlFlowNode mainBranchSucc(ControlFlowNode n, boolean b) {
result = succ(n, BooleanCompletion(_, b))
}
private Node mainBranchSucc(Node n, boolean b) { result = succ(n, BooleanCompletion(_, b)) }
/**
* A true- or false-successor that is not tagged with a `booleanCompletion`.
@@ -1487,8 +1595,8 @@ private module ControlFlowGraphImpl {
* In the latter case, when `n` occurs as the last node in a finally block, there might be
* multiple different such successors.
*/
private ControlFlowNode otherBranchSucc(ControlFlowNode n, boolean b) {
exists(ControlFlowNode main | main = mainBranchSucc(n, b.booleanNot()) |
private Node otherBranchSucc(Node n, boolean b) {
exists(Node main | main = mainBranchSucc(n, b.booleanNot()) |
result = succ(n, resumption(n)) and
not result = main and
(b = true or b = false)
@@ -1497,7 +1605,7 @@ private module ControlFlowGraphImpl {
/** Gets a true- or false-successor of `n`. */
cached
ControlFlowNode branchSuccessor(ControlFlowNode n, boolean branch) {
Node branchSuccessor(Node n, boolean branch) {
result = mainBranchSucc(n, branch) or
result = otherBranchSucc(n, branch)
}
@@ -1506,18 +1614,18 @@ private module ControlFlowGraphImpl {
private import ControlFlowGraphImpl
/** A control-flow node that branches based on a condition. */
class ConditionNode extends ControlFlowNode {
class ConditionNode extends ControlFlow::Node {
ConditionNode() { exists(branchSuccessor(this, _)) }
/** Gets a true- or false-successor of the `ConditionNode`. */
ControlFlowNode getABranchSuccessor(boolean branch) { result = branchSuccessor(this, branch) }
ControlFlow::Node getABranchSuccessor(boolean branch) { result = branchSuccessor(this, branch) }
/** Gets a true-successor of the `ConditionNode`. */
ControlFlowNode getATrueSuccessor() { result = this.getABranchSuccessor(true) }
ControlFlow::Node getATrueSuccessor() { result = this.getABranchSuccessor(true) }
/** Gets a false-successor of the `ConditionNode`. */
ControlFlowNode getAFalseSuccessor() { result = this.getABranchSuccessor(false) }
ControlFlow::Node getAFalseSuccessor() { result = this.getABranchSuccessor(false) }
/** Gets the condition of this `ConditionNode`. This is equal to the node itself. */
ExprParent getCondition() { result = this }
/** Gets the condition of this `ConditionNode`. */
ExprParent getCondition() { result = this.asExpr() or result = this.asStmt() }
}

View File

@@ -61,10 +61,10 @@ class Expr extends ExprParent, @expr {
Expr getAChildExpr() { exprs(result, _, _, this, _) }
/** Gets the basic block in which this expression occurs, if any. */
BasicBlock getBasicBlock() { result.getANode() = this }
BasicBlock getBasicBlock() { result.getANode().asExpr() = this }
/** Gets the `ControlFlowNode` corresponding to this expression. */
ControlFlowNode getControlFlowNode() { result = this }
ControlFlowNode getControlFlowNode() { result.asExpr() = this }
/** This statement's Halstead ID (used to compute Halstead metrics). */
string getHalsteadID() { result = this.toString() }

View File

@@ -45,10 +45,10 @@ class Stmt extends StmtParent, ExprParent, @stmt {
Stmt getAChild() { result.getParent() = this }
/** Gets the basic block in which this statement occurs. */
BasicBlock getBasicBlock() { result.getANode() = this }
BasicBlock getBasicBlock() { result.getANode().asStmt() = this }
/** Gets the `ControlFlowNode` corresponding to this statement. */
ControlFlowNode getControlFlowNode() { result = this }
ControlFlowNode getControlFlowNode() { result.asStmt() = this }
/** Cast this statement to a class that provides access to metrics information. */
MetricStmt getMetrics() { result = this }

View File

@@ -66,3 +66,8 @@ class BasicBlock extends ControlFlowNode {
/** Holds if this basic block post-dominates `node`. (This is reflexive.) */
predicate bbPostDominates(BasicBlock node) { bbPostDominates(this, node) }
}
/** A basic block that ends in an exit node. */
class ExitBlock extends BasicBlock {
ExitBlock() { this.getLastNode() instanceof ControlFlow::ExitNode }
}

View File

@@ -9,13 +9,15 @@ import java
*/
/** Entry points for control-flow. */
private predicate flowEntry(Stmt entry) {
exists(Callable c | entry = c.getBody())
or
// This disjunct is technically superfluous, but safeguards against extractor problems.
entry instanceof BlockStmt and
not exists(entry.getEnclosingCallable()) and
not entry.getParent() instanceof Stmt
private predicate flowEntry(BasicBlock entry) {
exists(Stmt entrystmt | entrystmt = entry.getFirstNode().asStmt() |
exists(Callable c | entrystmt = c.getBody())
or
// This disjunct is technically superfluous, but safeguards against extractor problems.
entrystmt instanceof BlockStmt and
not exists(entry.getEnclosingCallable()) and
not entrystmt.getParent() instanceof Stmt
)
}
/** The successor relation for basic blocks. */
@@ -31,11 +33,8 @@ predicate hasDominanceInformation(BasicBlock bb) {
exists(BasicBlock entry | flowEntry(entry) and bbSucc*(entry, bb))
}
/** Exit points for control-flow. */
private predicate flowExit(Callable exit) { exists(ControlFlowNode s | s.getASuccessor() = exit) }
/** Exit points for basic-block control-flow. */
private predicate bbSink(BasicBlock exit) { flowExit(exit.getLastNode()) }
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
/** Reversed `bbSucc`. */
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }

View File

@@ -113,7 +113,7 @@ private PatternCase getClosestPrecedingPatternCase(SwitchCase case) {
private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pred) {
pred = sc.getControlFlowNode().getAPredecessor() and
(
pred.(Expr).getParent*() = sc.getSelectorExpr()
pred.asExpr().getParent*() = sc.getSelectorExpr()
or
// Ambiguous: in the case of `case String _ when x: case "SomeConstant":`, the guard `x`
// passing edge will fall through into the constant case, and the guard failing edge
@@ -122,7 +122,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
exists(PatternCase previousPatternCase |
previousPatternCase = getClosestPrecedingPatternCase(sc)
|
pred.(Expr).getParent*() = previousPatternCase.getGuard() and
pred.asExpr().getParent*() = previousPatternCase.getGuard() and
// Check there is any statement in between the previous pattern case and this one,
// or the case is a rule, so there is no chance of a fall-through.
(
@@ -133,7 +133,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
or
// Unambigious: on the test-passing edge there must be at least one intervening
// declaration node, including anonymous `_` declarations.
pred = getClosestPrecedingPatternCase(sc)
pred.asStmt() = getClosestPrecedingPatternCase(sc)
)
}

View File

@@ -32,7 +32,7 @@ abstract class ActionConfiguration extends string {
private BasicBlock actionBlock(ActionConfiguration conf) {
exists(ControlFlowNode node | result = node.getBasicBlock() |
conf.isAction(node) or
callAlwaysPerformsAction(node, conf)
callAlwaysPerformsAction(node.asCall(), conf)
)
}
@@ -45,17 +45,17 @@ private predicate callAlwaysPerformsAction(Call call, ActionConfiguration conf)
/** Holds if an action dominates the exit of the callable. */
private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) {
exists(BasicBlock exit |
exit.getLastNode() = callable and
exists(ExitBlock exit |
exit.getEnclosingCallable() = callable and
actionBlock(conf).bbDominates(exit)
)
}
/** Gets a `BasicBlock` that contains an action that does not dominate the exit. */
private BasicBlock nonDominatingActionBlock(ActionConfiguration conf) {
exists(BasicBlock exit |
exists(ExitBlock exit |
result = actionBlock(conf) and
exit.getLastNode() = result.getEnclosingCallable() and
exit.getEnclosingCallable() = result.getEnclosingCallable() and
not result.bbDominates(exit)
)
}
@@ -80,8 +80,8 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
private predicate callableAlwaysPerformsAction(Callable callable, ActionConfiguration conf) {
actionDominatesExit(callable, conf)
or
exists(BasicBlock exit |
exit.getLastNode() = callable and
exists(ExitBlock exit |
exit.getEnclosingCallable() = callable and
postActionBlock(exit, conf)
)
}

View File

@@ -207,14 +207,12 @@ class UnreachableBasicBlock extends BasicBlock {
conditionBlock.controls(this, constant.booleanNot())
)
or
// This block is not reachable in the CFG, and is not a callable, a body of a callable, an
// expression in an annotation, an expression in an assert statement, or a catch clause.
// This block is not reachable in the CFG, and is not the entrypoint in a callable, an
// expression in an assert statement, or a catch clause.
forall(BasicBlock bb | bb = this.getABBPredecessor() | bb instanceof UnreachableBasicBlock) and
not exists(Callable c | c.getBody() = this) and
not this instanceof Callable and
not exists(Annotation a | a.getAChildExpr*() = this) and
not this.(Expr).getEnclosingStmt() instanceof AssertStmt and
not this instanceof CatchClause
not exists(Callable c | c.getBody().getControlFlowNode() = this.getFirstNode()) and
not this.getFirstNode().asExpr().getEnclosingStmt() instanceof AssertStmt and
not this.getFirstNode().asStmt() instanceof CatchClause
or
// Switch statements with a constant comparison expression may have unreachable cases.
exists(ConstSwitchStmt constSwitchStmt, BasicBlock unreachableCaseBlock |

View File

@@ -227,12 +227,14 @@ class InstanceAccessExt extends TInstanceAccessExt {
/** Gets the control flow node associated with this instance access. */
ControlFlowNode getCfgNode() {
exists(ExprParent e | e = this.getAssociatedExprOrStmt() |
e instanceof Call and result = e
result.asCall() = e
or
e instanceof InstanceAccess and result = e
e.(InstanceAccess).getControlFlowNode() = result
or
exists(FieldAccess fa | fa = e |
if fa instanceof VarRead then fa = result else result.(AssignExpr).getDest() = fa
if fa instanceof VarRead
then fa.getControlFlowNode() = result
else result.asExpr().(AssignExpr).getDest() = fa
)
)
}

View File

@@ -130,8 +130,8 @@ predicate dereference(Expr e) {
* The `VarAccess` is included for nicer error reporting.
*/
private ControlFlowNode varDereference(SsaVariable v, VarAccess va) {
dereference(result) and
result = sameValue(v, va)
dereference(result.asExpr()) and
result.asExpr() = sameValue(v, va)
}
/**
@@ -141,16 +141,16 @@ private ControlFlowNode varDereference(SsaVariable v, VarAccess va) {
private ControlFlowNode ensureNotNull(SsaVariable v) {
result = varDereference(v, _)
or
result.(AssertStmt).getExpr() = nullGuard(v, true, false)
result.asStmt().(AssertStmt).getExpr() = nullGuard(v, true, false)
or
exists(AssertTrueMethod m | result = m.getACheck(nullGuard(v, true, false)))
exists(AssertTrueMethod m | result.asCall() = m.getACheck(nullGuard(v, true, false)))
or
exists(AssertFalseMethod m | result = m.getACheck(nullGuard(v, false, false)))
exists(AssertFalseMethod m | result.asCall() = m.getACheck(nullGuard(v, false, false)))
or
exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse()))
exists(AssertNotNullMethod m | result.asCall() = m.getACheck(v.getAUse()))
or
exists(AssertThatMethod m, MethodCall ma |
result = m.getACheck(v.getAUse()) and ma.getControlFlowNode() = result
result.asCall() = m.getACheck(v.getAUse()) and ma.getControlFlowNode() = result
|
ma.getAnArgument().(MethodCall).getMethod().getName() = "notNullValue"
)
@@ -279,10 +279,10 @@ private predicate enhancedForEarlyExit(EnhancedForStmt for, ControlFlowNode n1,
exists(Expr forExpr |
n1.getANormalSuccessor() = n2 and
for.getExpr() = forExpr and
forExpr.getAChildExpr*() = n1 and
not forExpr.getAChildExpr*() = n2 and
n1.getANormalSuccessor() = for.getVariable() and
not n2 = for.getVariable()
forExpr.getAChildExpr*() = n1.asExpr() and
not forExpr.getAChildExpr*() = n2.asExpr() and
n1.getANormalSuccessor().asExpr() = for.getVariable() and
not n2.asExpr() = for.getVariable()
)
}
@@ -343,7 +343,7 @@ private predicate nullVarStep(
not impossibleEdge(mid, bb) and
not exists(boolean branch | nullGuard(midssa, branch, false).hasBranchEdge(mid, bb, branch)) and
not (leavingFinally(mid, bb, true) and midstoredcompletion = true) and
if bb.getFirstNode() = any(TryStmt try | | try.getFinally())
if bb.getFirstNode().asStmt() = any(TryStmt try | | try.getFinally())
then
if bb.getFirstNode() = mid.getLastNode().getANormalSuccessor()
then storedcompletion = false

View File

@@ -211,9 +211,11 @@ module Sem implements Semantic {
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
private predicate id(BasicBlock x, BasicBlock y) { x = y }
private predicate id(ExprParent x, ExprParent y) { x = y }
private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOfAst(ExprParent x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getAstNode(), y) }
int getBlockId1(BasicBlock bb) { idOf(bb, result) }

View File

@@ -228,7 +228,7 @@ private module SsaImpl {
/** Holds if `n` must update the locally tracked variable `v`. */
cached
predicate certainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
exists(VariableUpdate a | a = n | getDestVar(a) = v) and
exists(VariableUpdate a | a.getControlFlowNode() = n | getDestVar(a) = v) and
b.getNode(i) = n and
hasDominanceInformation(b)
or
@@ -237,8 +237,8 @@ private module SsaImpl {
/** Gets the definition point of a nested class in the parent scope. */
private ControlFlowNode parentDef(NestedClass nc) {
nc.(AnonymousClass).getClassInstanceExpr() = result or
nc.(LocalClass).getLocalTypeDeclStmt() = result
nc.(AnonymousClass).getClassInstanceExpr().getControlFlowNode() = result or
nc.(LocalClass).getLocalTypeDeclStmt().getControlFlowNode() = result
}
/**
@@ -276,7 +276,7 @@ private module SsaImpl {
/** Holds if `VarAccess` `use` of `v` occurs in `b` at index `i`. */
private predicate variableUse(TrackedVar v, VarRead use, BasicBlock b, int i) {
v.getAnAccess() = use and b.getNode(i) = use
v.getAnAccess() = use and b.getNode(i) = use.getControlFlowNode()
}
/** Holds if the value of `v` is captured in `b` at index `i`. */
@@ -423,7 +423,7 @@ private module SsaImpl {
* `f` has an update somewhere.
*/
private predicate updateCandidate(TrackedField f, Call call, BasicBlock b, int i) {
b.getNode(i) = call and
b.getNode(i).asCall() = call and
call.getEnclosingCallable() = f.getEnclosingCallable() and
relevantFieldUpdate(_, f.getField(), _)
}
@@ -550,7 +550,7 @@ private module SsaImpl {
/** Holds if `n` might update the locally tracked variable `v`. */
cached
predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
exists(Call c | c = n | updatesNamedField(c, v, _)) and
exists(Call c | c = n.asCall() | updatesNamedField(c, v, _)) and
b.getNode(i) = n and
hasDominanceInformation(b)
or
@@ -574,12 +574,16 @@ private module SsaImpl {
/** Holds if `v` has an implicit definition at the entry, `b`, of the callable. */
cached
predicate hasEntryDef(TrackedVar v, BasicBlock b) {
exists(LocalScopeVariable l, Callable c | v = TLocalVar(c, l) and c.getBody() = b |
exists(LocalScopeVariable l, Callable c |
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
|
l instanceof Parameter or
l.getCallable() != c
)
or
v instanceof SsaSourceField and v.getEnclosingCallable().getBody() = b and liveAtEntry(v, b)
v instanceof SsaSourceField and
v.getEnclosingCallable().getBody().getControlFlowNode() = b and
liveAtEntry(v, b)
}
/**
@@ -882,7 +886,7 @@ private newtype TSsaVariable =
} or
TSsaEntryDef(TrackedVar v, BasicBlock b) { hasEntryDef(v, b) } or
TSsaUntracked(SsaSourceField nf, ControlFlowNode n) {
n = nf.getAnAccess().(FieldRead) and not trackField(nf)
n = nf.getAnAccess().(FieldRead).getControlFlowNode() and not trackField(nf)
}
/**
@@ -940,7 +944,7 @@ class SsaVariable extends TSsaVariable {
/** Gets an access of this SSA variable. */
VarRead getAUse() {
ssaDefReachesUse(_, this, result) or
this = TSsaUntracked(_, result)
this = TSsaUntracked(_, result.getControlFlowNode())
}
/**
@@ -954,7 +958,7 @@ class SsaVariable extends TSsaVariable {
*/
VarRead getAFirstUse() {
firstUse(this, result) or
this = TSsaUntracked(_, result)
this = TSsaUntracked(_, result.getControlFlowNode())
}
/** Holds if this SSA variable is live at the end of `b`. */
@@ -990,7 +994,7 @@ class SsaUpdate extends SsaVariable {
class SsaExplicitUpdate extends SsaUpdate, TSsaCertainUpdate {
SsaExplicitUpdate() {
exists(VariableUpdate upd |
upd = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
upd.getControlFlowNode() = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
)
}
@@ -998,7 +1002,8 @@ class SsaExplicitUpdate extends SsaUpdate, TSsaCertainUpdate {
/** Gets the `VariableUpdate` defining the SSA variable. */
VariableUpdate getDefiningExpr() {
result = this.getCfgNode() and getDestVar(result) = this.getSourceVariable()
result.getControlFlowNode() = this.getCfgNode() and
getDestVar(result) = this.getSourceVariable()
}
}
@@ -1038,7 +1043,7 @@ class SsaImplicitUpdate extends SsaUpdate {
exists(SsaSourceField f, Callable setter |
f = this.getSourceVariable() and
relevantFieldUpdate(setter, f.getField(), result) and
updatesNamedField(this.getCfgNode(), f, setter)
updatesNamedField(this.getCfgNode().asCall(), f, setter)
)
}
@@ -1086,7 +1091,7 @@ class SsaImplicitInit extends SsaVariable, TSsaEntryDef {
*/
predicate isParameterDefinition(Parameter p) {
this.getSourceVariable() = TLocalVar(p.getCallable(), p) and
p.getCallable().getBody() = this.getCfgNode()
p.getCallable().getBody().getControlFlowNode() = this.getCfgNode()
}
}

View File

@@ -252,8 +252,8 @@ private module Input implements TypeFlowInput<Location> {
downcastSuccessorAux(pragma[only_bind_into](cast), v, t, t1, t2) and
t1.getASourceSupertype+() = t2 and
va = v.getAUse() and
dominates(cast, va) and
dominates(cast.(ControlFlowNode).getANormalSuccessor(), va)
dominates(cast.getControlFlowNode(), va.getControlFlowNode()) and
dominates(cast.getControlFlowNode().getANormalSuccessor(), va.getControlFlowNode())
)
}

View File

@@ -73,15 +73,15 @@ private module SsaImpl {
/** Holds if `n` updates the local variable `v`. */
cached
predicate variableUpdate(BaseSsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) {
exists(VariableUpdate a | a = n | getDestVar(a) = v) and
exists(VariableUpdate a | a.getControlFlowNode() = n | getDestVar(a) = v) and
b.getNode(i) = n and
hasDominanceInformation(b)
}
/** Gets the definition point of a nested class in the parent scope. */
private ControlFlowNode parentDef(NestedClass nc) {
nc.(AnonymousClass).getClassInstanceExpr() = result or
nc.(LocalClass).getLocalTypeDeclStmt() = result
nc.(AnonymousClass).getClassInstanceExpr().getControlFlowNode() = result or
nc.(LocalClass).getLocalTypeDeclStmt().getControlFlowNode() = result
}
/**
@@ -121,7 +121,7 @@ private module SsaImpl {
/** Holds if `VarAccess` `use` of `v` occurs in `b` at index `i`. */
private predicate variableUse(BaseSsaSourceVariable v, VarRead use, BasicBlock b, int i) {
v.getAnAccess() = use and b.getNode(i) = use
v.getAnAccess() = use and b.getNode(i) = use.getControlFlowNode()
}
/** Holds if the value of `v` is captured in `b` at index `i`. */
@@ -164,7 +164,9 @@ private module SsaImpl {
/** Holds if `v` has an implicit definition at the entry, `b`, of the callable. */
cached
predicate hasEntryDef(BaseSsaSourceVariable v, BasicBlock b) {
exists(LocalScopeVariable l, Callable c | v = TLocalVar(c, l) and c.getBody() = b |
exists(LocalScopeVariable l, Callable c |
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
|
l instanceof Parameter or
l.getCallable() != c
)
@@ -537,7 +539,7 @@ class BaseSsaVariable extends TBaseSsaVariable {
class BaseSsaUpdate extends BaseSsaVariable, TSsaUpdate {
BaseSsaUpdate() {
exists(VariableUpdate upd |
upd = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
upd.getControlFlowNode() = this.getCfgNode() and getDestVar(upd) = this.getSourceVariable()
)
}
@@ -545,7 +547,8 @@ class BaseSsaUpdate extends BaseSsaVariable, TSsaUpdate {
/** Gets the `VariableUpdate` defining the SSA variable. */
VariableUpdate getDefiningExpr() {
result = this.getCfgNode() and getDestVar(result) = this.getSourceVariable()
result.getControlFlowNode() = this.getCfgNode() and
getDestVar(result) = this.getSourceVariable()
}
}
@@ -566,7 +569,7 @@ class BaseSsaImplicitInit extends BaseSsaVariable, TSsaEntryDef {
*/
predicate isParameterDefinition(Parameter p) {
this.getSourceVariable() = TLocalVar(p.getCallable(), p) and
p.getCallable().getBody() = this.getCfgNode()
p.getCallable().getBody().getControlFlowNode() = this.getCfgNode()
}
}

View File

@@ -112,7 +112,7 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
Location getLocation() { result = super.getLocation() }
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.(J::BasicBlock).getNode(i) }
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.(J::BasicBlock).getNode(i).asExpr() }
}
class VariableWrite extends Expr instanceof VariableUpdate {

View File

@@ -17,9 +17,11 @@ import DataFlowNodes::Public
/** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */
private predicate thisAccess(Node n, ControlFlowNode cfgnode) {
n.(InstanceParameterNode).getCallable().getBody() = cfgnode
n.(InstanceParameterNode).getCallable().getBody() = cfgnode.asStmt()
or
exists(InstanceAccess ia | ia = n.asExpr() and ia = cfgnode and ia.isOwnInstanceAccess())
exists(InstanceAccess ia |
ia = n.asExpr() and ia.getControlFlowNode() = cfgnode and ia.isOwnInstanceAccess()
)
or
n.(ImplicitInstanceAccess).getInstanceAccess().(OwnInstanceAccess).getCfgNode() = cfgnode
}

View File

@@ -133,5 +133,5 @@ module Private {
predicate ssaUpdateStep = RU::ssaUpdateStep/3;
Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode() }
Expr getABasicBlockExpr(BasicBlock bb) { result = bb.getANode().asExpr() }
}

View File

@@ -340,7 +340,7 @@ private module Impl {
Field getField(FieldAccess fa) { result = fa.getField() }
Expr getAnExpression(SsaReadPositionBlock bb) { result = bb.getBlock().getANode() }
Expr getAnExpression(SsaReadPositionBlock bb) { result = bb.getBlock().getANode().asExpr() }
Guard getComparisonGuard(ComparisonExpr ce) { result = ce }
}

View File

@@ -15,9 +15,11 @@ class BasicBlock = BB::BasicBlock;
/** Gets a basic block in which SSA variable `v` is read. */
BasicBlock getAReadBasicBlock(SsaVariable v) { result = v.getAUse().getBasicBlock() }
private predicate id(BasicBlock x, BasicBlock y) { x = y }
private predicate id(BB::ExprParent x, BB::ExprParent y) { x = y }
private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOfAst(BB::ExprParent x, int y) = equivalenceRelation(id/2)(x, y)
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getAstNode(), y) }
private int getId(BasicBlock bb) { idOf(bb, result) }

View File

@@ -109,12 +109,12 @@ predicate assertFail(BasicBlock bb, ControlFlowNode n) {
bb = n.getBasicBlock() and
(
exists(AssertTrueMethod m |
n = m.getACheck(any(BooleanLiteral b | b.getBooleanValue() = false))
n.asExpr() = m.getACheck(any(BooleanLiteral b | b.getBooleanValue() = false))
) or
exists(AssertFalseMethod m |
n = m.getACheck(any(BooleanLiteral b | b.getBooleanValue() = true))
n.asExpr() = m.getACheck(any(BooleanLiteral b | b.getBooleanValue() = true))
) or
exists(AssertFailMethod m | n = m.getACheck()) or
n.(AssertStmt).getExpr().(BooleanLiteral).getBooleanValue() = false
exists(AssertFailMethod m | n.asExpr() = m.getACheck()) or
n.asStmt().(AssertStmt).getExpr().(BooleanLiteral).getBooleanValue() = false
)
}

View File

@@ -4,6 +4,7 @@
import java
import SpringHttp
private import semmle.code.java.security.RequestForgery
/** The class `org.springframework.web.client.RestTemplate`. */
class SpringRestTemplate extends Class {
@@ -27,3 +28,76 @@ class SpringWebClient extends Interface {
this.hasQualifiedName("org.springframework.web.reactive.function.client", "WebClient")
}
}
/** The method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */
class SpringRestTemplateGetForObjectMethod extends Method {
SpringRestTemplateGetForObjectMethod() {
this.getDeclaringType() instanceof SpringRestTemplate and
this.hasName("getForObject")
}
}
/** A call to the method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */
class SpringRestTemplateGetForObjectMethodCall extends MethodCall {
SpringRestTemplateGetForObjectMethodCall() {
this.getMethod() instanceof SpringRestTemplateGetForObjectMethod
}
/** Gets the first argument, if it is a compile time constant. */
CompileTimeConstantExpr getConstantUrl() { result = this.getArgument(0) }
/**
* Holds if the first argument is a compile time constant and it has a
* placeholder at offset `offset`, and there are `idx` placeholders that
* appear before it.
*/
predicate urlHasPlaceholderAtOffset(int idx, int offset) {
exists(
this.getConstantUrl()
.getStringValue()
.replaceAll("\\{", " ")
.replaceAll("\\}", " ")
.regexpFind("\\{[^}]*\\}", idx, offset)
)
}
}
private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink {
SpringWebClientRestTemplateGetForObject() {
exists(SpringRestTemplateGetForObjectMethodCall mc, int i |
// Note that the first argument is modeled as a request forgery sink
// separately. This model is for arguments beyond the first two. There
// are two relevant overloads, one with third parameter type `Object...`
// and one with third parameter type `Map<String, ?>`. For the latter we
// cannot deal with MapValue content easily but there is a default
// implicit taint read at sinks that will catch it.
i >= 0 and
this.asExpr() = mc.getArgument(i + 2)
|
// If we can determine that part of mc.getArgument(0) is a hostname
// sanitizing prefix, then we count how many placeholders occur before it
// and only consider that many arguments beyond the first two as sinks.
// For the `Map<String, ?>` overload this has the effect of only
// considering the map values as sinks if there is at least one
// placeholder in the URL before the hostname sanitizing prefix.
exists(int offset |
mc.urlHasPlaceholderAtOffset(i, offset) and
offset < mc.getConstantUrl().(HostnameSanitizingPrefix).getOffset()
)
or
// If we cannot determine that part of mc.getArgument(0) is a hostname
// sanitizing prefix, but it is a compile time constant and we can get
// its string value, then we count how many placeholders occur in it
// and only consider that many arguments beyond the first two as sinks.
// For the `Map<String, ?>` overload this has the effect of only
// considering the map values as sinks if there is at least one
// placeholder in the URL.
not mc.getConstantUrl() instanceof HostnameSanitizingPrefix and
mc.urlHasPlaceholderAtOffset(i, _)
or
// If we cannot determine the string value of mc.getArgument(0), then we
// conservatively consider all arguments as sinks.
not exists(mc.getConstantUrl().getStringValue())
)
}
}

View File

@@ -73,14 +73,14 @@ class MetricCallable extends Callable {
// so there should be a branching point for each non-default switch
// case (ignoring those that just fall through to the next case).
private predicate branchingSwitchCase(ConstCase sc) {
not sc.(ControlFlowNode).getASuccessor() instanceof SwitchCase and
not sc.getControlFlowNode().getASuccessor().asStmt() instanceof SwitchCase and
not defaultFallThrough(sc)
}
private predicate defaultFallThrough(ConstCase sc) {
exists(DefaultCase default | default.(ControlFlowNode).getASuccessor() = sc)
exists(DefaultCase default | default.getControlFlowNode().getASuccessor().asStmt() = sc)
or
defaultFallThrough(sc.(ControlFlowNode).getAPredecessor())
defaultFallThrough(sc.getControlFlowNode().getAPredecessor().asStmt())
}
/** Holds if `stmt` is a branching statement used for the computation of cyclomatic complexity. */

View File

@@ -29,15 +29,19 @@ private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
*/
private predicate validationMethod(Method m, int arg) {
exists(
Guard g, SsaImplicitInit var, ControlFlowNode exit, ControlFlowNode normexit, boolean branch
Guard g, SsaImplicitInit var, ControlFlow::ExitNode exit, ControlFlowNode normexit,
boolean branch
|
validationGuard(g, var.getAUse(), branch) and
var.isParameterDefinition(m.getParameter(arg)) and
exit = m and
exit.getEnclosingCallable() = m and
normexit.getANormalSuccessor() = exit and
1 = strictcount(ControlFlowNode n | n.getANormalSuccessor() = exit)
|
g.(ConditionNode).getABranchSuccessor(branch) = exit or
exists(ConditionNode conditionNode |
g = conditionNode.getCondition() and conditionNode.getABranchSuccessor(branch) = exit
)
or
g.controls(normexit.getBasicBlock(), branch)
)
}
@@ -333,3 +337,18 @@ private Method getSourceMethod(Method m) {
not exists(Method src | m = src.getKotlinParameterDefaultsProxy()) and
result = m
}
/**
* A sanitizer that protects against path injection vulnerabilities
* by extracting the final component of the user provided path.
*
* TODO: convert this class to models-as-data if sanitizer support is added
*/
private class FileGetNameSanitizer extends PathInjectionSanitizer {
FileGetNameSanitizer() {
exists(MethodCall mc |
mc.getMethod().hasQualifiedName("java.io", "File", "getName") and
this.asExpr() = mc
)
}
}

View File

@@ -63,14 +63,17 @@ abstract class RequestForgerySanitizer extends DataFlow::Node { }
private class PrimitiveSanitizer extends RequestForgerySanitizer instanceof SimpleTypeSanitizer { }
private class HostnameSanitizingPrefix extends InterestingPrefix {
/**
* A string constant that contains a prefix which looks like when it is prepended to untrusted
* input, it will restrict the host or entity addressed.
*
* For example, anything containing `?` or `#`, or a slash that doesn't appear to be a protocol
* specifier (e.g. `http://` is not sanitizing), or specifically the string "/".
*/
class HostnameSanitizingPrefix extends InterestingPrefix {
int offset;
HostnameSanitizingPrefix() {
// Matches strings that look like when prepended to untrusted input, they will restrict
// the host or entity addressed: for example, anything containing `?` or `#`, or a slash that
// doesn't appear to be a protocol specifier (e.g. `http://` is not sanitizing), or specifically
// the string "/".
exists(this.getStringValue().regexpFind("([?#]|[^?#:/\\\\][/\\\\])|^/$", 0, offset))
}
@@ -81,8 +84,10 @@ private class HostnameSanitizingPrefix extends InterestingPrefix {
* A value that is the result of prepending a string that prevents any value from controlling the
* host of a URL.
*/
private class HostnameSantizer extends RequestForgerySanitizer {
HostnameSantizer() { this.asExpr() = any(HostnameSanitizingPrefix hsp).getAnAppendedExpression() }
private class HostnameSanitizer extends RequestForgerySanitizer {
HostnameSanitizer() {
this.asExpr() = any(HostnameSanitizingPrefix hsp).getAnAppendedExpression()
}
}
/**

View File

@@ -50,7 +50,7 @@ private predicate validatedAccess(VarAccess va) {
bb.getNode(i + 1) = node.getANormalSuccessor()
|
bb.bbStrictlyDominates(va.getBasicBlock()) or
bb.getNode(any(int j | j > i)) = va
bb.getNode(any(int j | j > i)).asExpr() = va
)
)
)

View File

@@ -1,3 +1,7 @@
## 1.1.11
No user-facing changes.
## 1.1.10
### Minor Analysis Improvements

View File

@@ -30,7 +30,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
ConditionBlock cb, SsaVariable v, BinaryExpr cond, boolean condIsTrue, int k1, int k2,
CompileTimeConstantExpr c1, CompileTimeConstantExpr c2
|
s1 = cond and
s1.getCondition() = cond and
cb.getCondition() = cond and
cond.hasOperands(v.getAUse(), c1) and
c1.getIntValue() = k1 and

View File

@@ -36,7 +36,7 @@ where
doubleCheckedLocking(if1, if2, sync, f) and
a.getEnclosingStmt().getEnclosingStmt*() = if2.getThen() and
se.getEnclosingStmt().getEnclosingStmt*() = sync.getBlock() and
a.(ControlFlowNode).getASuccessor+() = se and
a.getControlFlowNode().getASuccessor+().asExpr() = se and
a.getDest().(FieldAccess).getField() = f
select a,
"Potential race condition. This assignment to $@ is visible to other threads before the subsequent statements are executed.",

View File

@@ -64,12 +64,12 @@ class ValidSynchStmt extends Stmt {
exists(MethodCall lockAction |
lockAction.getQualifier() = lockField.getAnAccess() and
lockAction.getMethod().getName() = "lock" and
dominates(lockAction, this)
dominates(lockAction.getControlFlowNode(), this.getControlFlowNode())
) and
exists(MethodCall unlockAction |
unlockAction.getQualifier() = lockField.getAnAccess() and
unlockAction.getMethod().getName() = "unlock" and
postDominates(unlockAction, this)
postDominates(unlockAction.getControlFlowNode(), this.getControlFlowNode())
)
)
}

View File

@@ -59,11 +59,11 @@ class LockType extends RefType {
}
predicate lockBlock(LockType t, BasicBlock b, int locks) {
locks = strictcount(int i | b.getNode(i) = t.getLockAccess())
locks = strictcount(int i | b.getNode(i).asExpr() = t.getLockAccess())
}
predicate unlockBlock(LockType t, BasicBlock b, int unlocks) {
unlocks = strictcount(int i | b.getNode(i) = t.getUnlockAccess())
unlocks = strictcount(int i | b.getNode(i).asExpr() = t.getUnlockAccess())
}
/**
@@ -90,11 +90,11 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
exists(ControlFlowNode lock |
lock = lockblock.getLastNode() and
(
lock = t.getLockAccess()
lock.asExpr() = t.getLockAccess()
or
exists(SsaExplicitUpdate lockbool |
// Using the value of `t.getLockAccess()` ensures that it is a `tryLock` call.
lock = lockbool.getAUse() and
lock.asExpr() = lockbool.getAUse() and
lockbool.getDefiningExpr().(VariableAssign).getSource() = t.getLockAccess()
)
) and
@@ -147,12 +147,12 @@ predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) {
)
}
from Callable c, LockType t, BasicBlock src, BasicBlock exit, MethodCall lock
from Callable c, LockType t, BasicBlock src, ExitBlock exit, MethodCall lock
where
// Restrict results to those methods that actually attempt to unlock.
t.getUnlockAccess().getEnclosingCallable() = c and
blockIsLocked(t, src, exit, _) and
exit.getLastNode() = c and
lock = src.getANode() and
exit.getEnclosingCallable() = c and
lock = src.getANode().asExpr() and
lock = t.getLockAccess()
select lock, "This lock might not be unlocked or might be locked more times than it is unlocked."

View File

@@ -61,7 +61,7 @@ predicate mainLoopCondition(LoopStmt loop, Expr cond) {
else loopReentry = cond
|
last.getEnclosingStmt().getEnclosingStmt*() = loop.getBody() and
last.getASuccessor().(Expr).getParent*() = loopReentry
last.getASuccessor().asExpr().getParent*() = loopReentry
)
}
@@ -75,7 +75,7 @@ where
// None of the ssa variables in `cond` are updated inside the loop.
forex(SsaVariable ssa, VarRead use | ssa.getAUse() = use and use.getParent*() = cond |
not ssa.getCfgNode().getEnclosingStmt().getEnclosingStmt*() = loop or
ssa.getCfgNode().(Expr).getParent*() = loop.(ForStmt).getAnInit()
ssa.getCfgNode().asExpr().getParent*() = loop.(ForStmt).getAnInit()
) and
// And `cond` does not use method calls, field reads, or array reads.
not exists(MethodCall ma | ma.getParent*() = cond) and

View File

@@ -80,8 +80,8 @@ predicate badReentrantLockOrder(MethodCall first, MethodCall second, MethodCall
otherSecond = v1.getLockAction() and
second = v2.getLockAction() and
otherFirst = v2.getLockAction() and
first.(ControlFlowNode).getASuccessor+() = second and
otherFirst.(ControlFlowNode).getASuccessor+() = otherSecond
first.getControlFlowNode().getASuccessor+() = second.getControlFlowNode() and
otherFirst.getControlFlowNode().getASuccessor+() = otherSecond.getControlFlowNode()
|
v1 != v2
)

View File

@@ -17,7 +17,7 @@ import Common
from SwitchStmt s, Stmt c
where
c = s.getACase() and
not c.(ControlFlowNode).getASuccessor() instanceof SwitchCase and
not c.getControlFlowNode().getASuccessor().asStmt() instanceof SwitchCase and
not s.(Annotatable).suppressesWarningsAbout("fallthrough") and
mayDropThroughWithoutComment(s, c)
select c,

View File

@@ -24,15 +24,15 @@ predicate switchCaseControlFlowPlus(SwitchStmt switch, BasicBlock b1, BasicBlock
exists(BasicBlock mid |
switchCaseControlFlowPlus(switch, mid, b2) and
switchCaseControlFlow(switch, b1, mid) and
not mid.getFirstNode() = switch.getACase()
not mid.getFirstNode().asStmt() = switch.getACase()
)
}
predicate mayDropThroughWithoutComment(SwitchStmt switch, Stmt switchCase) {
switchCase = switch.getACase() and
exists(Stmt other, BasicBlock b1, BasicBlock b2 |
b1.getFirstNode() = switchCase and
b2.getFirstNode() = other and
b1.getFirstNode().asStmt() = switchCase and
b2.getFirstNode().asStmt() = other and
switchCaseControlFlowPlus(switch, b1, b2) and
other = switch.getACase() and
not fallThroughCommented(other)

View File

@@ -0,0 +1,3 @@
## 1.1.11
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.1.10
lastReleaseVersion: 1.1.11

View File

@@ -55,7 +55,7 @@ module SpringViewManipulationConfig implements DataFlow::ConfigSig {
// a = "redirect:" + taint`
// ```
exists(AddExpr e, StringLiteral sl |
node.asExpr() = e.getControlFlowNode().getASuccessor*() and
node.asExpr() = e.getControlFlowNode().getASuccessor*().asExpr() and
sl = e.getLeftOperand*() and
sl.getValue().matches(["redirect:%", "ajaxredirect:%", "forward:%"])
)

View File

@@ -1,5 +1,5 @@
name: codeql/java-queries
version: 1.1.10
version: 1.1.11
groups:
- java
- queries

View File

@@ -1,3 +1,3 @@
import java
import TestUtilities.InlineFlowTest
import utils.test.InlineFlowTest
import DefaultFlowTest

View File

@@ -1,8 +1,8 @@
| Test.kt:3:8:80:1 | { ... } | 0 | Test.kt:3:8:80:1 | { ... } |
| Test.kt:3:8:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) |
| Test.kt:3:8:80:1 | { ... } | 2 | Test.kt:3:8:80:1 | { ... } |
| Test.kt:3:8:80:1 | { ... } | 3 | Test.kt:3:8:80:1 | Test |
| Test.kt:4:2:79:2 | test | 0 | Test.kt:4:2:79:2 | test |
| Test.kt:3:8:80:1 | { ... } | 3 | Test.kt:3:8:80:1 | Exit |
| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } |
| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:7:5:7 | var ...; |
| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 |
@@ -102,7 +102,7 @@
| Test.kt:43:3:43:3 | <Expr>; | 8 | Test.kt:77:3:77:8 | ...=... |
| Test.kt:43:3:43:3 | <Expr>; | 9 | Test.kt:78:3:78:8 | INSTANCE |
| Test.kt:43:3:43:3 | <Expr>; | 10 | Test.kt:78:3:78:8 | return ... |
| Test.kt:82:1:89:1 | t1 | 0 | Test.kt:82:1:89:1 | t1 |
| Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } |
| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... |
| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } |
@@ -117,7 +117,7 @@
| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } |
| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 |
| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... |
| Test.kt:91:1:98:1 | t2 | 0 | Test.kt:91:1:98:1 | t2 |
| Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } |
| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... |
| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } |
@@ -132,7 +132,7 @@
| Test.kt:95:4:97:2 | catch (...) | 2 | Test.kt:95:36:97:2 | { ... } |
| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 |
| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... |
| Test.kt:100:1:110:1 | fn | 0 | Test.kt:100:1:110:1 | fn |
| Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } |
| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | <Expr>; |
| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... |
@@ -165,7 +165,7 @@
| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | <Expr>; |
| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" |
| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) |
| Test.kt:112:1:116:1 | fn | 0 | Test.kt:112:1:116:1 | fn |
| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } |
| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | <Expr>; |
| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... |
@@ -174,7 +174,7 @@
| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x |
| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y |
| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } |
| Test.kt:118:1:124:1 | fn_when | 0 | Test.kt:118:1:124:1 | fn_when |
| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } |
| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... |

View File

@@ -3,5 +3,5 @@ import default
from BasicBlock b, int i, ControlFlowNode n
where
b.getNode(i) = n and
b.getFile().(CompilationUnit).fromSource()
b.getLocation().getFile().(CompilationUnit).fromSource()
select b, i, n

View File

@@ -1,4 +1,4 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | test |
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:18:3:18:3 | <Expr>; |
@@ -9,7 +9,7 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:9:38:9 | x |
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:3 | <Expr>; |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:4:2:79:2 | test |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:4:2:79:2 | Exit |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:21:3:24:9 | ... -> ... |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:22:4:22:4 | <Expr>; |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:30:15:33:3 | { ... } |
@@ -27,13 +27,13 @@
| Test.kt:35:3:35:3 | <Expr>; | Test.kt:43:3:43:3 | <Expr>; |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:3 | <Expr>; |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | t1 |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | t2 |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:33:103:5 | { ... } |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | <Expr>; |
@@ -45,11 +45,11 @@
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | fn_when |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } |

View File

@@ -4,7 +4,7 @@
| Test.kt:11:14:14:3 | { ... } | Test.kt:18:3:18:3 | <Expr>; |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:21:3:24:9 | ... -> ... |
| Test.kt:18:3:18:3 | <Expr>; | Test.kt:22:4:22:4 | <Expr>; |
| Test.kt:21:3:24:9 | ... -> ... | Test.kt:4:2:79:2 | test |
| Test.kt:21:3:24:9 | ... -> ... | Test.kt:4:2:79:2 | Exit |
| Test.kt:22:4:22:4 | <Expr>; | Test.kt:30:15:33:3 | { ... } |
| Test.kt:22:4:22:4 | <Expr>; | Test.kt:35:3:35:3 | <Expr>; |
| Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:3 | <Expr>; |
@@ -12,34 +12,34 @@
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:3 | <Expr>; |
| Test.kt:38:16:41:3 | { ... } | Test.kt:38:9:38:9 | x |
| Test.kt:43:3:43:3 | <Expr>; | Test.kt:4:2:79:2 | test |
| Test.kt:43:3:43:3 | <Expr>; | Test.kt:4:2:79:2 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | t1 |
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | t1 |
| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Exit |
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | t2 |
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | t2 |
| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Exit |
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | <Expr>; |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
| Test.kt:101:22:101:22 | y | Test.kt:105:5:109:5 | <Expr>; |
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | fn |
| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | fn |
| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Exit |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:118:1:124:1 | fn_when |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:118:1:124:1 | Exit |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:123:8:123:10 | { ... } |
| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | fn_when |
| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | fn_when |
| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Exit |
| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Exit |

View File

@@ -1,26 +1,19 @@
#select
| Test.kt:0:0:0:0 | TestKt | Class | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | Test | Class | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:8:80:1 | { ... } | BlockStmt |
| Test.kt:3:8:80:1 | Test | Constructor | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:8:80:1 | Exit | Constructor | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt |
| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:8:80:1 | Test | Constructor |
| Test.kt:4:2:79:2 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:4:2:79:2 | test | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:8:80:1 | Exit | Constructor |
| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:7:5:7 | int x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral |
| Test.kt:5:7:5:7 | x | LocalVariableDeclExpr | Test.kt:6:7:6:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:16:5:16 | 0 | IntegerLiteral | Test.kt:5:7:5:7 | x | LocalVariableDeclExpr |
| Test.kt:6:7:6:7 | long y | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:6:7:6:7 | var ...; | LocalVariableDeclStmt | Test.kt:6:17:6:18 | 50 | LongLiteral |
| Test.kt:6:7:6:7 | y | LocalVariableDeclExpr | Test.kt:7:7:7:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:6:17:6:18 | 50 | LongLiteral | Test.kt:6:7:6:7 | y | LocalVariableDeclExpr |
| Test.kt:7:7:7:7 | int z | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:7:7:7:7 | var ...; | LocalVariableDeclStmt | Test.kt:7:16:7:16 | 0 | IntegerLiteral |
| Test.kt:7:7:7:7 | z | LocalVariableDeclExpr | Test.kt:8:7:8:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:7:16:7:16 | 0 | IntegerLiteral | Test.kt:7:7:7:7 | z | LocalVariableDeclExpr |
| Test.kt:8:7:8:7 | int w | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:8:7:8:7 | var ...; | LocalVariableDeclStmt | Test.kt:8:16:8:16 | 0 | IntegerLiteral |
| Test.kt:8:7:8:7 | w | LocalVariableDeclExpr | Test.kt:11:3:16:3 | <Expr>; | ExprStmt |
| Test.kt:8:16:8:16 | 0 | IntegerLiteral | Test.kt:8:7:8:7 | w | LocalVariableDeclExpr |
@@ -35,20 +28,16 @@
| Test.kt:11:11:11:11 | 0 | IntegerLiteral | Test.kt:11:7:11:11 | ... > ... | GTExpr |
| Test.kt:11:14:14:3 | { ... } | BlockStmt | Test.kt:12:4:12:4 | <Expr>; | ExprStmt |
| Test.kt:12:4:12:4 | <Expr>; | ExprStmt | Test.kt:12:8:12:9 | 20 | LongLiteral |
| Test.kt:12:4:12:4 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:12:4:12:9 | ...=... | AssignExpr | Test.kt:13:4:13:4 | <Expr>; | ExprStmt |
| Test.kt:12:8:12:9 | 20 | LongLiteral | Test.kt:12:4:12:9 | ...=... | AssignExpr |
| Test.kt:13:4:13:4 | <Expr>; | ExprStmt | Test.kt:13:8:13:9 | 10 | IntegerLiteral |
| Test.kt:13:4:13:4 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:13:4:13:9 | ...=... | AssignExpr | Test.kt:18:3:18:3 | <Expr>; | ExprStmt |
| Test.kt:13:8:13:9 | 10 | IntegerLiteral | Test.kt:13:4:13:9 | ...=... | AssignExpr |
| Test.kt:14:10:16:3 | { ... } | BlockStmt | Test.kt:15:4:15:4 | <Expr>; | ExprStmt |
| Test.kt:15:4:15:4 | <Expr>; | ExprStmt | Test.kt:15:8:15:9 | 30 | LongLiteral |
| Test.kt:15:4:15:4 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:15:4:15:9 | ...=... | AssignExpr | Test.kt:18:3:18:3 | <Expr>; | ExprStmt |
| Test.kt:15:8:15:9 | 30 | LongLiteral | Test.kt:15:4:15:9 | ...=... | AssignExpr |
| Test.kt:18:3:18:3 | <Expr>; | ExprStmt | Test.kt:18:7:18:7 | 0 | IntegerLiteral |
| Test.kt:18:3:18:3 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:18:3:18:7 | ...=... | AssignExpr | Test.kt:21:3:24:9 | <Expr>; | ExprStmt |
| Test.kt:18:7:18:7 | 0 | IntegerLiteral | Test.kt:18:3:18:7 | ...=... | AssignExpr |
| Test.kt:21:3:24:9 | ... -> ... | WhenBranch | Test.kt:21:3:24:9 | true | BooleanLiteral |
@@ -61,13 +50,11 @@
| Test.kt:21:6:21:10 | ... < ... | LTExpr | Test.kt:22:4:22:4 | <Expr>; | ExprStmt |
| Test.kt:21:10:21:10 | 0 | IntegerLiteral | Test.kt:21:6:21:10 | ... < ... | LTExpr |
| Test.kt:22:4:22:4 | <Expr>; | ExprStmt | Test.kt:22:8:22:9 | 40 | LongLiteral |
| Test.kt:22:4:22:4 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:22:4:22:9 | ...=... | AssignExpr | Test.kt:27:3:27:3 | <Expr>; | ExprStmt |
| Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr |
| Test.kt:24:4:24:9 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt |
| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | test | Method |
| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:27:3:27:3 | <Expr>; | ExprStmt | Test.kt:27:7:27:8 | 10 | IntegerLiteral |
| Test.kt:27:3:27:3 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | <Expr>; | ExprStmt |
| Test.kt:27:7:27:8 | 10 | IntegerLiteral | Test.kt:27:3:27:8 | ...=... | AssignExpr |
| Test.kt:30:3:33:3 | ... -> ... | WhenBranch | Test.kt:30:7:30:7 | x | VarAccess |
@@ -79,15 +66,12 @@
| Test.kt:30:12:30:12 | 0 | IntegerLiteral | Test.kt:30:7:30:12 | ... (value equals) ... | ValueEQExpr |
| Test.kt:30:15:33:3 | { ... } | BlockStmt | Test.kt:31:4:31:4 | <Expr>; | ExprStmt |
| Test.kt:31:4:31:4 | <Expr>; | ExprStmt | Test.kt:31:8:31:9 | 60 | LongLiteral |
| Test.kt:31:4:31:4 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:31:4:31:9 | ...=... | AssignExpr | Test.kt:32:4:32:4 | <Expr>; | ExprStmt |
| Test.kt:31:8:31:9 | 60 | LongLiteral | Test.kt:31:4:31:9 | ...=... | AssignExpr |
| Test.kt:32:4:32:4 | <Expr>; | ExprStmt | Test.kt:32:8:32:9 | 10 | IntegerLiteral |
| Test.kt:32:4:32:4 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:32:4:32:9 | ...=... | AssignExpr | Test.kt:35:3:35:3 | <Expr>; | ExprStmt |
| Test.kt:32:8:32:9 | 10 | IntegerLiteral | Test.kt:32:4:32:9 | ...=... | AssignExpr |
| Test.kt:35:3:35:3 | <Expr>; | ExprStmt | Test.kt:35:7:35:8 | 20 | IntegerLiteral |
| Test.kt:35:3:35:3 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:35:3:35:8 | ...=... | AssignExpr | Test.kt:38:3:41:3 | while (...) | WhileStmt |
| Test.kt:35:7:35:8 | 20 | IntegerLiteral | Test.kt:35:3:35:8 | ...=... | AssignExpr |
| Test.kt:38:3:41:3 | while (...) | WhileStmt | Test.kt:38:9:38:9 | x | VarAccess |
@@ -97,90 +81,65 @@
| Test.kt:38:13:38:13 | 0 | IntegerLiteral | Test.kt:38:9:38:13 | ... > ... | GTExpr |
| Test.kt:38:16:41:3 | { ... } | BlockStmt | Test.kt:39:4:39:4 | <Expr>; | ExprStmt |
| Test.kt:39:4:39:4 | <Expr>; | ExprStmt | Test.kt:39:8:39:9 | 10 | LongLiteral |
| Test.kt:39:4:39:4 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:39:4:39:9 | ...=... | AssignExpr | Test.kt:40:4:40:6 | <Expr>; | ExprStmt |
| Test.kt:39:8:39:9 | 10 | LongLiteral | Test.kt:39:4:39:9 | ...=... | AssignExpr |
| Test.kt:40:4:40:4 | <Expr>; | ExprStmt | Test.kt:40:4:40:6 | tmp0 | VarAccess |
| Test.kt:40:4:40:4 | x | VarAccess | Test.kt:40:4:40:6 | tmp0 | LocalVariableDeclExpr |
| Test.kt:40:4:40:4 | x | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | ...=... | AssignExpr | Test.kt:40:4:40:6 | <Expr>; | ExprStmt |
| Test.kt:40:4:40:6 | <Expr>; | ExprStmt | Test.kt:40:4:40:6 | <Stmt> | StmtExpr |
| Test.kt:40:4:40:6 | <Expr>; | ExprStmt | Test.kt:40:4:40:6 | tmp0 | VarAccess |
| Test.kt:40:4:40:6 | <Stmt> | StmtExpr | Test.kt:40:4:40:6 | { ... } | BlockStmt |
| Test.kt:40:4:40:6 | <implicit coercion to unit> | ImplicitCoercionToUnitExpr | Test.kt:38:9:38:9 | x | VarAccess |
| Test.kt:40:4:40:6 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | dec(...) | MethodCall | Test.kt:40:4:40:6 | ...=... | AssignExpr |
| Test.kt:40:4:40:6 | int tmp0 | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | tmp0 | LocalVariableDeclExpr | Test.kt:40:4:40:4 | <Expr>; | ExprStmt |
| Test.kt:40:4:40:6 | tmp0 | VarAccess | Test.kt:40:4:40:6 | <implicit coercion to unit> | ImplicitCoercionToUnitExpr |
| Test.kt:40:4:40:6 | tmp0 | VarAccess | Test.kt:40:4:40:6 | dec(...) | MethodCall |
| Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | Test.kt:40:4:40:4 | x | VarAccess |
| Test.kt:40:4:40:6 | { ... } | BlockStmt | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt |
| Test.kt:43:3:43:3 | <Expr>; | ExprStmt | Test.kt:43:7:43:8 | 30 | IntegerLiteral |
| Test.kt:43:3:43:3 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:43:3:43:8 | ...=... | AssignExpr | Test.kt:73:3:73:3 | <Expr>; | ExprStmt |
| Test.kt:43:7:43:8 | 30 | IntegerLiteral | Test.kt:43:3:43:8 | ...=... | AssignExpr |
| Test.kt:73:3:73:3 | <Expr>; | ExprStmt | Test.kt:73:7:73:8 | 50 | IntegerLiteral |
| Test.kt:73:3:73:3 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:73:3:73:8 | ...=... | AssignExpr | Test.kt:77:3:77:3 | <Expr>; | ExprStmt |
| Test.kt:73:7:73:8 | 50 | IntegerLiteral | Test.kt:73:3:73:8 | ...=... | AssignExpr |
| Test.kt:77:3:77:3 | <Expr>; | ExprStmt | Test.kt:77:7:77:8 | 40 | IntegerLiteral |
| Test.kt:77:3:77:3 | w | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:3:78:8 | INSTANCE | VarAccess |
| Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr |
| Test.kt:78:3:78:8 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt |
| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | test | Method |
| Test.kt:82:1:89:1 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:1:89:1 | t1 | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:8:82:13 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:8:82:13 | o | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt |
| Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt |
| Test.kt:83:6:86:2 | { ... } | BlockStmt | Test.kt:84:7:84:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:84:7:84:7 | int x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:84:7:84:7 | var ...; | LocalVariableDeclStmt | Test.kt:84:11:84:11 | o | VarAccess |
| Test.kt:84:7:84:7 | x | LocalVariableDeclExpr | Test.kt:85:10:85:10 | 1 | IntegerLiteral |
| Test.kt:84:11:84:11 | o | VarAccess | Test.kt:84:11:84:18 | (...)... | CastExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:84:7:84:7 | x | LocalVariableDeclExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
| Test.kt:84:11:84:18 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | t1 | Method |
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
| Test.kt:86:11:86:31 | ClassCastException | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:86:11:86:31 | ClassCastException e | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | t1 | Method |
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt |
| Test.kt:91:1:98:1 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:1:98:1 | t2 | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:8:91:14 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:8:91:14 | o | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt |
| Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt |
| Test.kt:92:6:95:2 | { ... } | BlockStmt | Test.kt:93:7:93:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:93:7:93:7 | Object x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:93:7:93:7 | var ...; | LocalVariableDeclStmt | Test.kt:93:11:93:11 | o | VarAccess |
| Test.kt:93:7:93:7 | x | LocalVariableDeclExpr | Test.kt:94:10:94:10 | 1 | IntegerLiteral |
| Test.kt:93:11:93:11 | o | VarAccess | Test.kt:93:12:93:13 | ...!! | NotNullExpr |
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:93:7:93:7 | x | LocalVariableDeclExpr |
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | t2 | Method |
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
| Test.kt:95:11:95:33 | NullPointerException | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:95:11:95:33 | NullPointerException e | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | t2 | Method |
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt |
| Test.kt:100:1:110:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:1:110:1 | fn | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:8:100:13 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:8:100:13 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:16:100:22 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:16:100:22 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | <Expr>; | ExprStmt |
| Test.kt:101:5:103:5 | ... -> ... | WhenBranch | Test.kt:101:9:101:30 | ... && ... | AndLogicalExpr |
| Test.kt:101:5:103:5 | <Expr>; | ExprStmt | Test.kt:101:5:103:5 | when ... | WhenExpr |
@@ -195,8 +154,7 @@
| Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr | Test.kt:105:5:109:5 | <Expr>; | ExprStmt |
| Test.kt:101:27:101:30 | null | NullLiteral | Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr |
| Test.kt:101:33:103:5 | { ... } | BlockStmt | Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr |
| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:102:15:102:25 | Exception | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr | Test.kt:102:9:102:25 | throw ... | ThrowStmt |
| Test.kt:105:5:109:5 | <Expr>; | ExprStmt | Test.kt:105:5:109:5 | when ... | WhenExpr |
| Test.kt:105:5:109:5 | when ... | WhenExpr | Test.kt:105:9:107:5 | ... -> ... | WhenBranch |
@@ -207,41 +165,29 @@
| Test.kt:105:14:105:17 | null | NullLiteral | Test.kt:105:9:105:17 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:105:20:107:5 | { ... } | BlockStmt | Test.kt:106:9:106:29 | <Expr>; | ExprStmt |
| Test.kt:106:9:106:29 | <Expr>; | ExprStmt | Test.kt:106:17:106:28 | "x not null" | StringLiteral |
| Test.kt:106:9:106:29 | ConsoleKt | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:106:17:106:28 | "x not null" | StringLiteral | Test.kt:106:9:106:29 | println(...) | MethodCall |
| Test.kt:107:16:107:16 | y | VarAccess | Test.kt:107:21:107:24 | null | NullLiteral |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:107:27:109:5 | { ... } | BlockStmt |
| Test.kt:107:16:109:5 | ... -> ... | WhenBranch | Test.kt:107:16:107:16 | y | VarAccess |
| Test.kt:107:21:107:24 | null | NullLiteral | Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:107:27:109:5 | { ... } | BlockStmt | Test.kt:108:9:108:29 | <Expr>; | ExprStmt |
| Test.kt:108:9:108:29 | <Expr>; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral |
| Test.kt:108:9:108:29 | ConsoleKt | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall |
| Test.kt:112:1:116:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:1:116:1 | fn | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:8:112:17 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:8:112:17 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:20:112:29 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:20:112:29 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | <Expr>; | ExprStmt |
| Test.kt:113:5:115:5 | ... -> ... | WhenBranch | Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr |
| Test.kt:113:5:115:5 | <Expr>; | ExprStmt | Test.kt:113:5:115:5 | when ... | WhenExpr |
| Test.kt:113:5:115:5 | when ... | WhenExpr | Test.kt:113:5:115:5 | ... -> ... | WhenBranch |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:113:14:113:14 | y | VarAccess |
| Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr | Test.kt:113:9:113:9 | x | VarAccess |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt |
| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:118:1:124:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:1:124:1 | fn_when | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:13:118:22 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:13:118:22 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:25:118:34 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:25:118:34 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | <Expr>; | ExprStmt |
| Test.kt:119:2:123:12 | <Expr>; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr |
| Test.kt:119:2:123:12 | when ... | WhenExpr | Test.kt:120:3:123:10 | ... -> ... | WhenBranch |
@@ -251,11 +197,11 @@
| Test.kt:121:4:121:4 | x | VarAccess | Test.kt:122:12:122:16 | ... -> ... | WhenBranch |
| Test.kt:121:4:121:9 | ... -> ... | WhenBranch | Test.kt:121:4:121:4 | x | VarAccess |
| Test.kt:121:9:121:9 | <Expr>; | ExprStmt | Test.kt:121:9:121:9 | y | VarAccess |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:123:8:123:10 | { ... } | BlockStmt |
| Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral |
| Test.kt:122:12:122:16 | <Expr>; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral |
| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | <Expr>; | ExprStmt |
| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Exit | Method |
missingSuccessor

View File

@@ -21,7 +21,7 @@ class YesMaybeControlFlowNode extends MaybeControlFlowNode {
override Location getLocation() { result = c.getLocation() }
override string getPrimaryQlClasses() { result = c.getPrimaryQlClasses() }
override string getPrimaryQlClasses() { result = c.getAstNode().getPrimaryQlClasses() }
}
class NoMaybeControlFlowNode extends MaybeControlFlowNode {
@@ -43,12 +43,12 @@ MaybeControlFlowNode maybeSuccessor(ControlFlowNode n) {
from ControlFlowNode n, MaybeControlFlowNode m
where
m = maybeSuccessor(n) and
n.getFile().(CompilationUnit).fromSource()
select n, n.getPrimaryQlClasses(), m, m.getPrimaryQlClasses()
n.getLocation().getFile().(CompilationUnit).fromSource()
select n, n.getAstNode().getPrimaryQlClasses(), m, m.getPrimaryQlClasses()
query predicate missingSuccessor(Expr n) {
maybeSuccessor(n) instanceof NoMaybeControlFlowNode and
n.getFile().(CompilationUnit).fromSource() and
not n instanceof TypeAccess and
not n instanceof VarWrite
query predicate missingSuccessor(Expr e) {
maybeSuccessor(e.getControlFlowNode()) instanceof NoMaybeControlFlowNode and
e.getFile().(CompilationUnit).fromSource() and
not e instanceof TypeAccess and
not e instanceof VarWrite
}

View File

@@ -2,5 +2,5 @@ import default
import semmle.code.java.controlflow.Dominance
from Stmt pre, Stmt post
where strictlyDominates(pre, post)
where strictlyDominates(pre.getControlFlowNode(), post.getControlFlowNode())
select pre, post

View File

@@ -2,5 +2,5 @@ import default
import semmle.code.java.controlflow.Dominance
from Stmt pre, Stmt post
where strictlyPostDominates(post, pre)
where strictlyPostDominates(post.getControlFlowNode(), pre.getControlFlowNode())
select post, pre

View File

@@ -4,6 +4,6 @@ import semmle.code.java.controlflow.Dominance
from IfStmt i, BlockStmt b
where
b = i.getThen() and
dominates(i.getThen(), b) and
dominates(i.getElse(), b)
dominates(i.getThen().getControlFlowNode(), b.getControlFlowNode()) and
dominates(i.getElse().getControlFlowNode(), b.getControlFlowNode())
select i, b

View File

@@ -17,5 +17,5 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node
where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
dominanceCounterExample(c.getBody(), dom, node)
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node

View File

@@ -3,14 +3,14 @@ import default
import semmle.code.java.controlflow.Dominance
ControlFlowNode reachableIn(Method func) {
result = func.getBody() or
result = func.getBody().getControlFlowNode() or
result = reachableIn(func).getASuccessor()
}
from Method func, ControlFlowNode entry, ControlFlowNode node
where
func.getBody() = entry and
func.getBody().getControlFlowNode() = entry and
reachableIn(func) = node and
entry != node and
not strictlyDominates(func.getBody(), node)
not strictlyDominates(func.getBody().getControlFlowNode(), node)
select func, node

View File

@@ -44,7 +44,7 @@
| Test.kt:21:3:24:11 | true | Test.kt:24:11:24:11 | z |
| Test.kt:21:3:24:11 | when ... | Test.kt:21:3:24:11 | ... -> ... |
| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | test |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Exit |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:21:3:24:11 | ... -> ... |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:4 | <Expr>; |
| Test.kt:21:11:21:11 | 0 | Test.kt:21:7:21:11 | ... < ... |
@@ -142,7 +142,7 @@
| Test.kt:92:4:93:9 | <Expr>; | Test.kt:92:4:93:9 | when ... |
| Test.kt:92:4:93:9 | when ... | Test.kt:92:4:93:9 | ... -> ... |
| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | test2 |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Exit |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | <Expr>; |
| Test.kt:92:13:92:14 | 10 | Test.kt:92:8:92:14 | ... (value equals) ... |

View File

@@ -4,13 +4,13 @@ import semmle.code.java.controlflow.Dominance
/** transitive dominance */
ControlFlowNode reachableIn(Method func) {
result = func.getBody() or
result = func.getBody().getControlFlowNode() or
result = reachableIn(func).getASuccessor()
}
from Method func, ControlFlowNode node
where
node = reachableIn(func) and
node != func.getBody() and
node != func.getBody().getControlFlowNode() and
not iDominates(_, node)
select func, node

View File

@@ -5,7 +5,7 @@ class PathTestConf extends ActionConfiguration {
PathTestConf() { this = "PathTestConf" }
override predicate isAction(ControlFlowNode node) {
node.(MethodCall).getMethod().hasName("action")
node.asExpr().(MethodCall).getMethod().hasName("action")
}
}

View File

@@ -1,4 +1,4 @@
import java
import TestUtilities.InlineFlowTest
import utils.test.InlineFlowTest
import DefaultFlowTest
import TaintFlow::PathGraph

View File

@@ -1,8 +1,8 @@
| Test.kt:3:1:80:1 | { ... } | 0 | Test.kt:3:1:80:1 | { ... } |
| Test.kt:3:1:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) |
| Test.kt:3:1:80:1 | { ... } | 2 | Test.kt:3:1:80:1 | { ... } |
| Test.kt:3:1:80:1 | { ... } | 3 | Test.kt:3:1:80:1 | Test |
| Test.kt:4:2:79:2 | test | 0 | Test.kt:4:2:79:2 | test |
| Test.kt:3:1:80:1 | { ... } | 3 | Test.kt:3:1:80:1 | Exit |
| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } |
| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:3:5:16 | var ...; |
| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 |
@@ -102,7 +102,7 @@
| Test.kt:43:3:43:8 | <Expr>; | 8 | Test.kt:77:3:77:8 | ...=... |
| Test.kt:43:3:43:8 | <Expr>; | 9 | Test.kt:78:9:78:9 | INSTANCE |
| Test.kt:43:3:43:8 | <Expr>; | 10 | Test.kt:78:3:78:8 | return ... |
| Test.kt:82:1:89:1 | t1 | 0 | Test.kt:82:1:89:1 | t1 |
| Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } |
| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... |
| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } |
@@ -117,7 +117,7 @@
| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } |
| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 |
| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... |
| Test.kt:91:1:98:1 | t2 | 0 | Test.kt:91:1:98:1 | t2 |
| Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } |
| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... |
| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } |
@@ -132,7 +132,7 @@
| Test.kt:95:4:97:2 | catch (...) | 2 | Test.kt:95:36:97:2 | { ... } |
| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 |
| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... |
| Test.kt:100:1:110:1 | fn | 0 | Test.kt:100:1:110:1 | fn |
| Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } |
| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | <Expr>; |
| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... |
@@ -165,7 +165,7 @@
| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | <Expr>; |
| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" |
| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) |
| Test.kt:112:1:116:1 | fn | 0 | Test.kt:112:1:116:1 | fn |
| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } |
| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | <Expr>; |
| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... |
@@ -174,7 +174,7 @@
| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x |
| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y |
| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } |
| Test.kt:118:1:124:1 | fn_when | 0 | Test.kt:118:1:124:1 | fn_when |
| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } |
| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... |

View File

@@ -3,5 +3,5 @@ import default
from BasicBlock b, int i, ControlFlowNode n
where
b.getNode(i) = n and
b.getFile().(CompilationUnit).fromSource()
b.getLocation().getFile().(CompilationUnit).fromSource()
select b, i, n

View File

@@ -1,4 +1,4 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | test |
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... |
| Test.kt:4:13:79:2 | { ... } | Test.kt:18:3:18:7 | <Expr>; |
@@ -9,7 +9,7 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:9:38:9 | x |
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:8 | <Expr>; |
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:4:2:79:2 | test |
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:4:2:79:2 | Exit |
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:22:4:22:9 | <Expr>; |
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:24:4:24:9 | ... -> ... |
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:30:15:33:3 | { ... } |
@@ -27,13 +27,13 @@
| Test.kt:35:3:35:8 | <Expr>; | Test.kt:43:3:43:8 | <Expr>; |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:8 | <Expr>; |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | t1 |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | t2 |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:33:103:5 | { ... } |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | <Expr>; |
@@ -45,11 +45,11 @@
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | fn_when |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } |

View File

@@ -6,40 +6,40 @@
| Test.kt:18:3:18:7 | <Expr>; | Test.kt:24:4:24:9 | ... -> ... |
| Test.kt:22:4:22:9 | <Expr>; | Test.kt:30:15:33:3 | { ... } |
| Test.kt:22:4:22:9 | <Expr>; | Test.kt:35:3:35:8 | <Expr>; |
| Test.kt:24:4:24:9 | ... -> ... | Test.kt:4:2:79:2 | test |
| Test.kt:24:4:24:9 | ... -> ... | Test.kt:4:2:79:2 | Exit |
| Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:8 | <Expr>; |
| Test.kt:35:3:35:8 | <Expr>; | Test.kt:38:9:38:9 | x |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:8 | <Expr>; |
| Test.kt:38:16:41:3 | { ... } | Test.kt:38:9:38:9 | x |
| Test.kt:43:3:43:8 | <Expr>; | Test.kt:4:2:79:2 | test |
| Test.kt:43:3:43:8 | <Expr>; | Test.kt:4:2:79:2 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | t1 |
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | t1 |
| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Exit |
| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | t2 |
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | t2 |
| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Exit |
| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | <Expr>; |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
| Test.kt:101:22:101:22 | y | Test.kt:105:5:109:5 | <Expr>; |
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | <Expr>; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | fn |
| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | fn |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | fn |
| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Exit |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | fn |
| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | <Expr>; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:118:1:124:1 | fn_when |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:118:1:124:1 | Exit |
| Test.kt:121:9:121:9 | <Expr>; | Test.kt:123:8:123:10 | { ... } |
| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | fn_when |
| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | fn_when |
| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Exit |
| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Exit |

View File

@@ -1,26 +1,19 @@
#select
| Test.kt:0:0:0:0 | TestKt | Class | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | Test | Class | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | Test | Constructor | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | Exit | Constructor | file://:0:0:0:0 | <none> | <none> |
| Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:1:80:1 | { ... } | BlockStmt |
| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | Test | Constructor |
| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | Exit | Constructor |
| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt |
| Test.kt:4:2:79:2 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:4:2:79:2 | test | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:3:5:16 | int x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral |
| Test.kt:5:3:5:16 | x | LocalVariableDeclExpr | Test.kt:6:3:6:18 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:16:5:16 | 0 | IntegerLiteral | Test.kt:5:3:5:16 | x | LocalVariableDeclExpr |
| Test.kt:6:3:6:18 | long y | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:6:3:6:18 | var ...; | LocalVariableDeclStmt | Test.kt:6:17:6:18 | 50 | LongLiteral |
| Test.kt:6:3:6:18 | y | LocalVariableDeclExpr | Test.kt:7:3:7:16 | var ...; | LocalVariableDeclStmt |
| Test.kt:6:17:6:18 | 50 | LongLiteral | Test.kt:6:3:6:18 | y | LocalVariableDeclExpr |
| Test.kt:7:3:7:16 | int z | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:7:3:7:16 | var ...; | LocalVariableDeclStmt | Test.kt:7:16:7:16 | 0 | IntegerLiteral |
| Test.kt:7:3:7:16 | z | LocalVariableDeclExpr | Test.kt:8:3:8:16 | var ...; | LocalVariableDeclStmt |
| Test.kt:7:16:7:16 | 0 | IntegerLiteral | Test.kt:7:3:7:16 | z | LocalVariableDeclExpr |
| Test.kt:8:3:8:16 | int w | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:8:3:8:16 | var ...; | LocalVariableDeclStmt | Test.kt:8:16:8:16 | 0 | IntegerLiteral |
| Test.kt:8:3:8:16 | w | LocalVariableDeclExpr | Test.kt:11:3:16:3 | <Expr>; | ExprStmt |
| Test.kt:8:16:8:16 | 0 | IntegerLiteral | Test.kt:8:3:8:16 | w | LocalVariableDeclExpr |
@@ -34,22 +27,18 @@
| Test.kt:11:14:14:3 | { ... } | BlockStmt | Test.kt:12:4:12:9 | <Expr>; | ExprStmt |
| Test.kt:12:4:12:9 | ...=... | AssignExpr | Test.kt:13:4:13:9 | <Expr>; | ExprStmt |
| Test.kt:12:4:12:9 | <Expr>; | ExprStmt | Test.kt:12:8:12:9 | 20 | LongLiteral |
| Test.kt:12:4:12:9 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:12:8:12:9 | 20 | LongLiteral | Test.kt:12:4:12:9 | ...=... | AssignExpr |
| Test.kt:13:4:13:9 | ...=... | AssignExpr | Test.kt:18:3:18:7 | <Expr>; | ExprStmt |
| Test.kt:13:4:13:9 | <Expr>; | ExprStmt | Test.kt:13:8:13:9 | 10 | IntegerLiteral |
| Test.kt:13:4:13:9 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:13:8:13:9 | 10 | IntegerLiteral | Test.kt:13:4:13:9 | ...=... | AssignExpr |
| Test.kt:14:10:16:3 | ... -> ... | WhenBranch | Test.kt:14:10:16:3 | true | BooleanLiteral |
| Test.kt:14:10:16:3 | true | BooleanLiteral | Test.kt:14:10:16:3 | { ... } | BlockStmt |
| Test.kt:14:10:16:3 | { ... } | BlockStmt | Test.kt:15:4:15:9 | <Expr>; | ExprStmt |
| Test.kt:15:4:15:9 | ...=... | AssignExpr | Test.kt:18:3:18:7 | <Expr>; | ExprStmt |
| Test.kt:15:4:15:9 | <Expr>; | ExprStmt | Test.kt:15:8:15:9 | 30 | LongLiteral |
| Test.kt:15:4:15:9 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:15:8:15:9 | 30 | LongLiteral | Test.kt:15:4:15:9 | ...=... | AssignExpr |
| Test.kt:18:3:18:7 | ...=... | AssignExpr | Test.kt:21:3:24:9 | <Expr>; | ExprStmt |
| Test.kt:18:3:18:7 | <Expr>; | ExprStmt | Test.kt:18:7:18:7 | 0 | IntegerLiteral |
| Test.kt:18:3:18:7 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:18:7:18:7 | 0 | IntegerLiteral | Test.kt:18:3:18:7 | ...=... | AssignExpr |
| Test.kt:21:3:24:9 | <Expr>; | ExprStmt | Test.kt:21:3:24:9 | when ... | WhenExpr |
| Test.kt:21:3:24:9 | when ... | WhenExpr | Test.kt:21:6:22:9 | ... -> ... | WhenBranch |
@@ -60,15 +49,13 @@
| Test.kt:21:10:21:10 | 0 | IntegerLiteral | Test.kt:21:6:21:10 | ... < ... | LTExpr |
| Test.kt:22:4:22:9 | ...=... | AssignExpr | Test.kt:27:3:27:8 | <Expr>; | ExprStmt |
| Test.kt:22:4:22:9 | <Expr>; | ExprStmt | Test.kt:22:8:22:9 | 40 | LongLiteral |
| Test.kt:22:4:22:9 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr |
| Test.kt:24:4:24:9 | ... -> ... | WhenBranch | Test.kt:24:4:24:9 | true | BooleanLiteral |
| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | test | Method |
| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:24:4:24:9 | true | BooleanLiteral | Test.kt:24:10:24:10 | INSTANCE | VarAccess |
| Test.kt:24:10:24:10 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt |
| Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | <Expr>; | ExprStmt |
| Test.kt:27:3:27:8 | <Expr>; | ExprStmt | Test.kt:27:7:27:8 | 10 | IntegerLiteral |
| Test.kt:27:3:27:8 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:27:7:27:8 | 10 | IntegerLiteral | Test.kt:27:3:27:8 | ...=... | AssignExpr |
| Test.kt:30:3:33:3 | <Expr>; | ExprStmt | Test.kt:30:3:33:3 | when ... | WhenExpr |
| Test.kt:30:3:33:3 | when ... | WhenExpr | Test.kt:30:7:33:3 | ... -> ... | WhenBranch |
@@ -80,15 +67,12 @@
| Test.kt:30:15:33:3 | { ... } | BlockStmt | Test.kt:31:4:31:9 | <Expr>; | ExprStmt |
| Test.kt:31:4:31:9 | ...=... | AssignExpr | Test.kt:32:4:32:9 | <Expr>; | ExprStmt |
| Test.kt:31:4:31:9 | <Expr>; | ExprStmt | Test.kt:31:8:31:9 | 60 | LongLiteral |
| Test.kt:31:4:31:9 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:31:8:31:9 | 60 | LongLiteral | Test.kt:31:4:31:9 | ...=... | AssignExpr |
| Test.kt:32:4:32:9 | ...=... | AssignExpr | Test.kt:35:3:35:8 | <Expr>; | ExprStmt |
| Test.kt:32:4:32:9 | <Expr>; | ExprStmt | Test.kt:32:8:32:9 | 10 | IntegerLiteral |
| Test.kt:32:4:32:9 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:32:8:32:9 | 10 | IntegerLiteral | Test.kt:32:4:32:9 | ...=... | AssignExpr |
| Test.kt:35:3:35:8 | ...=... | AssignExpr | Test.kt:38:3:41:3 | while (...) | WhileStmt |
| Test.kt:35:3:35:8 | <Expr>; | ExprStmt | Test.kt:35:7:35:8 | 20 | IntegerLiteral |
| Test.kt:35:3:35:8 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:35:7:35:8 | 20 | IntegerLiteral | Test.kt:35:3:35:8 | ...=... | AssignExpr |
| Test.kt:38:3:41:3 | while (...) | WhileStmt | Test.kt:38:9:38:9 | x | VarAccess |
| Test.kt:38:9:38:9 | x | VarAccess | Test.kt:38:13:38:13 | 0 | IntegerLiteral |
@@ -98,7 +82,6 @@
| Test.kt:38:16:41:3 | { ... } | BlockStmt | Test.kt:39:4:39:9 | <Expr>; | ExprStmt |
| Test.kt:39:4:39:9 | ...=... | AssignExpr | Test.kt:40:4:40:6 | <Expr>; | ExprStmt |
| Test.kt:39:4:39:9 | <Expr>; | ExprStmt | Test.kt:39:8:39:9 | 10 | LongLiteral |
| Test.kt:39:4:39:9 | y | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:39:8:39:9 | 10 | LongLiteral | Test.kt:39:4:39:9 | ...=... | AssignExpr |
| Test.kt:40:4:40:4 | x | VarAccess | Test.kt:40:4:40:6 | <unary> | LocalVariableDeclExpr |
| Test.kt:40:4:40:6 | ...=... | AssignExpr | Test.kt:40:4:40:6 | <Expr>; | ExprStmt |
@@ -110,77 +93,53 @@
| Test.kt:40:4:40:6 | <unary> | LocalVariableDeclExpr | Test.kt:40:4:40:6 | <Expr>; | ExprStmt |
| Test.kt:40:4:40:6 | <unary> | VarAccess | Test.kt:40:4:40:6 | <implicit coercion to unit> | ImplicitCoercionToUnitExpr |
| Test.kt:40:4:40:6 | <unary> | VarAccess | Test.kt:40:4:40:6 | dec(...) | MethodCall |
| Test.kt:40:4:40:6 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | dec(...) | MethodCall | Test.kt:40:4:40:6 | ...=... | AssignExpr |
| Test.kt:40:4:40:6 | int <unary> | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | Test.kt:40:4:40:4 | x | VarAccess |
| Test.kt:40:4:40:6 | x | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:40:4:40:6 | { ... } | BlockStmt | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt |
| Test.kt:43:3:43:8 | ...=... | AssignExpr | Test.kt:73:3:73:8 | <Expr>; | ExprStmt |
| Test.kt:43:3:43:8 | <Expr>; | ExprStmt | Test.kt:43:7:43:8 | 30 | IntegerLiteral |
| Test.kt:43:3:43:8 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:43:7:43:8 | 30 | IntegerLiteral | Test.kt:43:3:43:8 | ...=... | AssignExpr |
| Test.kt:73:3:73:8 | ...=... | AssignExpr | Test.kt:77:3:77:8 | <Expr>; | ExprStmt |
| Test.kt:73:3:73:8 | <Expr>; | ExprStmt | Test.kt:73:7:73:8 | 50 | IntegerLiteral |
| Test.kt:73:3:73:8 | z | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:73:7:73:8 | 50 | IntegerLiteral | Test.kt:73:3:73:8 | ...=... | AssignExpr |
| Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:9:78:9 | INSTANCE | VarAccess |
| Test.kt:77:3:77:8 | <Expr>; | ExprStmt | Test.kt:77:7:77:8 | 40 | IntegerLiteral |
| Test.kt:77:3:77:8 | w | VarAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr |
| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | test | Method |
| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:78:9:78:9 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt |
| Test.kt:82:1:89:1 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:1:89:1 | t1 | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:8:82:13 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:8:82:13 | o | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt |
| Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt |
| Test.kt:83:6:86:2 | { ... } | BlockStmt | Test.kt:84:3:84:18 | var ...; | LocalVariableDeclStmt |
| Test.kt:84:3:84:18 | int x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:84:3:84:18 | var ...; | LocalVariableDeclStmt | Test.kt:84:11:84:11 | o | VarAccess |
| Test.kt:84:3:84:18 | x | LocalVariableDeclExpr | Test.kt:85:10:85:10 | 1 | IntegerLiteral |
| Test.kt:84:11:84:11 | o | VarAccess | Test.kt:84:11:84:18 | (...)... | CastExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:84:3:84:18 | x | LocalVariableDeclExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
| Test.kt:84:11:84:18 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | t1 | Method |
| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
| Test.kt:86:11:86:31 | ClassCastException | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:86:11:86:31 | ClassCastException e | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | t1 | Method |
| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt |
| Test.kt:91:1:98:1 | int | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:1:98:1 | t2 | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:8:91:14 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:8:91:14 | o | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt |
| Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt |
| Test.kt:92:6:95:2 | { ... } | BlockStmt | Test.kt:93:3:93:13 | var ...; | LocalVariableDeclStmt |
| Test.kt:93:3:93:13 | Object x | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:93:3:93:13 | var ...; | LocalVariableDeclStmt | Test.kt:93:11:93:11 | o | VarAccess |
| Test.kt:93:3:93:13 | x | LocalVariableDeclExpr | Test.kt:94:10:94:10 | 1 | IntegerLiteral |
| Test.kt:93:11:93:11 | o | VarAccess | Test.kt:93:11:93:13 | ...!! | NotNullExpr |
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:93:3:93:13 | x | LocalVariableDeclExpr |
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | t2 | Method |
| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
| Test.kt:95:11:95:33 | NullPointerException | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:95:11:95:33 | NullPointerException e | LocalVariableDecl | file://:0:0:0:0 | <none> | <none> |
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | t2 | Method |
| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt |
| Test.kt:100:1:110:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:1:110:1 | fn | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:8:100:13 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:8:100:13 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:16:100:22 | Object | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:16:100:22 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | <Expr>; | ExprStmt |
| Test.kt:101:5:103:5 | <Expr>; | ExprStmt | Test.kt:101:5:103:5 | when ... | WhenExpr |
| Test.kt:101:5:103:5 | when ... | WhenExpr | Test.kt:101:9:103:5 | ... -> ... | WhenBranch |
@@ -195,8 +154,7 @@
| Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr | Test.kt:105:5:109:5 | <Expr>; | ExprStmt |
| Test.kt:101:27:101:30 | null | NullLiteral | Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr |
| Test.kt:101:33:103:5 | { ... } | BlockStmt | Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr |
| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:102:15:102:25 | Exception | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr | Test.kt:102:9:102:25 | throw ... | ThrowStmt |
| Test.kt:105:5:109:5 | <Expr>; | ExprStmt | Test.kt:105:5:109:5 | when ... | WhenExpr |
| Test.kt:105:5:109:5 | when ... | WhenExpr | Test.kt:105:9:107:5 | ... -> ... | WhenBranch |
@@ -207,41 +165,29 @@
| Test.kt:105:14:105:17 | null | NullLiteral | Test.kt:105:9:105:17 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:105:20:107:5 | { ... } | BlockStmt | Test.kt:106:9:106:29 | <Expr>; | ExprStmt |
| Test.kt:106:9:106:29 | <Expr>; | ExprStmt | Test.kt:106:17:106:28 | "x not null" | StringLiteral |
| Test.kt:106:9:106:29 | ConsoleKt | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:106:17:106:28 | "x not null" | StringLiteral | Test.kt:106:9:106:29 | println(...) | MethodCall |
| Test.kt:107:16:107:16 | y | VarAccess | Test.kt:107:21:107:24 | null | NullLiteral |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:107:27:109:5 | { ... } | BlockStmt |
| Test.kt:107:16:109:5 | ... -> ... | WhenBranch | Test.kt:107:16:107:16 | y | VarAccess |
| Test.kt:107:21:107:24 | null | NullLiteral | Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:107:27:109:5 | { ... } | BlockStmt | Test.kt:108:9:108:29 | <Expr>; | ExprStmt |
| Test.kt:108:9:108:29 | <Expr>; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral |
| Test.kt:108:9:108:29 | ConsoleKt | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | fn | Method |
| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall |
| Test.kt:112:1:116:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:1:116:1 | fn | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:8:112:17 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:8:112:17 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:20:112:29 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:20:112:29 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | <Expr>; | ExprStmt |
| Test.kt:113:5:115:5 | <Expr>; | ExprStmt | Test.kt:113:5:115:5 | when ... | WhenExpr |
| Test.kt:113:5:115:5 | when ... | WhenExpr | Test.kt:113:9:115:5 | ... -> ... | WhenBranch |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:113:14:113:14 | y | VarAccess |
| Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr | Test.kt:113:9:113:9 | x | VarAccess |
| Test.kt:113:9:115:5 | ... -> ... | WhenBranch | Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt |
| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | fn | Method |
| Test.kt:118:1:124:1 | Unit | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:1:124:1 | fn_when | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:13:118:22 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:13:118:22 | x | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:25:118:34 | boolean | TypeAccess | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:25:118:34 | y | Parameter | file://:0:0:0:0 | <none> | <none> |
| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | <none> | <none> |
| Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | <Expr>; | ExprStmt |
| Test.kt:119:2:123:12 | <Expr>; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr |
| Test.kt:119:2:123:12 | when ... | WhenExpr | Test.kt:120:3:123:10 | ... -> ... | WhenBranch |
@@ -251,11 +197,11 @@
| Test.kt:121:4:121:4 | x | VarAccess | Test.kt:122:12:122:16 | ... -> ... | WhenBranch |
| Test.kt:121:4:121:9 | ... -> ... | WhenBranch | Test.kt:121:4:121:4 | x | VarAccess |
| Test.kt:121:9:121:9 | <Expr>; | ExprStmt | Test.kt:121:9:121:9 | y | VarAccess |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:123:8:123:10 | { ... } | BlockStmt |
| Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral |
| Test.kt:122:12:122:16 | <Expr>; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral |
| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | <Expr>; | ExprStmt |
| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | fn_when | Method |
| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Exit | Method |
missingSuccessor

View File

@@ -21,7 +21,7 @@ class YesMaybeControlFlowNode extends MaybeControlFlowNode {
override Location getLocation() { result = c.getLocation() }
override string getPrimaryQlClasses() { result = c.getPrimaryQlClasses() }
override string getPrimaryQlClasses() { result = c.getAstNode().getPrimaryQlClasses() }
}
class NoMaybeControlFlowNode extends MaybeControlFlowNode {
@@ -43,11 +43,11 @@ MaybeControlFlowNode maybeSuccessor(ControlFlowNode n) {
from ControlFlowNode n, MaybeControlFlowNode m
where
m = maybeSuccessor(n) and
n.getFile().(CompilationUnit).fromSource()
select n, n.getPrimaryQlClasses(), m, m.getPrimaryQlClasses()
n.getLocation().getFile().(CompilationUnit).fromSource()
select n, n.getAstNode().getPrimaryQlClasses(), m, m.getPrimaryQlClasses()
query predicate missingSuccessor(Expr n) {
maybeSuccessor(n) instanceof NoMaybeControlFlowNode and
maybeSuccessor(n.getControlFlowNode()) instanceof NoMaybeControlFlowNode and
n.getFile().(CompilationUnit).fromSource() and
not n instanceof TypeAccess and
not n instanceof VarWrite

View File

@@ -2,5 +2,5 @@ import default
import semmle.code.java.controlflow.Dominance
from Stmt pre, Stmt post
where strictlyDominates(pre, post)
where strictlyDominates(pre.getControlFlowNode(), post.getControlFlowNode())
select pre, post

View File

@@ -2,5 +2,5 @@ import default
import semmle.code.java.controlflow.Dominance
from Stmt pre, Stmt post
where strictlyPostDominates(post, pre)
where strictlyPostDominates(post.getControlFlowNode(), pre.getControlFlowNode())
select post, pre

View File

@@ -4,6 +4,6 @@ import semmle.code.java.controlflow.Dominance
from IfStmt i, BlockStmt b
where
b = i.getThen() and
dominates(i.getThen(), b) and
dominates(i.getElse(), b)
dominates(i.getThen().getControlFlowNode(), b.getControlFlowNode()) and
dominates(i.getElse().getControlFlowNode(), b.getControlFlowNode())
select i, b

View File

@@ -17,5 +17,5 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
from Callable c, ControlFlowNode dom, ControlFlowNode node
where
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
dominanceCounterExample(c.getBody(), dom, node)
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
select c, dom, node

View File

@@ -3,14 +3,14 @@ import default
import semmle.code.java.controlflow.Dominance
ControlFlowNode reachableIn(Method func) {
result = func.getBody() or
result = func.getBody().getControlFlowNode() or
result = reachableIn(func).getASuccessor()
}
from Method func, ControlFlowNode entry, ControlFlowNode node
where
func.getBody() = entry and
func.getBody().getControlFlowNode() = entry and
reachableIn(func) = node and
entry != node and
not strictlyDominates(func.getBody(), node)
not strictlyDominates(func.getBody().getControlFlowNode(), node)
select func, node

View File

@@ -41,7 +41,7 @@
| Test.kt:21:3:24:11 | <Expr>; | Test.kt:21:3:24:11 | when ... |
| Test.kt:21:3:24:11 | when ... | Test.kt:21:7:22:9 | ... -> ... |
| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | test |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Exit |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:9 | <Expr>; |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:24:4:24:11 | ... -> ... |
| Test.kt:21:7:22:9 | ... -> ... | Test.kt:21:7:21:7 | x |
@@ -141,7 +141,7 @@
| Test.kt:92:4:93:9 | <Expr>; | Test.kt:92:4:93:9 | when ... |
| Test.kt:92:4:93:9 | when ... | Test.kt:92:8:93:9 | ... -> ... |
| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | test2 |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Exit |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | <Expr>; |
| Test.kt:92:8:93:9 | ... -> ... | Test.kt:92:8:92:8 | a |

View File

@@ -4,13 +4,13 @@ import semmle.code.java.controlflow.Dominance
/** transitive dominance */
ControlFlowNode reachableIn(Method func) {
result = func.getBody() or
result = func.getBody().getControlFlowNode() or
result = reachableIn(func).getASuccessor()
}
from Method func, ControlFlowNode node
where
node = reachableIn(func) and
node != func.getBody() and
node != func.getBody().getControlFlowNode() and
not iDominates(_, node)
select func, node

View File

@@ -5,7 +5,7 @@ class PathTestConf extends ActionConfiguration {
PathTestConf() { this = "PathTestConf" }
override predicate isAction(ControlFlowNode node) {
node.(MethodCall).getMethod().hasName("action")
node.asExpr().(MethodCall).getMethod().hasName("action")
}
}

View File

@@ -1,4 +1,4 @@
import java
import TestUtilities.InlineFlowTest
import utils.test.InlineFlowTest
import DefaultFlowTest
import TaintFlow::PathGraph

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-020/Log4jJndiInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,5 +1,5 @@
import java
import TestUtilities.InlineFlowTest
import utils.test.InlineFlowTest
import semmle.code.java.security.TaintedPathQuery
import TaintFlowTestArgString<TaintedPathConfig, getArgString/2>

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-073/FilePathInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-078/CommandInjectionRuntimeExecLocal.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-078/ExecTainted.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-089/MyBatisAnnotationSqlInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-089/MyBatisMapperXmlSqlInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-094/BeanShellInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-094/JShellInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-094/JakartaExpressionInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-094/JythonInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-094/ScriptInjection.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-200/InsecureWebResourceResponse.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-208/PossibleTimingAttackAgainstSignature.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-208/TimingAttackAgainstSignature.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

View File

@@ -1,2 +1,2 @@
query: experimental/Security/CWE/CWE-299/DisabledRevocationChecking.ql
postprocess: TestUtilities/PrettyPrintModels.ql
postprocess: utils/test/PrettyPrintModels.ql

Some files were not shown because too many files have changed in this diff Show More