mirror of
https://github.com/github/codeql.git
synced 2026-05-30 02:51:24 +02:00
Merge tag 'codeql-cli/latest'
Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
@@ -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__"])
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
20
java/ql/lib/change-notes/released/6.0.0.md
Normal file
20
java/ql/lib/change-notes/released/6.0.0.md
Normal 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 5.0.0
|
||||
lastReleaseVersion: 6.0.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-all
|
||||
version: 5.0.0
|
||||
version: 6.0.0
|
||||
groups: java
|
||||
dbscheme: config/semmlecode.dbscheme
|
||||
extractor: java
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.1.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.1.10
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
3
java/ql/src/change-notes/released/1.1.11.md
Normal file
3
java/ql/src/change-notes/released/1.1.11.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.1.11
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.1.10
|
||||
lastReleaseVersion: 1.1.11
|
||||
|
||||
@@ -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:%"])
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 1.1.10
|
||||
version: 1.1.11
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
import utils.test.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
|
||||
@@ -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 ... |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 | { ... } |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) ... |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
import utils.test.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
import TaintFlow::PathGraph
|
||||
|
||||
@@ -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 ... |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 | { ... } |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
import utils.test.InlineFlowTest
|
||||
import DefaultFlowTest
|
||||
import TaintFlow::PathGraph
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-020/Log4jJndiInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
import utils.test.InlineFlowTest
|
||||
import semmle.code.java.security.TaintedPathQuery
|
||||
import TaintFlowTestArgString<TaintedPathConfig, getArgString/2>
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-073/FilePathInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-078/CommandInjectionRuntimeExecLocal.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-078/ExecTainted.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-089/MyBatisAnnotationSqlInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-089/MyBatisMapperXmlSqlInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-094/BeanShellInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-094/JShellInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-094/JakartaExpressionInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-094/JythonInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-094/ScriptInjection.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-1004/SensitiveCookieNotHttpOnly.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-200/InsecureWebResourceResponse.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-208/PossibleTimingAttackAgainstSignature.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
query: experimental/Security/CWE/CWE-208/TimingAttackAgainstSignature.ql
|
||||
postprocess: TestUtilities/PrettyPrintModels.ql
|
||||
postprocess: utils/test/PrettyPrintModels.ql
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user