mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
Merge tag 'codeql-cli/latest' into auto/sync-main-pr
Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
@@ -196,7 +196,6 @@ ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql
|
||||
|
||||
@@ -99,7 +99,6 @@ ql/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-732/ReadingFromWorldWritableFile.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-829/InsecureDependencyResolution.ql
|
||||
|
||||
@@ -158,6 +158,7 @@ ql/java/ql/src/Security/CWE/CWE-312/CleartextStorageClass.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-319/UseSSL.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsComparison.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsSourceCall.ql
|
||||
ql/java/ql/src/Security/CWE/CWE-798/HardcodedPasswordField.ql
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 7.3.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The predicate `getValue()` on `SpringRequestMappingMethod` is now deprecated. Use `getAValue()` instead.
|
||||
* Java now uses the shared `BasicBlock` library. This means that the names of several member predicates have been changed to align with the names used in other languages. The old predicates have been deprecated. The `BasicBlock` class itself no longer extends `ControlFlowNode` - the predicate `getFirstNode` can be used to fix any QL code that somehow relied on this.
|
||||
|
||||
## 7.2.0
|
||||
|
||||
### New Features
|
||||
@@ -20,7 +27,7 @@ No user-facing changes.
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Java extraction is now able to download Maven 3.9.x if a Maven Enforcer Plugin configuration indicates it is necessary. Maven 3.8.x is still preferred if the enforcer-plugin configuration (if any) permits it.
|
||||
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure '/', '\', '..' are not in the path.
|
||||
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure `/`, `\\`, `..` are not in the path.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -55,8 +62,8 @@ No user-facing changes.
|
||||
* Deleted the deprecated `isLValue` and `isRValue` predicates from the `VarAccess` class, use `isVarWrite` and `isVarRead` respectively instead.
|
||||
* Deleted the deprecated `getRhs` predicate from the `VarWrite` class, use `getASource` instead.
|
||||
* Deleted the deprecated `LValue` and `RValue` classes, use `VarWrite` and `VarRead` respectively instead.
|
||||
* Deleted a lot of deprecated classes ending in "*Access", use the corresponding "*Call" classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in "*Access", use the corresponding "*Call" predicates instead.
|
||||
* Deleted a lot of deprecated classes ending in `*Access`, use the corresponding `*Call` classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in `*Access`, use the corresponding `*Call` predicates instead.
|
||||
* Deleted the deprecated `EnvInput` and `DatabaseInput` classes from `FlowSources.qll`, use the threat models feature instead.
|
||||
* Deleted some deprecated API predicates from `SensitiveApi.qll`, use the Sink classes from that file instead.
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* Deleted the deprecated `isLValue` and `isRValue` predicates from the `VarAccess` class, use `isVarWrite` and `isVarRead` respectively instead.
|
||||
* Deleted the deprecated `getRhs` predicate from the `VarWrite` class, use `getASource` instead.
|
||||
* Deleted the deprecated `LValue` and `RValue` classes, use `VarWrite` and `VarRead` respectively instead.
|
||||
* Deleted a lot of deprecated classes ending in "*Access", use the corresponding "*Call" classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in "*Access", use the corresponding "*Call" predicates instead.
|
||||
* Deleted a lot of deprecated classes ending in `*Access`, use the corresponding `*Call` classes instead.
|
||||
* Deleted a lot of deprecated predicates ending in `*Access`, use the corresponding `*Call` predicates instead.
|
||||
* Deleted the deprecated `EnvInput` and `DatabaseInput` classes from `FlowSources.qll`, use the threat models feature instead.
|
||||
* Deleted some deprecated API predicates from `SensitiveApi.qll`, use the Sink classes from that file instead.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Java extraction is now able to download Maven 3.9.x if a Maven Enforcer Plugin configuration indicates it is necessary. Maven 3.8.x is still preferred if the enforcer-plugin configuration (if any) permits it.
|
||||
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure '/', '\', '..' are not in the path.
|
||||
* Added a path injection sanitizer for calls to `java.lang.String.matches`, `java.lang.String.replace`, and `java.lang.String.replaceAll` that make sure `/`, `\\`, `..` are not in the path.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
6
java/ql/lib/change-notes/released/7.3.0.md
Normal file
6
java/ql/lib/change-notes/released/7.3.0.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## 7.3.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The predicate `getValue()` on `SpringRequestMappingMethod` is now deprecated. Use `getAValue()` instead.
|
||||
* Java now uses the shared `BasicBlock` library. This means that the names of several member predicates have been changed to align with the names used in other languages. The old predicates have been deprecated. The `BasicBlock` class itself no longer extends `ControlFlowNode` - the predicate `getFirstNode` can be used to fix any QL code that somehow relied on this.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 7.2.0
|
||||
lastReleaseVersion: 7.3.0
|
||||
|
||||
@@ -353,7 +353,7 @@ module JCAModel {
|
||||
else result instanceof KeyOpAlg::TUnknownKeyOperationAlgorithmType
|
||||
}
|
||||
|
||||
override string getKeySizeFixed() {
|
||||
override int getKeySizeFixed() {
|
||||
none() // TODO: implement to handle variants such as AES-128
|
||||
}
|
||||
|
||||
@@ -611,6 +611,8 @@ module JCAModel {
|
||||
}
|
||||
|
||||
class CipherOperationInstance extends Crypto::KeyOperationInstance instanceof CipherOperationCall {
|
||||
CipherOperationInstance() { not this.isIntermediate() }
|
||||
|
||||
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||
if CipherFlowAnalysisImpl::hasInit(this)
|
||||
then result = CipherFlowAnalysisImpl::getInitFromUse(this, _, _).getCipherOperationModeType()
|
||||
@@ -1102,7 +1104,7 @@ module JCAModel {
|
||||
KeyGeneratorFlowAnalysisImpl::getInitFromUse(this, _, _).getKeySizeArg() = result.asExpr()
|
||||
}
|
||||
|
||||
override string getKeySizeFixed() { none() }
|
||||
override int getKeySizeFixed() { none() }
|
||||
}
|
||||
|
||||
class KeyGeneratorCipherAlgorithm extends CipherStringLiteralAlgorithmInstance {
|
||||
@@ -1308,7 +1310,7 @@ module JCAModel {
|
||||
result.asExpr() = this.getKeySpecInstantiation().(PBEKeySpecInstantiation).getKeyLengthArg()
|
||||
}
|
||||
|
||||
override string getKeySizeFixed() { none() }
|
||||
override int getKeySizeFixed() { none() }
|
||||
|
||||
override string getOutputKeySizeFixed() { none() }
|
||||
|
||||
@@ -1604,13 +1606,8 @@ module JCAModel {
|
||||
else result = Crypto::OtherEllipticCurveType()
|
||||
}
|
||||
|
||||
override string getKeySize() {
|
||||
exists(int keySize |
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), keySize,
|
||||
_)
|
||||
|
|
||||
result = keySize.toString()
|
||||
)
|
||||
override int getKeySize() {
|
||||
Crypto::ellipticCurveNameToKeySizeAndFamilyMapping(this.getRawEllipticCurveName(), result, _)
|
||||
}
|
||||
|
||||
EllipticCurveAlgorithmValueConsumer getConsumer() { result = consumer }
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
name: codeql/java-all
|
||||
version: 7.2.0
|
||||
version: 7.3.0
|
||||
groups: java
|
||||
dbscheme: config/semmlecode.dbscheme
|
||||
extractor: java
|
||||
library: true
|
||||
upgrades: upgrades
|
||||
dependencies:
|
||||
codeql/controlflow: ${workspace}
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/dataflowstack: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
|
||||
@@ -4,91 +4,128 @@
|
||||
|
||||
import java
|
||||
import Dominance
|
||||
private import codeql.controlflow.BasicBlock as BB
|
||||
|
||||
cached
|
||||
private module BasicBlockStage {
|
||||
cached
|
||||
predicate ref() { any() }
|
||||
private module Input implements BB::InputSig<Location> {
|
||||
import SuccessorType
|
||||
|
||||
cached
|
||||
predicate backref() {
|
||||
(exists(any(BasicBlock bb).getABBSuccessor()) implies any()) and
|
||||
(exists(any(BasicBlock bb).getNode(_)) implies any()) and
|
||||
(exists(any(BasicBlock bb).length()) implies any())
|
||||
/** Hold if `t` represents a conditional successor type. */
|
||||
predicate successorTypeIsCondition(SuccessorType t) { none() }
|
||||
|
||||
/** A delineated part of the AST with its own CFG. */
|
||||
class CfgScope = Callable;
|
||||
|
||||
/** The class of control flow nodes. */
|
||||
class Node = ControlFlowNode;
|
||||
|
||||
/** Gets the CFG scope in which this node occurs. */
|
||||
CfgScope nodeGetCfgScope(Node node) { node.getEnclosingCallable() = result }
|
||||
|
||||
private Node getASpecificSuccessor(Node node, SuccessorType t) {
|
||||
node.(ConditionNode).getABranchSuccessor(t.(BooleanSuccessor).getValue()) = result
|
||||
or
|
||||
node.getAnExceptionSuccessor() = result and t instanceof ExceptionSuccessor
|
||||
}
|
||||
|
||||
/** Gets an immediate successor of this node. */
|
||||
Node nodeGetASuccessor(Node node, SuccessorType t) {
|
||||
result = getASpecificSuccessor(node, t)
|
||||
or
|
||||
node.getASuccessor() = result and
|
||||
t instanceof NormalSuccessor and
|
||||
not result = getASpecificSuccessor(node, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an entry node to be used when calculating
|
||||
* dominance.
|
||||
*/
|
||||
predicate nodeIsDominanceEntry(Node node) {
|
||||
exists(Stmt entrystmt | entrystmt = node.asStmt() |
|
||||
exists(Callable c | entrystmt = c.getBody())
|
||||
or
|
||||
// This disjunct is technically superfluous, but safeguards against extractor problems.
|
||||
entrystmt instanceof BlockStmt and
|
||||
not exists(entrystmt.getEnclosingCallable()) and
|
||||
not entrystmt.getParent() instanceof Stmt
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents an exit node to be used when calculating
|
||||
* post dominance.
|
||||
*/
|
||||
predicate nodeIsPostDominanceExit(Node node) { node instanceof ControlFlow::ExitNode }
|
||||
}
|
||||
|
||||
private module BbImpl = BB::Make<Location, Input>;
|
||||
|
||||
import BbImpl
|
||||
|
||||
/** Holds if the dominance relation is calculated for `bb`. */
|
||||
predicate hasDominanceInformation(BasicBlock bb) {
|
||||
exists(BasicBlock entry |
|
||||
Input::nodeIsDominanceEntry(entry.getFirstNode()) and entry.getASuccessor*() = bb
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A control-flow node that represents the start of a basic block.
|
||||
*
|
||||
* A basic block is a series of nodes with no control-flow branching, which can
|
||||
* often be treated as a unit in analyses.
|
||||
* A basic block, that is, a maximal straight-line sequence of control flow nodes
|
||||
* without branches or joins.
|
||||
*/
|
||||
class BasicBlock extends ControlFlowNode {
|
||||
cached
|
||||
BasicBlock() {
|
||||
BasicBlockStage::ref() and
|
||||
not exists(this.getAPredecessor()) and
|
||||
exists(this.getASuccessor())
|
||||
or
|
||||
strictcount(this.getAPredecessor()) > 1
|
||||
or
|
||||
exists(ControlFlowNode pred | pred = this.getAPredecessor() |
|
||||
strictcount(pred.getASuccessor()) > 1
|
||||
)
|
||||
}
|
||||
class BasicBlock extends BbImpl::BasicBlock {
|
||||
/** Gets the immediately enclosing callable whose body contains this node. */
|
||||
Callable getEnclosingCallable() { result = this.getScope() }
|
||||
|
||||
/** Gets an immediate successor of this basic block. */
|
||||
cached
|
||||
BasicBlock getABBSuccessor() {
|
||||
BasicBlockStage::ref() and
|
||||
result = this.getLastNode().getASuccessor()
|
||||
}
|
||||
/**
|
||||
* Holds if this basic block dominates basic block `bb`.
|
||||
*
|
||||
* That is, all paths reaching `bb` from the entry point basic block must
|
||||
* go through this basic block.
|
||||
*/
|
||||
predicate dominates(BasicBlock bb) { super.dominates(bb) }
|
||||
|
||||
/** Gets an immediate predecessor of this basic block. */
|
||||
BasicBlock getABBPredecessor() { result.getABBSuccessor() = this }
|
||||
/**
|
||||
* DEPRECATED: Use `getASuccessor` instead.
|
||||
*
|
||||
* Gets an immediate successor of this basic block.
|
||||
*/
|
||||
deprecated BasicBlock getABBSuccessor() { result = this.getASuccessor() }
|
||||
|
||||
/** Gets a control-flow node contained in this basic block. */
|
||||
ControlFlowNode getANode() { result = this.getNode(_) }
|
||||
/**
|
||||
* DEPRECATED: Use `getAPredecessor` instead.
|
||||
*
|
||||
* Gets an immediate predecessor of this basic block.
|
||||
*/
|
||||
deprecated BasicBlock getABBPredecessor() { result.getASuccessor() = this }
|
||||
|
||||
/** Gets the control-flow node at a specific (zero-indexed) position in this basic block. */
|
||||
cached
|
||||
ControlFlowNode getNode(int pos) {
|
||||
BasicBlockStage::ref() and
|
||||
result = this and
|
||||
pos = 0
|
||||
or
|
||||
exists(ControlFlowNode mid, int mid_pos | pos = mid_pos + 1 |
|
||||
this.getNode(mid_pos) = mid and
|
||||
mid.getASuccessor() = result and
|
||||
not result instanceof BasicBlock
|
||||
)
|
||||
}
|
||||
/**
|
||||
* DEPRECATED: Use `strictlyDominates` instead.
|
||||
*
|
||||
* Holds if this basic block strictly dominates `node`.
|
||||
*/
|
||||
deprecated predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) }
|
||||
|
||||
/** Gets the first control-flow node in this basic block. */
|
||||
ControlFlowNode getFirstNode() { result = this }
|
||||
/**
|
||||
* DEPRECATED: Use `dominates` instead.
|
||||
*
|
||||
* Holds if this basic block dominates `node`. (This is reflexive.)
|
||||
*/
|
||||
deprecated predicate bbDominates(BasicBlock node) { this.dominates(node) }
|
||||
|
||||
/** Gets the last control-flow node in this basic block. */
|
||||
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
|
||||
/**
|
||||
* DEPRECATED: Use `strictlyPostDominates` instead.
|
||||
*
|
||||
* Holds if this basic block strictly post-dominates `node`.
|
||||
*/
|
||||
deprecated predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) }
|
||||
|
||||
/** Gets the number of control-flow nodes contained in this basic block. */
|
||||
cached
|
||||
int length() {
|
||||
BasicBlockStage::ref() and
|
||||
result = strictcount(this.getANode())
|
||||
}
|
||||
|
||||
/** Holds if this basic block strictly dominates `node`. */
|
||||
predicate bbStrictlyDominates(BasicBlock node) { bbStrictlyDominates(this, node) }
|
||||
|
||||
/** Holds if this basic block dominates `node`. (This is reflexive.) */
|
||||
predicate bbDominates(BasicBlock node) { bbDominates(this, node) }
|
||||
|
||||
/** Holds if this basic block strictly post-dominates `node`. */
|
||||
predicate bbStrictlyPostDominates(BasicBlock node) { bbStrictlyPostDominates(this, node) }
|
||||
|
||||
/** Holds if this basic block post-dominates `node`. (This is reflexive.) */
|
||||
predicate bbPostDominates(BasicBlock node) { bbPostDominates(this, node) }
|
||||
/**
|
||||
* DEPRECATED: Use `postDominates` instead.
|
||||
*
|
||||
* Holds if this basic block post-dominates `node`. (This is reflexive.)
|
||||
*/
|
||||
deprecated predicate bbPostDominates(BasicBlock node) { this.postDominates(node) }
|
||||
}
|
||||
|
||||
/** A basic block that ends in an exit node. */
|
||||
|
||||
@@ -8,91 +8,75 @@ import java
|
||||
* Predicates for basic-block-level dominance.
|
||||
*/
|
||||
|
||||
/** Entry points for control-flow. */
|
||||
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. */
|
||||
private predicate bbSucc(BasicBlock pre, BasicBlock post) { post = pre.getABBSuccessor() }
|
||||
|
||||
/** The immediate dominance relation for basic blocks. */
|
||||
cached
|
||||
predicate bbIDominates(BasicBlock dom, BasicBlock node) =
|
||||
idominance(flowEntry/1, bbSucc/2)(_, dom, node)
|
||||
|
||||
/** Holds if the dominance relation is calculated for `bb`. */
|
||||
predicate hasDominanceInformation(BasicBlock bb) {
|
||||
exists(BasicBlock entry | flowEntry(entry) and bbSucc*(entry, bb))
|
||||
/**
|
||||
* DEPRECATED: Use `BasicBlock::immediatelyDominates` instead.
|
||||
*
|
||||
* The immediate dominance relation for basic blocks.
|
||||
*/
|
||||
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock node) {
|
||||
dom.immediatelyDominates(node)
|
||||
}
|
||||
|
||||
/** Exit points for basic-block control-flow. */
|
||||
private predicate bbSink(BasicBlock exit) { exit.getLastNode() instanceof ControlFlow::ExitNode }
|
||||
|
||||
/** Reversed `bbSucc`. */
|
||||
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getABBSuccessor() }
|
||||
private predicate bbPred(BasicBlock post, BasicBlock pre) { post = pre.getASuccessor() }
|
||||
|
||||
/** The immediate post-dominance relation on basic blocks. */
|
||||
cached
|
||||
predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
|
||||
deprecated predicate bbIPostDominates(BasicBlock dominator, BasicBlock node) =
|
||||
idominance(bbSink/1, bbPred/2)(_, dominator, node)
|
||||
|
||||
/** Holds if `dom` strictly dominates `node`. */
|
||||
predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) { bbIDominates+(dom, node) }
|
||||
|
||||
/** Holds if `dom` dominates `node`. (This is reflexive.) */
|
||||
predicate bbDominates(BasicBlock dom, BasicBlock node) {
|
||||
bbStrictlyDominates(dom, node) or dom = node
|
||||
/**
|
||||
* DEPRECATED: Use `BasicBlock::strictlyDominates` instead.
|
||||
*
|
||||
* Holds if `dom` strictly dominates `node`.
|
||||
*/
|
||||
deprecated predicate bbStrictlyDominates(BasicBlock dom, BasicBlock node) {
|
||||
dom.strictlyDominates(node)
|
||||
}
|
||||
|
||||
/** Holds if `dom` strictly post-dominates `node`. */
|
||||
predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) { bbIPostDominates+(dom, node) }
|
||||
/**
|
||||
* DEPRECATED: Use `BasicBlock::dominates` instead.
|
||||
*
|
||||
* Holds if `dom` dominates `node`. (This is reflexive.)
|
||||
*/
|
||||
deprecated predicate bbDominates(BasicBlock dom, BasicBlock node) { dom.dominates(node) }
|
||||
|
||||
/** Holds if `dom` post-dominates `node`. (This is reflexive.) */
|
||||
predicate bbPostDominates(BasicBlock dom, BasicBlock node) {
|
||||
bbStrictlyPostDominates(dom, node) or dom = node
|
||||
/**
|
||||
* DEPRECATED: Use `BasicBlock::strictlyPostDominates` instead.
|
||||
*
|
||||
* Holds if `dom` strictly post-dominates `node`.
|
||||
*/
|
||||
deprecated predicate bbStrictlyPostDominates(BasicBlock dom, BasicBlock node) {
|
||||
dom.strictlyPostDominates(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BasicBlock::postDominates` instead.
|
||||
*
|
||||
* Holds if `dom` post-dominates `node`. (This is reflexive.)
|
||||
*/
|
||||
deprecated predicate bbPostDominates(BasicBlock dom, BasicBlock node) { dom.postDominates(node) }
|
||||
|
||||
/**
|
||||
* The dominance frontier relation for basic blocks.
|
||||
*
|
||||
* This is equivalent to:
|
||||
*
|
||||
* ```
|
||||
* bbDominates(x, w.getABBPredecessor()) and not bbStrictlyDominates(x, w)
|
||||
* x.dominates(w.getAPredecessor()) and not x.strictlyDominates(w)
|
||||
* ```
|
||||
*/
|
||||
predicate dominanceFrontier(BasicBlock x, BasicBlock w) {
|
||||
x = w.getABBPredecessor() and not bbIDominates(x, w)
|
||||
x = w.getAPredecessor() and not x.immediatelyDominates(w)
|
||||
or
|
||||
exists(BasicBlock prev | dominanceFrontier(prev, w) |
|
||||
bbIDominates(x, prev) and
|
||||
not bbIDominates(x, w)
|
||||
x.immediatelyDominates(prev) and
|
||||
not x.immediatelyDominates(w)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(bb1, bb2)` is an edge that dominates `bb2`, that is, all other
|
||||
* predecessors of `bb2` are dominated by `bb2`. This implies that `bb1` is the
|
||||
* immediate dominator of `bb2`.
|
||||
*
|
||||
* This is a necessary and sufficient condition for an edge to dominate anything,
|
||||
* and in particular `dominatingEdge(bb1, bb2) and bb2.bbDominates(bb3)` means
|
||||
* that the edge `(bb1, bb2)` dominates `bb3`.
|
||||
*/
|
||||
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
|
||||
bbIDominates(bb1, bb2) and
|
||||
bb1.getABBSuccessor() = bb2 and
|
||||
forall(BasicBlock pred | pred = bb2.getABBPredecessor() and pred != bb1 | bbDominates(bb2, pred))
|
||||
}
|
||||
|
||||
/*
|
||||
* Predicates for expression-level dominance.
|
||||
*/
|
||||
@@ -102,7 +86,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
|
||||
exists(BasicBlock bb, int i | dominator = bb.getNode(i) and node = bb.getNode(i + 1))
|
||||
or
|
||||
exists(BasicBlock dom, BasicBlock bb |
|
||||
bbIDominates(dom, bb) and
|
||||
dom.immediatelyDominates(bb) and
|
||||
dominator = dom.getLastNode() and
|
||||
node = bb.getFirstNode()
|
||||
)
|
||||
@@ -112,7 +96,7 @@ predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) {
|
||||
pragma[inline]
|
||||
predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
// This predicate is gigantic, so it must be inlined.
|
||||
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
|
||||
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i < j)
|
||||
}
|
||||
@@ -121,7 +105,7 @@ predicate strictlyDominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
pragma[inline]
|
||||
predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
// This predicate is gigantic, so it must be inlined.
|
||||
bbStrictlyDominates(dom.getBasicBlock(), node.getBasicBlock())
|
||||
dom.getBasicBlock().strictlyDominates(node.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i <= j)
|
||||
}
|
||||
@@ -130,7 +114,7 @@ predicate dominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
pragma[inline]
|
||||
predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
// This predicate is gigantic, so it must be inlined.
|
||||
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
|
||||
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i > j)
|
||||
}
|
||||
@@ -139,7 +123,7 @@ predicate strictlyPostDominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
pragma[inline]
|
||||
predicate postDominates(ControlFlowNode dom, ControlFlowNode node) {
|
||||
// This predicate is gigantic, so it must be inlined.
|
||||
bbStrictlyPostDominates(dom.getBasicBlock(), node.getBasicBlock())
|
||||
dom.getBasicBlock().strictlyPostDominates(node.getBasicBlock())
|
||||
or
|
||||
exists(BasicBlock b, int i, int j | dom = b.getNode(i) and node = b.getNode(j) and i >= j)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class ConditionBlock extends BasicBlock {
|
||||
|
||||
/** Gets a `true`- or `false`-successor of the last node of this basic block. */
|
||||
BasicBlock getTestSuccessor(boolean testIsTrue) {
|
||||
result = this.getConditionNode().getABranchSuccessor(testIsTrue)
|
||||
result.getFirstNode() = this.getConditionNode().getABranchSuccessor(testIsTrue)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -68,7 +68,7 @@ class ConditionBlock extends BasicBlock {
|
||||
exists(BasicBlock succ |
|
||||
succ = this.getTestSuccessor(testIsTrue) and
|
||||
dominatingEdge(this, succ) and
|
||||
succ.bbDominates(controlled)
|
||||
succ.dominates(controlled)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
|
||||
* Evaluating a switch case to true corresponds to taking that switch case, and
|
||||
* evaluating it to false corresponds to taking some other branch.
|
||||
*/
|
||||
class Guard extends ExprParent {
|
||||
final class Guard extends ExprParent {
|
||||
Guard() {
|
||||
this.(Expr).getType() instanceof BooleanType and not this instanceof BooleanLiteral
|
||||
or
|
||||
@@ -272,6 +272,15 @@ class Guard extends ExprParent {
|
||||
preconditionControls(this, controlled, branch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||
*/
|
||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||
guardControlsBranchEdge_v3(this, bb1, bb2, branch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this guard evaluating to `branch` directly or indirectly controls
|
||||
* the block `controlled`. That is, the evaluation of `controlled` is
|
||||
@@ -287,7 +296,7 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
|
||||
// Pattern cases are handled as condition blocks
|
||||
not sc instanceof PatternCase and
|
||||
caseblock.getFirstNode() = sc.getControlFlowNode() and
|
||||
caseblock.bbDominates(bb) and
|
||||
caseblock.dominates(bb) and
|
||||
// Check we can't fall through from a previous block:
|
||||
forall(ControlFlowNode pred | pred = sc.getControlFlowNode().getAPredecessor() |
|
||||
isNonFallThroughPredecessor(sc, pred)
|
||||
@@ -300,14 +309,14 @@ private predicate preconditionBranchEdge(
|
||||
) {
|
||||
conditionCheckArgument(ma, _, branch) and
|
||||
bb1.getLastNode() = ma.getControlFlowNode() and
|
||||
bb2 = bb1.getLastNode().getANormalSuccessor()
|
||||
bb2.getFirstNode() = bb1.getLastNode().getANormalSuccessor()
|
||||
}
|
||||
|
||||
private predicate preconditionControls(MethodCall ma, BasicBlock controlled, boolean branch) {
|
||||
exists(BasicBlock check, BasicBlock succ |
|
||||
preconditionBranchEdge(ma, check, succ, branch) and
|
||||
dominatingEdge(check, succ) and
|
||||
succ.bbDominates(controlled)
|
||||
succ.dominates(controlled)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -351,6 +360,51 @@ private predicate guardControls_v3(Guard guard, BasicBlock controlled, boolean b
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate guardControlsBranchEdge_v2(
|
||||
Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch
|
||||
) {
|
||||
guard.hasBranchEdge(bb1, bb2, branch)
|
||||
or
|
||||
exists(Guard g, boolean b |
|
||||
guardControlsBranchEdge_v2(g, bb1, bb2, b) and
|
||||
implies_v2(g, b, guard, branch)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate guardControlsBranchEdge_v3(
|
||||
Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch
|
||||
) {
|
||||
guard.hasBranchEdge(bb1, bb2, branch)
|
||||
or
|
||||
exists(Guard g, boolean b |
|
||||
guardControlsBranchEdge_v3(g, bb1, bb2, b) and
|
||||
implies_v3(g, b, guard, branch)
|
||||
)
|
||||
}
|
||||
|
||||
/** INTERNAL: Use `Guard` instead. */
|
||||
final class Guard_v2 extends Guard {
|
||||
/**
|
||||
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||
*/
|
||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||
guardControlsBranchEdge_v2(this, bb1, bb2, branch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this guard evaluating to `branch` directly or indirectly controls
|
||||
* the block `controlled`. That is, the evaluation of `controlled` is
|
||||
* dominated by this guard evaluating to `branch`.
|
||||
*/
|
||||
predicate controls(BasicBlock controlled, boolean branch) {
|
||||
guardControls_v2(this, controlled, branch)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
||||
exists(EqualityTest eqtest |
|
||||
eqtest = g and
|
||||
|
||||
@@ -47,7 +47,7 @@ private predicate callAlwaysPerformsAction(Call call, ActionConfiguration conf)
|
||||
private predicate actionDominatesExit(Callable callable, ActionConfiguration conf) {
|
||||
exists(ExitBlock exit |
|
||||
exit.getEnclosingCallable() = callable and
|
||||
actionBlock(conf).bbDominates(exit)
|
||||
actionBlock(conf).dominates(exit)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ private BasicBlock nonDominatingActionBlock(ActionConfiguration conf) {
|
||||
exists(ExitBlock exit |
|
||||
result = actionBlock(conf) and
|
||||
exit.getEnclosingCallable() = result.getEnclosingCallable() and
|
||||
not result.bbDominates(exit)
|
||||
not result.dominates(exit)
|
||||
)
|
||||
}
|
||||
|
||||
private class JoinBlock extends BasicBlock {
|
||||
JoinBlock() { 2 <= strictcount(this.getABBPredecessor()) }
|
||||
JoinBlock() { 2 <= strictcount(this.getAPredecessor()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,8 +72,8 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
|
||||
bb = nonDominatingActionBlock(conf)
|
||||
or
|
||||
if bb instanceof JoinBlock
|
||||
then forall(BasicBlock pred | pred = bb.getABBPredecessor() | postActionBlock(pred, conf))
|
||||
else postActionBlock(bb.getABBPredecessor(), conf)
|
||||
then forall(BasicBlock pred | pred = bb.getAPredecessor() | postActionBlock(pred, conf))
|
||||
else postActionBlock(bb.getAPredecessor(), conf)
|
||||
}
|
||||
|
||||
/** Holds if every path through `callable` goes through at least one action node. */
|
||||
|
||||
72
java/ql/lib/semmle/code/java/controlflow/SuccessorType.qll
Normal file
72
java/ql/lib/semmle/code/java/controlflow/SuccessorType.qll
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Provides different types of control flow successor types.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import codeql.util.Boolean
|
||||
|
||||
private newtype TSuccessorType =
|
||||
TNormalSuccessor() or
|
||||
TBooleanSuccessor(Boolean branch) or
|
||||
TExceptionSuccessor()
|
||||
|
||||
/** The type of a control flow successor. */
|
||||
class SuccessorType extends TSuccessorType {
|
||||
/** Gets a textual representation of successor type. */
|
||||
string toString() { result = "SuccessorType" }
|
||||
}
|
||||
|
||||
/** A normal control flow successor. */
|
||||
class NormalSuccessor extends SuccessorType, TNormalSuccessor { }
|
||||
|
||||
/**
|
||||
* An exceptional control flow successor.
|
||||
*
|
||||
* This marks control flow edges that are taken when an exception is thrown.
|
||||
*/
|
||||
class ExceptionSuccessor extends SuccessorType, TExceptionSuccessor { }
|
||||
|
||||
/**
|
||||
* A conditional control flow successor.
|
||||
*
|
||||
* This currently only includes boolean successors (`BooleanSuccessor`).
|
||||
*/
|
||||
class ConditionalSuccessor extends SuccessorType, TBooleanSuccessor {
|
||||
/** Gets the Boolean value of this successor. */
|
||||
boolean getValue() { this = TBooleanSuccessor(result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean control flow successor.
|
||||
*
|
||||
* For example, this program fragment:
|
||||
*
|
||||
* ```java
|
||||
* if (x < 0)
|
||||
* return 0;
|
||||
* else
|
||||
* return 1;
|
||||
* ```
|
||||
*
|
||||
* has a control flow graph containing Boolean successors:
|
||||
*
|
||||
* ```
|
||||
* if
|
||||
* |
|
||||
* x < 0
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* true false
|
||||
* | \
|
||||
* return 0 return 1
|
||||
* ```
|
||||
*/
|
||||
class BooleanSuccessor = ConditionalSuccessor;
|
||||
|
||||
/**
|
||||
* A nullness control flow successor. This is currently unused for Java.
|
||||
*/
|
||||
class NullnessSuccessor extends ConditionalSuccessor {
|
||||
NullnessSuccessor() { none() }
|
||||
}
|
||||
@@ -209,7 +209,7 @@ class UnreachableBasicBlock extends BasicBlock {
|
||||
or
|
||||
// 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
|
||||
forall(BasicBlock bb | bb = this.getAPredecessor() | bb instanceof UnreachableBasicBlock) and
|
||||
not exists(Callable c | c.getBody().getControlFlowNode() = this.getFirstNode()) and
|
||||
not this.getFirstNode().asExpr().getEnclosingStmt() instanceof AssertStmt and
|
||||
not this.getFirstNode().asStmt() instanceof CatchClause
|
||||
@@ -219,11 +219,10 @@ class UnreachableBasicBlock extends BasicBlock {
|
||||
// Not accessible from the switch expression
|
||||
unreachableCaseBlock = constSwitchStmt.getAFailingCase().getBasicBlock() and
|
||||
// Not accessible from the successful case
|
||||
not constSwitchStmt.getMatchingCase().getBasicBlock().getABBSuccessor*() =
|
||||
unreachableCaseBlock
|
||||
not constSwitchStmt.getMatchingCase().getBasicBlock().getASuccessor*() = unreachableCaseBlock
|
||||
|
|
||||
// Blocks dominated by an unreachable case block are unreachable
|
||||
unreachableCaseBlock.bbDominates(this)
|
||||
unreachableCaseBlock.dominates(this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ SsaVariable getADefinition(SsaVariable v, boolean fromBackEdge) {
|
||||
exists(SsaVariable inp, BasicBlock bb, boolean fbe |
|
||||
v.(SsaPhiNode).hasInputFromBlock(inp, bb) and
|
||||
result = getADefinition(inp, fbe) and
|
||||
(if v.getBasicBlock().bbDominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
|
||||
(if v.getBasicBlock().dominates(bb) then fromBackEdge = true else fromBackEdge = fbe)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -290,10 +290,10 @@ private predicate guardImpliesEqual(Guard guard, boolean branch, SsaVariable v,
|
||||
)
|
||||
}
|
||||
|
||||
private ControlFlowNode getAGuardBranchSuccessor(Guard g, boolean branch) {
|
||||
result = g.(Expr).getControlFlowNode().(ConditionNode).getABranchSuccessor(branch)
|
||||
private BasicBlock getAGuardBranchSuccessor(Guard g, boolean branch) {
|
||||
result.getFirstNode() = g.(Expr).getControlFlowNode().(ConditionNode).getABranchSuccessor(branch)
|
||||
or
|
||||
result = g.(SwitchCase).getControlFlowNode() and branch = true
|
||||
result.getFirstNode() = g.(SwitchCase).getControlFlowNode() and branch = true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,7 +306,7 @@ private predicate guardControlsPhiBranch(
|
||||
guard.directlyControls(upd.getBasicBlock(), branch) and
|
||||
upd.getDefiningExpr().(VariableAssign).getSource() = e and
|
||||
upd = phi.getAPhiInput() and
|
||||
guard.getBasicBlock().bbStrictlyDominates(phi.getBasicBlock())
|
||||
guard.getBasicBlock().strictlyDominates(phi.getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -331,7 +331,7 @@ private predicate conditionalAssign(SsaVariable v, Guard guard, boolean branch,
|
||||
forall(SsaVariable other | other != upd and other = phi.getAPhiInput() |
|
||||
guard.directlyControls(other.getBasicBlock(), branch.booleanNot())
|
||||
or
|
||||
other.getBasicBlock().bbDominates(guard.getBasicBlock()) and
|
||||
other.getBasicBlock().dominates(guard.getBasicBlock()) and
|
||||
not other.isLiveAtEndOfBlock(getAGuardBranchSuccessor(guard, branch))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ private predicate valueFlowStepSsa(SsaVariable v, SsaReadPosition pos, Expr e, i
|
||||
exists(Guard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = eqFlowCond(v, e, delta, true, testIsTrue) and
|
||||
guardDirectlyControlsSsaRead(guard, pos, testIsTrue)
|
||||
guardControlsSsaRead(guard, pos, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -298,9 +298,9 @@ private predicate impossibleEdge(BasicBlock bb1, BasicBlock bb2) {
|
||||
private predicate leavingFinally(BasicBlock bb1, BasicBlock bb2, boolean normaledge) {
|
||||
exists(TryStmt try, BlockStmt finally |
|
||||
try.getFinally() = finally and
|
||||
bb1.getABBSuccessor() = bb2 and
|
||||
bb1.getEnclosingStmt().getEnclosingStmt*() = finally and
|
||||
not bb2.getEnclosingStmt().getEnclosingStmt*() = finally and
|
||||
bb1.getASuccessor() = bb2 and
|
||||
bb1.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
|
||||
not bb2.getFirstNode().getEnclosingStmt().getEnclosingStmt*() = finally and
|
||||
if bb1.getLastNode().getANormalSuccessor() = bb2.getFirstNode()
|
||||
then normaledge = true
|
||||
else normaledge = false
|
||||
@@ -339,7 +339,7 @@ private predicate nullVarStep(
|
||||
midssa.isLiveAtEndOfBlock(mid) and
|
||||
not ensureNotNull(midssa).getBasicBlock() = mid and
|
||||
not assertFail(mid, _) and
|
||||
bb = mid.getABBSuccessor() and
|
||||
bb = mid.getASuccessor() and
|
||||
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
|
||||
|
||||
@@ -209,26 +209,20 @@ module Sem implements Semantic<Location> {
|
||||
|
||||
class BasicBlock = J::BasicBlock;
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
private predicate id(ExprParent x, ExprParent y) { 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) }
|
||||
private predicate idOf(BasicBlock x, int y) { idOfAst(x.getFirstNode().getAstNode(), y) }
|
||||
|
||||
int getBlockId1(BasicBlock bb) { idOf(bb, result) }
|
||||
|
||||
final private class FinalGuard = GL::Guard;
|
||||
|
||||
class Guard extends FinalGuard {
|
||||
class Guard extends GL::Guard_v2 {
|
||||
Expr asExpr() { result = this }
|
||||
}
|
||||
|
||||
predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) {
|
||||
GL::implies_v2(g1, b1, g2, b2)
|
||||
}
|
||||
|
||||
class Type = J::Type;
|
||||
|
||||
class IntegerType extends J::IntegralType {
|
||||
|
||||
@@ -19,8 +19,6 @@ predicate ssaUpdateStep = U::ssaUpdateStep/3;
|
||||
|
||||
predicate valueFlowStep = U::valueFlowStep/3;
|
||||
|
||||
predicate guardDirectlyControlsSsaRead = U::guardDirectlyControlsSsaRead/3;
|
||||
|
||||
predicate guardControlsSsaRead = U::guardControlsSsaRead/3;
|
||||
|
||||
predicate eqFlowCond = U::eqFlowCond/5;
|
||||
|
||||
@@ -321,14 +321,14 @@ private module Input implements TypeFlowInput<Location> {
|
||||
*/
|
||||
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) {
|
||||
ioe.getExpr() = v.getAUse() and
|
||||
strictcount(bb.getABBPredecessor()) > 1 and
|
||||
strictcount(bb.getAPredecessor()) > 1 and
|
||||
exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb)
|
||||
}
|
||||
|
||||
/** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */
|
||||
private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) {
|
||||
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
|
||||
strictcount(bb.getABBPredecessor())
|
||||
strictcount(bb.getAPredecessor())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,7 +338,7 @@ private module Input implements TypeFlowInput<Location> {
|
||||
predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) {
|
||||
exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va |
|
||||
instanceofDisjunction(bb, v) and
|
||||
bb.bbDominates(va.getBasicBlock()) and
|
||||
bb.dominates(va.getBasicBlock()) and
|
||||
va = v.getAUse() and
|
||||
instanceofDisjunct(ioe, bb, v) and
|
||||
t = ioe.getSyntacticCheckedType() and
|
||||
|
||||
@@ -145,7 +145,7 @@ private module BaseSsaImpl {
|
||||
/** Holds if `v` has an implicit definition at the entry, `b`, of the callable. */
|
||||
predicate hasEntryDef(BaseSsaSourceVariable v, BasicBlock b) {
|
||||
exists(LocalScopeVariable l, Callable c |
|
||||
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
|
||||
v = TLocalVar(c, l) and c.getBody().getBasicBlock() = b
|
||||
|
|
||||
l instanceof Parameter or
|
||||
l.getCallable() != c
|
||||
@@ -157,15 +157,14 @@ private import BaseSsaImpl
|
||||
|
||||
private module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
private import java as J
|
||||
private import semmle.code.java.controlflow.Dominance as Dom
|
||||
|
||||
class BasicBlock = J::BasicBlock;
|
||||
|
||||
class ControlFlowNode = J::ControlFlowNode;
|
||||
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) }
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class SourceVariable = BaseSsaSourceVariable;
|
||||
|
||||
|
||||
@@ -83,12 +83,12 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
|
||||
|
||||
class ControlFlowNode = J::ControlFlowNode;
|
||||
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { bbIDominates(result, bb) }
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) {
|
||||
result = bb.(J::BasicBlock).getABBSuccessor()
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) {
|
||||
result.(J::BasicBlock).immediatelyDominates(bb)
|
||||
}
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.(J::BasicBlock).getASuccessor() }
|
||||
|
||||
//TODO: support capture of `this` in lambdas
|
||||
class CapturedVariable instanceof LocalScopeVariable {
|
||||
CapturedVariable() {
|
||||
|
||||
@@ -40,14 +40,14 @@ private module ThisFlow {
|
||||
|
||||
private int lastRank(BasicBlock b) { result = max(int rankix | thisRank(_, b, rankix)) }
|
||||
|
||||
private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getABBSuccessor*(), _) }
|
||||
private predicate blockPrecedesThisAccess(BasicBlock b) { thisAccess(_, b.getASuccessor*(), _) }
|
||||
|
||||
private predicate thisAccessBlockReaches(BasicBlock b1, BasicBlock b2) {
|
||||
thisAccess(_, b1, _) and b2 = b1.getABBSuccessor()
|
||||
thisAccess(_, b1, _) and b2 = b1.getASuccessor()
|
||||
or
|
||||
exists(BasicBlock mid |
|
||||
thisAccessBlockReaches(b1, mid) and
|
||||
b2 = mid.getABBSuccessor() and
|
||||
b2 = mid.getASuccessor() and
|
||||
not thisAccess(_, mid, _) and
|
||||
blockPrecedesThisAccess(b2)
|
||||
)
|
||||
|
||||
@@ -144,13 +144,13 @@ private predicate certainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBl
|
||||
pragma[nomagic]
|
||||
private predicate hasEntryDef(TrackedVar v, BasicBlock b) {
|
||||
exists(LocalScopeVariable l, Callable c |
|
||||
v = TLocalVar(c, l) and c.getBody().getControlFlowNode() = b
|
||||
v = TLocalVar(c, l) and c.getBody().getBasicBlock() = b
|
||||
|
|
||||
l instanceof Parameter or
|
||||
l.getCallable() != c
|
||||
)
|
||||
or
|
||||
v instanceof SsaSourceField and v.getEnclosingCallable().getBody().getControlFlowNode() = b
|
||||
v instanceof SsaSourceField and v.getEnclosingCallable().getBody().getBasicBlock() = b
|
||||
}
|
||||
|
||||
/** Holds if `n` might update the locally tracked variable `v`. */
|
||||
@@ -165,15 +165,14 @@ private predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, Basic
|
||||
|
||||
private module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
private import java as J
|
||||
private import semmle.code.java.controlflow.Dominance as Dom
|
||||
|
||||
class BasicBlock = J::BasicBlock;
|
||||
|
||||
class ControlFlowNode = J::ControlFlowNode;
|
||||
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { Dom::bbIDominates(result, bb) }
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) }
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getABBSuccessor() }
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class SourceVariable = SsaSourceVariable;
|
||||
|
||||
@@ -655,16 +654,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
||||
def instanceof SsaUncertainImplicitUpdate
|
||||
}
|
||||
|
||||
class Guard extends Guards::Guard {
|
||||
/**
|
||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
||||
* guard to `branch`.
|
||||
*/
|
||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||
super.hasBranchEdge(bb1, bb2, branch)
|
||||
}
|
||||
}
|
||||
class Guard = Guards::Guard;
|
||||
|
||||
/** Holds if the guard `guard` directly controls block `bb` upon evaluating to `branch`. */
|
||||
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) {
|
||||
|
||||
@@ -4,7 +4,6 @@ module Private {
|
||||
private import semmle.code.java.dataflow.RangeUtils as RU
|
||||
private import semmle.code.java.controlflow.Guards as G
|
||||
private import semmle.code.java.controlflow.BasicBlocks as BB
|
||||
private import semmle.code.java.controlflow.internal.GuardsLogic as GL
|
||||
private import SsaReadPositionCommon
|
||||
|
||||
class BasicBlock = BB::BasicBlock;
|
||||
@@ -15,7 +14,7 @@ module Private {
|
||||
|
||||
class Expr = J::Expr;
|
||||
|
||||
class Guard = G::Guard;
|
||||
class Guard = G::Guard_v2;
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
@@ -101,29 +100,17 @@ module Private {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardDirectlyControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
guard.controls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(Guard guard0, boolean testIsTrue0 |
|
||||
GL::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
guardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.controls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard
|
||||
.controlsBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(),
|
||||
testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,12 @@ module Private {
|
||||
private import semmle.code.java.dataflow.SSA as Ssa
|
||||
private import semmle.code.java.controlflow.Guards as G
|
||||
private import SsaReadPositionCommon
|
||||
private import semmle.code.java.controlflow.internal.GuardsLogic as GL
|
||||
private import Sign
|
||||
import Impl
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
class Guard = G::Guard;
|
||||
class Guard = G::Guard_v2;
|
||||
|
||||
class SsaVariable = Ssa::SsaVariable;
|
||||
|
||||
@@ -170,31 +169,17 @@ module Private {
|
||||
|
||||
predicate ssaRead = RU::ssaRead/2;
|
||||
|
||||
/**
|
||||
* Holds if `guard` directly controls the position `controlled` with the
|
||||
* value `testIsTrue`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate guardDirectlyControlsSsaRead(
|
||||
Guard guard, SsaReadPosition controlled, boolean testIsTrue
|
||||
) {
|
||||
guard.directlyControls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` controls the position `controlled` with the value `testIsTrue`.
|
||||
*/
|
||||
predicate guardControlsSsaRead(Guard guard, SsaReadPosition controlled, boolean testIsTrue) {
|
||||
guardDirectlyControlsSsaRead(guard, controlled, testIsTrue)
|
||||
guard.controls(controlled.(SsaReadPositionBlock).getBlock(), testIsTrue)
|
||||
or
|
||||
exists(Guard guard0, boolean testIsTrue0 |
|
||||
GL::implies_v2(guard0, testIsTrue0, guard, testIsTrue) and
|
||||
guardControlsSsaRead(guard0, controlled, testIsTrue0)
|
||||
exists(SsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled |
|
||||
guard.controls(controlledEdge.getOrigBlock(), testIsTrue) or
|
||||
guard
|
||||
.controlsBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(),
|
||||
testIsTrue)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ private predicate id(BB::ExprParent x, BB::ExprParent y) { 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 predicate idOf(BasicBlock x, int y) { idOfAst(x.getFirstNode().getAstNode(), y) }
|
||||
|
||||
private int getId(BasicBlock bb) { idOf(bb, result) }
|
||||
|
||||
|
||||
@@ -153,8 +153,16 @@ class SpringRequestMappingMethod extends SpringControllerMethod {
|
||||
result = this.getProducesExpr().(CompileTimeConstantExpr).getStringValue()
|
||||
}
|
||||
|
||||
/** Gets the "value" @RequestMapping annotation value, if present. */
|
||||
string getValue() { result = requestMappingAnnotation.getStringValue("value") }
|
||||
/** DEPRECATED: Use `getAValue()` instead. */
|
||||
deprecated string getValue() { result = requestMappingAnnotation.getStringValue("value") }
|
||||
|
||||
/**
|
||||
* Gets a "value" @RequestMapping annotation string value, if present.
|
||||
*
|
||||
* If the annotation element is defined with an array initializer, then the result will be one of the
|
||||
* elements of that array. Otherwise, the result will be the single expression used as value.
|
||||
*/
|
||||
string getAValue() { result = requestMappingAnnotation.getAStringArrayValue("value") }
|
||||
|
||||
/** Gets the "method" @RequestMapping annotation value, if present. */
|
||||
string getMethodValue() {
|
||||
|
||||
@@ -24,6 +24,6 @@ private class SslProceedCall extends MethodCall {
|
||||
/** Holds if `m` trusts all certificates by calling `SslErrorHandler.proceed` unconditionally. */
|
||||
predicate trustsAllCerts(OnReceivedSslErrorMethod m) {
|
||||
exists(SslProceedCall pr | pr.getQualifier().(VarAccess).getVariable() = m.handlerArg() |
|
||||
pr.getBasicBlock().bbPostDominates(m.getBody().getBasicBlock())
|
||||
pr.getBasicBlock().postDominates(m.getBody().getBasicBlock())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ private module ValidationMethod<DataFlow::guardChecksSig/3 validationGuard> {
|
||||
validationMethod(ma.getMethod(), pos) and
|
||||
ma.getArgument(pos) = rv and
|
||||
adjacentUseUseSameVar(rv, result.asExpr()) and
|
||||
ma.getBasicBlock().bbDominates(result.asExpr().getBasicBlock())
|
||||
ma.getBasicBlock().dominates(result.asExpr().getBasicBlock())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ private class FullyDecodesUrlBarrier extends DataFlow::Node {
|
||||
exists(Variable v, Expr e | this.asExpr() = v.getAnAccess() |
|
||||
fullyDecodesUrlGuard(e) and
|
||||
e = v.getAnAccess() and
|
||||
e.getBasicBlock().bbDominates(this.asExpr().getBasicBlock())
|
||||
e.getBasicBlock().dominates(this.asExpr().getBasicBlock())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,16 +40,16 @@ private predicate validatedAccess(VarAccess va) {
|
||||
guardcall.getControlFlowNode() = node
|
||||
|
|
||||
exists(BasicBlock succ |
|
||||
succ = node.getANormalSuccessor() and
|
||||
succ.getFirstNode() = node.getANormalSuccessor() and
|
||||
dominatingEdge(node.getBasicBlock(), succ) and
|
||||
succ.bbDominates(va.getBasicBlock())
|
||||
succ.dominates(va.getBasicBlock())
|
||||
)
|
||||
or
|
||||
exists(BasicBlock bb, int i |
|
||||
bb.getNode(i) = node and
|
||||
bb.getNode(i + 1) = node.getANormalSuccessor()
|
||||
|
|
||||
bb.bbStrictlyDominates(va.getBasicBlock()) or
|
||||
bb.strictlyDominates(va.getBasicBlock()) or
|
||||
bb.getNode(any(int j | j > i)).asExpr() = va
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
## 1.5.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The query `java/hardcoded-credential-api-call` has been removed from all query suites.
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
@@ -99,8 +99,8 @@ predicate failedLock(LockType t, BasicBlock lockblock, BasicBlock exblock) {
|
||||
)
|
||||
) and
|
||||
(
|
||||
lock.getAnExceptionSuccessor() = exblock or
|
||||
lock.(ConditionNode).getAFalseSuccessor() = exblock
|
||||
lock.getAnExceptionSuccessor() = exblock.getFirstNode() or
|
||||
lock.(ConditionNode).getAFalseSuccessor() = exblock.getFirstNode()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -113,7 +113,7 @@ predicate heldByCurrentThreadCheck(LockType t, BasicBlock checkblock, BasicBlock
|
||||
exists(ConditionBlock conditionBlock |
|
||||
conditionBlock.getCondition() = t.getIsHeldByCurrentThreadAccess()
|
||||
|
|
||||
conditionBlock.getBasicBlock() = checkblock and
|
||||
conditionBlock = checkblock and
|
||||
conditionBlock.getTestSuccessor(false) = falsesucc
|
||||
)
|
||||
}
|
||||
@@ -133,7 +133,7 @@ predicate variableLockStateCheck(LockType t, BasicBlock checkblock, BasicBlock f
|
||||
conditionBlock.getTestSuccessor(true) = t.getUnlockAccess().getBasicBlock() and
|
||||
conditionBlock.getCondition() = v
|
||||
|
|
||||
conditionBlock.getBasicBlock() = checkblock and
|
||||
conditionBlock = checkblock and
|
||||
conditionBlock.getTestSuccessor(false) = falsesucc
|
||||
)
|
||||
}
|
||||
@@ -145,9 +145,7 @@ predicate variableLockStateCheck(LockType t, BasicBlock checkblock, BasicBlock f
|
||||
predicate blockIsLocked(LockType t, BasicBlock src, BasicBlock b, int locks) {
|
||||
lockUnlockBlock(t, b, locks) and src = b and locks > 0
|
||||
or
|
||||
exists(BasicBlock pred, int predlocks, int curlocks, int failedlock |
|
||||
pred = b.getABBPredecessor()
|
||||
|
|
||||
exists(BasicBlock pred, int predlocks, int curlocks, int failedlock | pred = b.getAPredecessor() |
|
||||
// The number of net locks from the `src` block to the predecessor block `pred` is `predlocks`.
|
||||
blockIsLocked(t, src, pred, predlocks) and
|
||||
// The recursive call ensures that at least one lock is held, so do not consider the false
|
||||
|
||||
@@ -18,6 +18,6 @@ where
|
||||
iteration = inner.getAnIterationVariable() and
|
||||
iteration = outer.getAnIterationVariable() and
|
||||
inner.getEnclosingStmt+() = outer and
|
||||
inner.getBasicBlock().getABBSuccessor+() = outer.getCondition().getBasicBlock()
|
||||
inner.getBasicBlock().getASuccessor+() = outer.getCondition().getBasicBlock()
|
||||
select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.",
|
||||
iteration, iteration.getName(), outer, "for statement"
|
||||
|
||||
@@ -18,6 +18,7 @@ public class Test {
|
||||
String s1 = "test";
|
||||
s1 = s1.replaceAll("t", "x"); // NON_COMPLIANT
|
||||
s1 = s1.replaceAll(".*", "x"); // COMPLIANT
|
||||
s1 = s1.replace("t", "x"); // COMPLIANT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @precision low
|
||||
* @id java/hardcoded-credential-api-call
|
||||
* @tags security
|
||||
* external/cwe/cwe-798
|
||||
|
||||
@@ -37,7 +37,7 @@ predicate overwritten(VariableUpdate upd) {
|
||||
bb1.getNode(i) = upd.getControlFlowNode() and
|
||||
bb2.getNode(j) = overwrite.getControlFlowNode()
|
||||
|
|
||||
bb1.getABBSuccessor+() = bb2
|
||||
bb1.getASuccessor+() = bb2
|
||||
or
|
||||
bb1 = bb2 and i < j
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ private predicate blockInSwitch(SwitchStmt s, BasicBlock b) {
|
||||
|
||||
private predicate switchCaseControlFlow(SwitchStmt switch, BasicBlock b1, BasicBlock b2) {
|
||||
blockInSwitch(switch, b1) and
|
||||
b1.getABBSuccessor() = b2 and
|
||||
b1.getASuccessor() = b2 and
|
||||
blockInSwitch(switch, b2)
|
||||
}
|
||||
|
||||
|
||||
5
java/ql/src/change-notes/released/1.5.1.md
Normal file
5
java/ql/src/change-notes/released/1.5.1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 1.5.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The query `java/hardcoded-credential-api-call` has been removed from all query suites.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.5.0
|
||||
lastReleaseVersion: 1.5.1
|
||||
|
||||
@@ -13,7 +13,7 @@ import semmle.code.java.dataflow.SSA
|
||||
|
||||
class SsaConvertibleReadAccess extends VarRead {
|
||||
SsaConvertibleReadAccess() {
|
||||
this.getEnclosingCallable().getBody().getBasicBlock().getABBSuccessor*() = this.getBasicBlock() and
|
||||
this.getEnclosingCallable().getBody().getBasicBlock().getASuccessor*() = this.getBasicBlock() and
|
||||
(
|
||||
not exists(this.getQualifier())
|
||||
or
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-queries
|
||||
version: 1.5.0
|
||||
version: 1.5.1
|
||||
groups:
|
||||
- java
|
||||
- queries
|
||||
|
||||
@@ -10,5 +10,5 @@ import internal.CaptureModels
|
||||
import SummaryModels
|
||||
|
||||
from DataFlowSummaryTargetApi api, string flow
|
||||
where flow = ContentSensitive::captureFlow(api, _)
|
||||
where flow = ContentSensitive::captureFlow(api, _, _, _, _)
|
||||
select flow order by flow
|
||||
|
||||
@@ -16,7 +16,7 @@ import PartialFlow::PartialPathGraph
|
||||
|
||||
int explorationLimit() { result = 3 }
|
||||
|
||||
module PartialFlow = Heuristic::PropagateFlow::FlowExplorationFwd<explorationLimit/0>;
|
||||
module PartialFlow = Heuristic::PropagateTaintFlow::FlowExplorationFwd<explorationLimit/0>;
|
||||
|
||||
from
|
||||
PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink,
|
||||
|
||||
@@ -12,16 +12,15 @@ import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import SummaryModels
|
||||
import Heuristic
|
||||
import PropagateFlow::PathGraph
|
||||
import Heuristic::PropagateTaintFlow::PathGraph
|
||||
|
||||
from
|
||||
PropagateFlow::PathNode source, PropagateFlow::PathNode sink, DataFlowSummaryTargetApi api,
|
||||
DataFlow::Node p, DataFlow::Node returnNodeExt
|
||||
Heuristic::PropagateTaintFlow::PathNode source, Heuristic::PropagateTaintFlow::PathNode sink,
|
||||
DataFlowSummaryTargetApi api, DataFlow::Node p, DataFlow::Node returnNodeExt
|
||||
where
|
||||
PropagateFlow::flowPath(source, sink) and
|
||||
Heuristic::PropagateTaintFlow::flowPath(source, sink) and
|
||||
p = source.getNode() and
|
||||
returnNodeExt = sink.getNode() and
|
||||
exists(captureThroughFlow0(api, p, returnNodeExt))
|
||||
Heuristic::captureThroughFlow0(api, p, returnNodeExt)
|
||||
select sink.getNode(), source, sink, "There is flow from $@ to the $@.", source.getNode(),
|
||||
"parameter", sink.getNode(), "return value"
|
||||
|
||||
@@ -92,7 +92,7 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Locatio
|
||||
|
||||
string qualifierString() { result = "Argument[this]" }
|
||||
|
||||
string parameterAccess(J::Parameter p) {
|
||||
string parameterApproximateAccess(J::Parameter p) {
|
||||
if
|
||||
p.getType() instanceof J::Array and
|
||||
not isPrimitiveTypeUsedForBulkData(p.getType().(J::Array).getElementType())
|
||||
@@ -103,20 +103,20 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Locatio
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
string parameterContentAccess(J::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
string parameterExactAccess(J::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
|
||||
|
||||
class InstanceParameterNode = DataFlow::InstanceParameterNode;
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterAccess(c.getParameter(pos))
|
||||
string paramReturnNodeAsApproximateOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterApproximateAccess(c.getParameter(pos))
|
||||
or
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterContentAccess(c.getParameter(pos))
|
||||
string paramReturnNodeAsExactOutput(Callable c, ParameterPosition pos) {
|
||||
result = parameterExactAccess(c.getParameter(pos))
|
||||
or
|
||||
result = qualifierString() and pos = -1
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import default
|
||||
import java
|
||||
import semmle.code.java.controlflow.Dominance
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where bbStrictlyDominates(b, b2)
|
||||
where b.strictlyDominates(b2)
|
||||
select b, b2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import default
|
||||
import java
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where b.getABBSuccessor() = b2
|
||||
where b.getASuccessor() = b2
|
||||
select b, b2
|
||||
|
||||
@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
|
||||
|
||||
from Callable c, ControlFlowNode dom, ControlFlowNode node
|
||||
where
|
||||
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
|
||||
strictlyDominates(dom, node) and
|
||||
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
|
||||
select c, dom, node
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import default
|
||||
import java
|
||||
import semmle.code.java.controlflow.Dominance
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where bbStrictlyDominates(b, b2)
|
||||
where b.strictlyDominates(b2)
|
||||
select b, b2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import default
|
||||
import java
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where b.getABBSuccessor() = b2
|
||||
where b.getASuccessor() = b2
|
||||
select b, b2
|
||||
|
||||
@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
|
||||
|
||||
from Callable c, ControlFlowNode dom, ControlFlowNode node
|
||||
where
|
||||
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
|
||||
strictlyDominates(dom, node) and
|
||||
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
|
||||
select c, dom, node
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import default
|
||||
import java
|
||||
import semmle.code.java.controlflow.Dominance
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where bbStrictlyDominates(b, b2)
|
||||
where b.strictlyDominates(b2)
|
||||
select b, b2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import default
|
||||
import java
|
||||
|
||||
from BasicBlock b, BasicBlock b2
|
||||
where b.getABBSuccessor() = b2
|
||||
where b.getASuccessor() = b2
|
||||
select b, b2
|
||||
|
||||
@@ -16,6 +16,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co
|
||||
|
||||
from Callable c, ControlFlowNode dom, ControlFlowNode node
|
||||
where
|
||||
(strictlyDominates(dom, node) or bbStrictlyDominates(dom, node)) and
|
||||
strictlyDominates(dom, node) and
|
||||
dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node)
|
||||
select c, dom, node
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import java
|
||||
import utils.test.InlineExpectationsTest
|
||||
private import semmle.code.java.frameworks.spring.SpringController
|
||||
|
||||
module TestRequestController implements TestSig {
|
||||
string getARelevantTag() { result = "RequestMappingURL" }
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "RequestMappingURL" and
|
||||
exists(SpringRequestMappingMethod m |
|
||||
m.getLocation() = location and
|
||||
element = m.toString() and
|
||||
value = "\"" + m.getAValue() + "\""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<TestRequestController>
|
||||
@@ -32,92 +32,93 @@ import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
|
||||
public class Test {
|
||||
|
||||
static void sink(Object o) {}
|
||||
static void sink(Object o) {
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class NotTaintedTest {
|
||||
@RequestMapping("/")
|
||||
public void get(WebRequest src) {
|
||||
public void get(WebRequest src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(NativeWebRequest src) {
|
||||
public void get(NativeWebRequest src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(ServletRequest src) {
|
||||
public void get(ServletRequest src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(HttpSession src) {
|
||||
public void get(HttpSession src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(PushBuilder src) {
|
||||
public void get(PushBuilder src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Principal src) {
|
||||
public void get(Principal src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(HttpMethod src) {
|
||||
public void get(HttpMethod src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Locale src) {
|
||||
public void get(Locale src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(TimeZone src) {
|
||||
public void get(TimeZone src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(ZoneId src) {
|
||||
public void get(ZoneId src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(OutputStream src) {
|
||||
public void get(OutputStream src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Writer src) {
|
||||
public void get(Writer src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(RedirectAttributes src) {
|
||||
public void get(RedirectAttributes src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Errors src) {
|
||||
public void get(Errors src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(SessionStatus src) {
|
||||
public void get(SessionStatus src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(UriComponentsBuilder src) {
|
||||
public void get(UriComponentsBuilder src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Pageable src) {
|
||||
public void get(Pageable src) { // $ RequestMappingURL="/"
|
||||
sink(src);
|
||||
}
|
||||
}
|
||||
@@ -125,62 +126,62 @@ public class Test {
|
||||
@Controller
|
||||
static class ExplicitlyTaintedTest {
|
||||
@RequestMapping("/")
|
||||
public void get(InputStream src) {
|
||||
public void get(InputStream src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(Reader src) {
|
||||
public void get(Reader src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void matrixVariable(@MatrixVariable Object src) {
|
||||
public void matrixVariable(@MatrixVariable Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void requestParam(@RequestParam Object src) {
|
||||
public void requestParam(@RequestParam Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void requestHeader(@RequestHeader Object src) {
|
||||
public void requestHeader(@RequestHeader Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void cookieValue(@CookieValue Object src) {
|
||||
public void cookieValue(@CookieValue Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void requestPart(@RequestPart Object src) {
|
||||
public void requestPart(@RequestPart Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void pathVariable(@PathVariable Object src) {
|
||||
public void pathVariable(@PathVariable Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void requestBody(@RequestBody Object src) {
|
||||
public void requestBody(@RequestBody Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(HttpEntity src) {
|
||||
public void get(HttpEntity src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void requestAttribute(@RequestAttribute Object src) {
|
||||
public void requestAttribute(@RequestAttribute Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void sessionAttribute(@SessionAttribute Object src) {
|
||||
public void sessionAttribute(@SessionAttribute Object src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
}
|
||||
@@ -191,13 +192,20 @@ public class Test {
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get(String src) {
|
||||
public void get(String src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
|
||||
@RequestMapping("/")
|
||||
public void get1(Pojo src) {
|
||||
public void get1(Pojo src) { // $ RequestMappingURL="/"
|
||||
sink(src); // $hasValueFlow
|
||||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
static class MultipleValuesTest {
|
||||
@RequestMapping({"/a", "/b"})
|
||||
public void get(WebRequest src) { // $ RequestMappingURL="/a" RequestMappingURL="/b"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,5 +3,6 @@ public class Test {
|
||||
String s1 = "test";
|
||||
s1 = s1.replaceAll("t", "x"); // $ Alert // NON_COMPLIANT
|
||||
s1 = s1.replaceAll(".*", "x"); // COMPLIANT
|
||||
s1 = s1.replace("t", "x"); // COMPLIANT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import SummaryModels
|
||||
import utils.test.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = ContentSensitive::captureFlow(c, _) }
|
||||
string getCapturedModel(Callable c) { result = ContentSensitive::captureFlow(c, _, _, _, _) }
|
||||
|
||||
string getKind() { result = "contentbased-summary" }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import SummaryModels
|
||||
import utils.test.InlineMadTest
|
||||
|
||||
module InlineMadTestConfig implements InlineMadTestConfigSig {
|
||||
string getCapturedModel(Callable c) { result = Heuristic::captureFlow(c) }
|
||||
string getCapturedModel(Callable c) { result = Heuristic::captureFlow(c, _) }
|
||||
|
||||
string getKind() { result = "heuristic-summary" }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ public final class FinalClass {
|
||||
|
||||
private static final String C = "constant";
|
||||
|
||||
// heuristic-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class ImmutablePojo {
|
||||
return x;
|
||||
}
|
||||
|
||||
// heuristic-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// heuristic-summary=p;ImmutablePojo;false;or;(String);;Argument[this];ReturnValue;taint;df-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
// contentbased-summary=p;ImmutablePojo;false;or;(String);;Argument[this].SyntheticField[p.ImmutablePojo.value];ReturnValue;value;dfc-generated
|
||||
|
||||
@@ -10,7 +10,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class AImplBasePrivateImpl extends BasePrivate {
|
||||
// heuristic-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$AImplBasePrivateImpl;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
@@ -19,7 +19,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class AImplBasePublic extends BasePublic {
|
||||
// heuristic-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$BasePublic;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
@@ -60,7 +60,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class BImpl extends B {
|
||||
// heuristic-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic1;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
@@ -69,7 +69,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class CImpl extends C {
|
||||
// heuristic-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$C;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
@@ -78,7 +78,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class DImpl extends D {
|
||||
// heuristic-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$IPublic2;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
@@ -87,7 +87,7 @@ public class Inheritance {
|
||||
}
|
||||
|
||||
public class EImpl extends E {
|
||||
// heuristic-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;Inheritance$EImpl;true;id;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
@Override
|
||||
public String id(String s) {
|
||||
|
||||
@@ -9,14 +9,14 @@ public class InnerClasses {
|
||||
}
|
||||
|
||||
public class CaptureMe {
|
||||
// heuristic-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String yesCm(String input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// heuristic-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String yes(String input) {
|
||||
return input;
|
||||
|
||||
@@ -2,7 +2,7 @@ package p;
|
||||
|
||||
public class MultiPaths {
|
||||
|
||||
// heuristic-summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultiPaths;true;cond;(String,String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String cond(String x, String other) {
|
||||
if (x == other) {
|
||||
|
||||
@@ -16,7 +16,7 @@ class MultipleImpl2 {
|
||||
}
|
||||
|
||||
public class Impl2 implements IInterface {
|
||||
// heuristic-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultipleImpl2$IInterface;true;m;(Object);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public Object m(Object value) {
|
||||
return value;
|
||||
|
||||
@@ -9,7 +9,7 @@ public class MultipleImpls {
|
||||
}
|
||||
|
||||
public static class Strat1 implements Strategy {
|
||||
// heuristic-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String doSomething(String value) {
|
||||
return value;
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.List;
|
||||
|
||||
public class ParamFlow {
|
||||
|
||||
// heuristic-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
public String returnsInput(String input) {
|
||||
return input;
|
||||
@@ -18,8 +18,8 @@ public class ParamFlow {
|
||||
return input.length();
|
||||
}
|
||||
|
||||
// heuristic-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint;df-generated
|
||||
// heuristic-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;value;df-generated
|
||||
// heuristic-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;value;df-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;value;dfc-generated
|
||||
// contentbased-summary=p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;value;dfc-generated
|
||||
public String returnMultipleParameters(String one, String two) {
|
||||
|
||||
@@ -40,8 +40,8 @@ public class Sources {
|
||||
return socketStream();
|
||||
}
|
||||
|
||||
// source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0].ArrayElement;remote;df-generated
|
||||
// source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1].Element;remote;df-generated
|
||||
// source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0];remote;df-generated
|
||||
// source=p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1];remote;df-generated
|
||||
// neutral=p;Sources;sourceToParameter;(InputStream[],List);summary;df-generated
|
||||
public void sourceToParameter(InputStream[] streams, List<InputStream> otherStreams)
|
||||
throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user