Merge remote-tracking branch 'upstream/main' into dataflow/interpret-read-store

This commit is contained in:
Tom Hvitved
2022-04-22 14:35:02 +02:00
531 changed files with 13215 additions and 19839 deletions

View File

@@ -1,3 +1,28 @@
## 0.0.13
## 0.0.12
### Breaking Changes
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
### Deprecated APIs
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
### Minor Analysis Improvements
* Added new guards `IsWindowsGuard`, `IsSpecificWindowsVariant`, `IsUnixGuard`, and `IsSpecificUnixVariant` to detect OS specific guards.
* Added a new predicate `getSystemProperty` that gets all expressions that retrieve system properties from a variety of sources (eg. alternative JDK API's, Google Guava, Apache Commons, Apache IO, etc.).
* Added support for detection of SSRF via JDBC database URLs, including connections made using the standard library (`java.sql`), Hikari Connection Pool, JDBI and Spring JDBC.
* Re-removed support for `CharacterLiteral` from `CompileTimeConstantExpr.getStringValue()` to restore the convention that that predicate only applies to `String`-typed constants.
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
## 0.0.11
### New Features

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -1,5 +0,0 @@
---
category: deprecated
---
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Re-removed support for `CharacterLiteral` from `CompileTimeConstantExpr.getStringValue()` to restore the convention that that predicate only applies to `String`-typed constants.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added support for detection of SSRF via JDBC database URLs, including connections made using the standard library (`java.sql`), Hikari Connection Pool, JDBI and Spring JDBC.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* The `getUrl` predicate of `DeclaredRepository` in `MavenPom.qll` has been renamed to `getRepositoryUrl`.

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.

View File

@@ -0,0 +1,22 @@
## 0.0.12
### Breaking Changes
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
### Deprecated APIs
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.
### New Features
* The data flow and taint tracking libraries have been extended with versions of `isBarrierIn`, `isBarrierOut`, and `isBarrierGuard`, respectively `isSanitizerIn`, `isSanitizerOut`, and `isSanitizerGuard`, that support flow states.
### Minor Analysis Improvements
* Added new guards `IsWindowsGuard`, `IsSpecificWindowsVariant`, `IsUnixGuard`, and `IsSpecificUnixVariant` to detect OS specific guards.
* Added a new predicate `getSystemProperty` that gets all expressions that retrieve system properties from a variety of sources (eg. alternative JDK API's, Google Guava, Apache Commons, Apache IO, etc.).
* Added support for detection of SSRF via JDBC database URLs, including connections made using the standard library (`java.sql`), Hikari Connection Pool, JDBI and Spring JDBC.
* Re-removed support for `CharacterLiteral` from `CompileTimeConstantExpr.getStringValue()` to restore the convention that that predicate only applies to `String`-typed constants.
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.

View File

@@ -0,0 +1 @@
## 0.0.13

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.11
lastReleaseVersion: 0.0.13

View File

@@ -1,5 +1,5 @@
name: codeql/java-all
version: 0.0.12-dev
version: 0.1.0-dev
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java

View File

@@ -355,9 +355,11 @@ class ReflectiveMethodAccess extends ClassMethodAccess {
then
// The method must be declared on the type itself.
result.getDeclaringType() = this.getInferredClassType()
else
// The method may be declared on an inferred type or a super-type.
else (
// The method must be public, and declared or inherited by the inferred class type.
result.isPublic() and
this.getInferredClassType().inherits(result)
)
) and
// Only consider instances where the method name is provided as a `StringLiteral`.
result.hasName(this.getArgument(0).(StringLiteral).getValue())

View File

@@ -438,13 +438,27 @@ class SwitchCase extends Stmt, @case {
/**
* Gets the expression on the right-hand side of the arrow, if any.
*
* Note, this predicate gets a value when this switch case is of the form
* `case e1 -> e2`, where `e2` is neither a block nor a throw statement.
* This predicate is mutually exclusive with `getRuleStatement`.
*/
Expr getRuleExpression() { result.getParent() = this and result.getIndex() = -1 }
Expr getRuleExpression() {
result.getParent() = this and result.getIndex() = -1
or
exists(ExprStmt es | es.getParent() = this and es.getIndex() = -1 | result = es.getExpr())
}
/**
* Gets the statement on the right-hand side of the arrow, if any.
*
* Note, this predicate gets a value when this switch case is of the form
* `case e1 -> { s1; s2; ... }` or `case e1 -> throw ...`.
* This predicate is mutually exclusive with `getRuleExpression`.
*/
Stmt getRuleStatement() { result.getParent() = this and result.getIndex() = -1 }
Stmt getRuleStatement() {
result.getParent() = this and result.getIndex() = -1 and not result instanceof ExprStmt
}
}
/** A constant `case` of a switch statement. */

View File

@@ -404,10 +404,17 @@ private predicate summaryModel(string row) {
any(SummaryModelCsv s).row(row)
}
bindingset[input]
private predicate getKind(string input, string kind, boolean generated) {
input.splitAt(":", 0) = "generated" and kind = input.splitAt(":", 1) and generated = true
or
not input.matches("%:%") and kind = input and generated = false
}
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind
string output, string kind, boolean generated
) {
exists(string row |
sourceModel(row) and
@@ -419,14 +426,14 @@ predicate sourceModel(
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
)
}
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind
string input, string kind, boolean generated
) {
exists(string row |
sinkModel(row) and
@@ -438,22 +445,22 @@ predicate sinkModel(
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
)
}
/** Holds if a summary model exists for the given parameters. */
predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind
string input, string output, string kind, boolean generated
) {
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, _)
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated, _)
}
/** Holds if a summary model `row` exists for the given parameters. */
predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string row
string input, string output, string kind, boolean generated, string row
) {
summaryModel(row) and
row.splitAt(";", 0) = namespace and
@@ -465,13 +472,13 @@ predicate summaryModel(
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated))
}
private predicate relevantPackage(string package) {
sourceModel(package, _, _, _, _, _, _, _) or
sinkModel(package, _, _, _, _, _, _, _) or
summaryModel(package, _, _, _, _, _, _, _, _)
sourceModel(package, _, _, _, _, _, _, _, _) or
sinkModel(package, _, _, _, _, _, _, _, _) or
summaryModel(package, _, _, _, _, _, _, _, _, _, _)
}
private predicate packageLink(string shortpkg, string longpkg) {
@@ -499,25 +506,25 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
part = "source" and
n =
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
string ext, string output |
string ext, string output, boolean generated |
canonicalPkgLink(package, subpkg) and
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind)
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, generated)
)
or
part = "sink" and
n =
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
string ext, string input |
string ext, string input, boolean generated |
canonicalPkgLink(package, subpkg) and
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind)
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, generated)
)
or
part = "summary" and
n =
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
string ext, string input, string output |
string ext, string input, string output, boolean generated |
canonicalPkgLink(package, subpkg) and
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind)
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, generated)
)
)
}
@@ -527,11 +534,11 @@ module CsvValidation {
/** Holds if some row in a CSV-based flow model appears to contain typos. */
query predicate invalidModelRow(string msg) {
exists(string pred, string namespace, string type, string name, string signature, string ext |
sourceModel(namespace, type, _, name, signature, ext, _, _) and pred = "source"
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _) and pred = "sink"
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "summary"
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
msg = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -550,9 +557,9 @@ module CsvValidation {
)
or
exists(string pred, string input, string part |
sinkModel(_, _, _, _, _, _, input, _) and pred = "sink"
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
or
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
|
(
invalidSpecComponent(input, part) and
@@ -567,9 +574,9 @@ module CsvValidation {
)
or
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _) and pred = "source"
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
or
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
|
invalidSpecComponent(output, part) and
not part = "" and
@@ -598,6 +605,13 @@ module CsvValidation {
msg = "Invalid boolean \"" + b + "\" in " + pred + " model."
)
)
or
exists(string row, string k, string kind | summaryModel(row) |
k = row.splitAt(";", 8) and
getKind(k, kind, _) and
not kind = ["taint", "value"] and
msg = "Invalid kind \"" + kind + "\" in summary model."
)
}
}
@@ -605,9 +619,9 @@ pragma[nomagic]
private predicate elementSpec(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {
sourceModel(namespace, type, subtypes, name, signature, ext, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _)
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
}
private string paramsStringPart(Callable c, int i) {

View File

@@ -0,0 +1,7 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) taint-tracking analyses.
*/
module TaintTracking3 {
import semmle.code.java.dataflow.internal.tainttracking3.TaintTrackingImpl
}

View File

@@ -42,9 +42,7 @@ module AccessPath {
* Parses a lower-bounded interval `n..` and gets the lower bound.
*/
bindingset[arg]
private int parseLowerBound(string arg) {
result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt()
}
int parseLowerBound(string arg) { result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt() }
/**
* Parses an integer constant or interval (bounded or unbounded) that explicitly

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -87,21 +87,9 @@ abstract class Configuration extends string {
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
/**
* Holds if data flow into `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierIn(Node node, FlowState state) { none() }
/** Holds if data flow out of `node` is prohibited. */
predicate isBarrierOut(Node node) { none() }
/**
* Holds if data flow out of `node` is prohibited when the flow state is
* `state`
*/
predicate isBarrierOut(Node node, FlowState state) { none() }
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
predicate isBarrierGuard(BarrierGuard guard) { none() }
@@ -321,7 +309,7 @@ private class RetNodeEx extends NodeEx {
ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
}
private predicate fullInBarrier(NodeEx node, Configuration config) {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n)
@@ -330,16 +318,7 @@ private predicate fullInBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateInBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierIn(n, state)
|
config.isSource(n, state)
)
}
private predicate fullOutBarrier(NodeEx node, Configuration config) {
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n)
@@ -348,15 +327,6 @@ private predicate fullOutBarrier(NodeEx node, Configuration config) {
)
}
private predicate stateOutBarrier(NodeEx node, FlowState state, Configuration config) {
exists(Node n |
node.asNode() = n and
config.isBarrierOut(n, state)
|
config.isSink(n, state)
)
}
pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
@@ -382,12 +352,6 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
exists(Node n | node.asNode() = n |
config.isBarrier(n, state)
or
config.isBarrierIn(n, state) and
not config.isSource(n, state)
or
config.isBarrierOut(n, state) and
not config.isSink(n, state)
or
exists(BarrierGuard g |
config.isBarrierGuard(g, state) and
n = g.getAGuardedNode()
@@ -420,8 +384,8 @@ private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
/** Provides the relevant barriers for a step from `node1` to `node2`. */
pragma[inline]
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
not fullOutBarrier(node1, config) and
not fullInBarrier(node2, config) and
not outBarrier(node1, config) and
not inBarrier(node2, config) and
not fullBarrier(node1, config) and
not fullBarrier(node2, config)
}
@@ -474,8 +438,6 @@ private predicate additionalLocalStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config)
)
@@ -517,8 +479,6 @@ private predicate additionalJumpStateStep(
config.isAdditionalFlowStep(n1, s1, n2, s2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2, config) and
not stateOutBarrier(node1, s1, config) and
not stateInBarrier(node2, s2, config) and
not stateBarrier(node1, s1, config) and
not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -970,8 +930,8 @@ private module Stage1 {
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
revFlow(node, true, config) and
fwdFlow(node, true, config) and
not fullInBarrier(node, config) and
not fullOutBarrier(node, config)
not inBarrier(node, config) and
not outBarrier(node, config)
}
/** Holds if flow may return from `callable`. */
@@ -1066,8 +1026,8 @@ private predicate flowOutOfCallNodeCand1(
) {
viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
Stage1::revFlow(ret, config) and
not fullOutBarrier(ret, config) and
not fullInBarrier(out, config)
not outBarrier(ret, config) and
not inBarrier(out, config)
}
pragma[nomagic]
@@ -1088,8 +1048,8 @@ private predicate flowIntoCallNodeCand1(
) {
viableParamArgNodeCand1(call, p, arg, config) and
Stage1::revFlow(p, config) and
not fullOutBarrier(arg, config) and
not fullInBarrier(p, config)
not outBarrier(arg, config) and
not inBarrier(p, config)
}
/**
@@ -1210,8 +1170,8 @@ private module Stage2 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
bindingset[node1, state1, config]
bindingset[node2, state2, config]
@@ -1298,7 +1258,7 @@ private module Stage2 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2003,8 +1963,8 @@ private module Stage3 {
bindingset[call, c, innercc]
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) { any() }
private predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
@@ -2104,7 +2064,7 @@ private module Stage3 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -2834,12 +2794,11 @@ private module Stage4 {
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
}
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
bindingset[node, cc]
private LocalCc getLocalCc(NodeEx node, Cc cc) {
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable()) and
exists(config)
node.getEnclosingCallable())
}
private predicate localStep(
@@ -2932,7 +2891,7 @@ private module Stage4 {
or
exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
localCc = getLocalCc(mid, cc)
|
localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
@@ -5119,6 +5078,7 @@ private module FlowExploration {
)
}
pragma[nomagic]
private predicate revPartialPathStep(
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config

View File

@@ -807,10 +807,10 @@ module Private {
module External {
/** Holds if `spec` is a relevant external specification. */
private predicate relevantSpec(string spec) {
summaryElement(_, spec, _, _) or
summaryElement(_, _, spec, _) or
sourceElement(_, spec, _) or
sinkElement(_, spec, _)
summaryElement(_, spec, _, _, _) or
summaryElement(_, _, spec, _, _) or
sourceElement(_, spec, _, _) or
sinkElement(_, spec, _, _)
}
private class AccessPathRange extends AccessPath::Range {
@@ -876,13 +876,20 @@ module Private {
}
private class SummarizedCallableExternal extends SummarizedCallable {
SummarizedCallableExternal() { summaryElement(this, _, _, _) }
SummarizedCallableExternal() { summaryElement(this, _, _, _, _) }
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
summaryElement(this, inSpec, outSpec, kind, false)
or
summaryElement(this, inSpec, outSpec, kind, true) and
not summaryElement(this, _, _, _, false)
}
override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
exists(AccessPath inSpec, AccessPath outSpec, string kind |
summaryElement(this, inSpec, outSpec, kind) and
this.relevantSummaryElement(inSpec, outSpec, kind) and
interpretSpec(inSpec, input) and
interpretSpec(outSpec, output)
|
@@ -911,7 +918,7 @@ module Private {
private predicate sourceElementRef(InterpretNode ref, AccessPath output, string kind) {
exists(SourceOrSinkElement e |
sourceElement(e, output, kind) and
sourceElement(e, output, kind, _) and
if outputNeedsReference(output.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()
@@ -920,7 +927,7 @@ module Private {
private predicate sinkElementRef(InterpretNode ref, AccessPath input, string kind) {
exists(SourceOrSinkElement e |
sinkElement(e, input, kind) and
sinkElement(e, input, kind, _) and
if inputNeedsReference(input.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()
@@ -1057,8 +1064,8 @@ module Private {
|
c.relevantSummary(input, output, preservesValue) and
csv =
c.getCallableCsv() + ";" + getComponentStackCsv(input) + ";" +
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
";" + renderKind(preservesValue)
)
}
}

View File

@@ -53,13 +53,16 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
/**
* Holds if an external flow summary exists for `c` with input specification
* `input`, output specification `output`, and kind `kind`.
* `input`, output specification `output`, kind `kind`, and a flag `generated`
* stating whether the summary is autogenerated.
*/
predicate summaryElement(DataFlowCallable c, string input, string output, string kind) {
predicate summaryElement(
DataFlowCallable c, string input, string output, string kind, boolean generated
) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind) and
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated) and
c.asCallable() = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
@@ -112,26 +115,28 @@ class SourceOrSinkElement = Top;
/**
* Holds if an external source specification exists for `e` with output specification
* `output` and kind `kind`.
* `output`, kind `kind`, and a flag `generated` stating whether the source specification is
* autogenerated.
*/
predicate sourceElement(SourceOrSinkElement e, string output, string kind) {
predicate sourceElement(SourceOrSinkElement e, string output, string kind, boolean generated) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind) and
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, generated) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
/**
* Holds if an external sink specification exists for `e` with input specification
* `input` and kind `kind`.
* `input`, kind `kind` and a flag `generated` stating whether the sink specification is
* autogenerated.
*/
predicate sinkElement(SourceOrSinkElement e, string input, string kind) {
predicate sinkElement(SourceOrSinkElement e, string input, string kind, boolean generated) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind) and
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, generated) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}

View File

@@ -109,16 +109,6 @@ abstract class Configuration extends DataFlow::Configuration {
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
@@ -126,16 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }

View File

@@ -109,16 +109,6 @@ abstract class Configuration extends DataFlow::Configuration {
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
/**
* Holds if taint propagation into `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerIn(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerIn(node, state)
}
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
@@ -126,16 +116,6 @@ abstract class Configuration extends DataFlow::Configuration {
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/**
* Holds if taint propagation out of `node` is prohibited when the flow state is
* `state`.
*/
predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizerOut(node, state)
}
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }

View File

@@ -0,0 +1,176 @@
/**
* Provides an implementation of global (interprocedural) taint tracking.
* This file re-exports the local (intraprocedural) taint-tracking analysis
* from `TaintTrackingParameter::Public` and adds a global analysis, mainly
* exposed through the `Configuration` class. For some languages, this file
* exists in several identical copies, allowing queries to use multiple
* `Configuration` classes that depend on each other without introducing
* mutual recursion among those configurations.
*/
import TaintTrackingParameter::Public
private import TaintTrackingParameter::Private
/**
* A configuration of interprocedural taint tracking analysis. This defines
* sources, sinks, and any other configurable aspect of the analysis. Each
* use of the taint tracking library must define its own unique extension of
* this abstract class.
*
* A taint-tracking configuration is a special data flow configuration
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
* necessarily preserve values but are still relevant from a taint tracking
* perspective. (For example, string concatenation, where one of the operands
* is tainted.)
*
* To create a configuration, extend this class with a subclass whose
* characteristic predicate is a unique singleton string. For example, write
*
* ```ql
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
* // Optionally override `isSanitizer`.
* // Optionally override `isSanitizerIn`.
* // Optionally override `isSanitizerOut`.
* // Optionally override `isSanitizerGuard`.
* // Optionally override `isAdditionalTaintStep`.
* }
* ```
*
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
* Multiple configurations can coexist, but it is unsupported to depend on
* another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the
* overridden predicates that define sources, sinks, or additional steps.
* Instead, the dependency should go to a `TaintTracking2::Configuration` or a
* `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc.
*/
abstract class Configuration extends DataFlow::Configuration {
bindingset[this]
Configuration() { any() }
/**
* Holds if `source` is a relevant taint source.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is a relevant taint source with the given initial
* `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
/**
* Holds if `sink` is a relevant taint sink
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink) { none() }
/**
* Holds if `sink` is a relevant taint sink accepting `state`.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
/** Holds if the node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/**
* Holds if the node `node` is a taint sanitizer when the flow state is
* `state`.
*/
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
this.isSanitizer(node, state)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
/** Holds if taint propagation out of `node` is prohibited. */
predicate isSanitizerOut(DataFlow::Node node) { none() }
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
}
/**
* Holds if taint propagation through nodes guarded by `guard` is prohibited
* when the flow state is `state`.
*/
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
this.isSanitizerGuard(guard, state)
}
/**
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
*/
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}
/**
* Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps.
* This step is only applicable in `state1` and updates the flow state to `state2`.
*/
predicate isAdditionalTaintStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
none()
}
final override predicate isAdditionalFlowStep(
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
DataFlow::FlowState state2
) {
this.isAdditionalTaintStep(node1, state1, node2, state2)
}
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
defaultImplicitTaintRead(node, c)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
// overridden to provide taint-tracking specific qldoc
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
super.hasFlow(source, sink)
}
}

View File

@@ -0,0 +1,5 @@
import semmle.code.java.dataflow.internal.TaintTrackingUtil as Public
module Private {
import semmle.code.java.dataflow.DataFlow3::DataFlow3 as DataFlow
}

View File

@@ -30,7 +30,7 @@ class Yaml extends RefType {
Yaml() { this.getAnAncestor().hasQualifiedName("org.yaml.snakeyaml", "Yaml") }
}
private class SafeYamlConstructionFlowConfig extends DataFlow2::Configuration {
private class SafeYamlConstructionFlowConfig extends DataFlow3::Configuration {
SafeYamlConstructionFlowConfig() { this = "SnakeYaml::SafeYamlConstructionFlowConfig" }
override predicate isSource(DataFlow::Node src) {
@@ -65,7 +65,7 @@ private class SnakeYamlParse extends MethodAccess {
}
}
private class SafeYamlFlowConfig extends DataFlow3::Configuration {
private class SafeYamlFlowConfig extends DataFlow2::Configuration {
SafeYamlFlowConfig() { this = "SnakeYaml::SafeYamlFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeYaml }

View File

@@ -112,23 +112,26 @@ private predicate isOsFromApacheCommons(FieldAccess fa, string fieldNamePattern)
}
private class IsWindowsFromApacheCommons extends IsWindowsGuard instanceof FieldAccess {
IsWindowsFromApacheCommons() { isOsFromApacheCommons(this, "IS_OS_WINDOWS") }
IsWindowsFromApacheCommons() { isOsFromApacheCommons(this, "IS\\_OS\\_WINDOWS") }
}
private class IsSpecificWindowsVariantFromApacheCommons extends IsSpecificWindowsVariant instanceof FieldAccess {
IsSpecificWindowsVariantFromApacheCommons() { isOsFromApacheCommons(this, "IS_OS_WINDOWS_%") }
IsSpecificWindowsVariantFromApacheCommons() {
isOsFromApacheCommons(this, "IS\\_OS\\_WINDOWS\\_%")
}
}
private class IsUnixFromApacheCommons extends IsUnixGuard instanceof FieldAccess {
IsUnixFromApacheCommons() { isOsFromApacheCommons(this, "IS_OS_UNIX") }
IsUnixFromApacheCommons() { isOsFromApacheCommons(this, "IS\\_OS\\_UNIX") }
}
private class IsSpecificUnixVariantFromApacheCommons extends IsSpecificUnixVariant instanceof FieldAccess {
IsSpecificUnixVariantFromApacheCommons() {
isOsFromApacheCommons(this,
[
"IS_OS_AIX", "IS_OS_HP_UX", "IS_OS_IRIX", "IS_OS_LINUX", "IS_OS_MAC%", "IS_OS_FREE_BSD",
"IS_OS_OPEN_BSD", "IS_OS_NET_BSD", "IS_OS_SOLARIS", "IS_OS_SUN_OS", "IS_OS_ZOS"
"IS\\_OS\\_AIX", "IS\\_OS\\_HP\\_UX", "IS\\_OS\\_IRIX", "IS\\_OS\\_LINUX", "IS\\_OS\\_MAC%",
"IS\\_OS\\_FREE\\_BSD", "IS\\_OS\\_OPEN\\_BSD", "IS\\_OS\\_NET\\_BSD", "IS\\_OS\\_SOLARIS",
"IS\\_OS\\_SUN\\_OS", "IS\\_OS\\_ZOS"
])
}
}

View File

@@ -2,9 +2,9 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.DataFlow3
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.TaintTracking2
import semmle.code.java.dataflow.TaintTracking3
import semmle.code.java.security.AndroidIntentRedirection
/**
@@ -38,7 +38,7 @@ private class OriginalIntentSanitizer extends IntentRedirectionSanitizer {
* Data flow configuration used to discard incoming Intents
* flowing directly to sinks that start Android components.
*/
private class SameIntentBeingRelaunchedConfiguration extends DataFlow3::Configuration {
private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configuration {
SameIntentBeingRelaunchedConfiguration() { this = "SameIntentBeingRelaunchedConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
@@ -74,7 +74,7 @@ private class IntentWithTaintedComponent extends DataFlow::Node {
/**
* A taint tracking configuration for tainted data flowing to an `Intent`'s component.
*/
private class TaintedIntentComponentConf extends TaintTracking2::Configuration {
private class TaintedIntentComponentConf extends TaintTracking3::Configuration {
TaintedIntentComponentConf() { this = "TaintedIntentComponentConf" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -3,7 +3,6 @@
import java
import semmle.code.java.frameworks.JAXB
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.security.CleartextStorageQuery
import semmle.code.java.security.CleartextStoragePropertiesQuery
@@ -74,7 +73,7 @@ private Expr getInstanceInput(DataFlow::Node instance, RefType t) {
)
}
private class ClassStoreFlowConfig extends DataFlow2::Configuration {
private class ClassStoreFlowConfig extends DataFlow::Configuration {
ClassStoreFlowConfig() { this = "ClassStoreFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ClassStore }

View File

@@ -3,6 +3,7 @@
import java
private import semmle.code.java.dataflow.DataFlow4
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.TaintTracking2
private import semmle.code.java.security.SensitiveActions
/** A sink representing persistent storage that saves data in clear text. */
@@ -39,7 +40,7 @@ abstract class Storable extends Call {
abstract Expr getAStore();
}
private class SensitiveSourceFlowConfig extends TaintTracking::Configuration {
private class SensitiveSourceFlowConfig extends TaintTracking2::Configuration {
SensitiveSourceFlowConfig() { this = "SensitiveSourceFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr }

View File

@@ -11,7 +11,10 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.ExternalProcess
import semmle.code.java.security.CommandArguments
private class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
/**
* A taint-tracking configuration for unvalidated user input that is used to run an external process.
*/
class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
RemoteUserInputToArgumentToExecFlowConfig() {
this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
}

View File

@@ -1,10 +1,19 @@
/** Definitions used by the queries for database query injection. */
/**
* Provides taint tracking and dataflow configurations to be used in Sql injection queries.
*
* Do not import this from a library file, in order to reduce the risk of
* unintentionally bringing a TaintTracking::Configuration into scope in an unrelated
* query.
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.QueryInjection
private class QueryInjectionFlowConfig extends TaintTracking::Configuration {
/**
* A taint-tracking configuration for unvalidated user input that is used in SQL queries.
*/
class QueryInjectionFlowConfig extends TaintTracking::Configuration {
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }

View File

@@ -380,7 +380,7 @@ class DeclaredRepository extends PomElement {
* Gets the url for this repository. If the `url` tag is present, this will
* be the string contents of that tag.
*/
string getUrl() { result = this.getAChild("url").(PomElement).getValue() }
string getRepositoryUrl() { result = this.getAChild("url").(PomElement).getValue() }
}
/**

View File

@@ -1,3 +1,15 @@
## 0.0.13
## 0.0.12
### New Queries
* The query "Insertion of sensitive information into log files" (`java/sensitive-logging`) has been promoted from experimental to the main query pack. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3090).
### Minor Analysis Improvements
* Updated "Local information disclosure in a temporary directory" (`java/local-temp-file-or-directory-information-disclosure`) to remove false-positives when OS is properly used as logical guard.
## 0.0.11
## 0.0.10

View File

@@ -14,7 +14,7 @@
import java
import semmle.code.java.dataflow.FlowSources
import SqlInjectionLib
import semmle.code.java.security.SqlInjectionQuery
import DataFlow::PathGraph
from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink

View File

@@ -14,7 +14,7 @@
import semmle.code.java.Expr
import semmle.code.java.dataflow.FlowSources
import SqlInjectionLib
import semmle.code.java.security.SqlInjectionQuery
import DataFlow::PathGraph
class LocalUserInputToQueryInjectionFlowConfig extends TaintTracking::Configuration {

View File

@@ -14,7 +14,7 @@
import java
import semmle.code.java.security.SqlUnescapedLib
import SqlInjectionLib
import semmle.code.java.security.SqlInjectionQuery
class UncontrolledStringBuilderSource extends DataFlow::ExprNode {
UncontrolledStringBuilderSource() {

View File

@@ -14,10 +14,10 @@ import java
import semmle.code.xml.MavenPom
predicate isBintrayRepositoryUsage(DeclaredRepository repository) {
repository.getUrl().matches("%.bintray.com%")
repository.getRepositoryUrl().matches("%.bintray.com%")
}
from DeclaredRepository repository
where isBintrayRepositoryUsage(repository)
select repository,
"Downloading or uploading artifacts to deprecated repository " + repository.getUrl()
"Downloading or uploading artifacts to deprecated repository " + repository.getRepositoryUrl()

View File

@@ -105,23 +105,21 @@ private class FileCreateTempFileSink extends FileCreationSink {
}
/**
* A guard that holds when the program is definitely running under some version of Windows.
* A sanitizer that holds when the program is definitely running under some version of Windows.
*/
abstract private class WindowsOsBarrierGuard extends DataFlow::BarrierGuard { }
abstract private class WindowsOsSanitizer extends DataFlow::Node { }
private class IsNotUnixBarrierGuard extends WindowsOsBarrierGuard instanceof IsUnixGuard {
override predicate checks(Expr e, boolean branch) {
this.controls(e.getBasicBlock(), branch.booleanNot())
}
private class IsNotUnixSanitizer extends WindowsOsSanitizer {
IsNotUnixSanitizer() { any(IsUnixGuard guard).controls(this.asExpr().getBasicBlock(), false) }
}
private class IsWindowsBarrierGuard extends WindowsOsBarrierGuard instanceof IsWindowsGuard {
override predicate checks(Expr e, boolean branch) { this.controls(e.getBasicBlock(), branch) }
private class IsWindowsSanitizer extends WindowsOsSanitizer {
IsWindowsSanitizer() { any(IsWindowsGuard guard).controls(this.asExpr().getBasicBlock(), true) }
}
private class IsSpecificWindowsBarrierGuard extends WindowsOsBarrierGuard instanceof IsSpecificWindowsVariant {
override predicate checks(Expr e, boolean branch) {
branch = true and this.controls(e.getBasicBlock(), branch)
private class IsSpecificWindowsSanitizer extends WindowsOsSanitizer {
IsSpecificWindowsSanitizer() {
any(IsSpecificWindowsVariant guard).controls(this.asExpr().getBasicBlock(), true)
}
}
@@ -155,10 +153,8 @@ private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Conf
exists(FilesSanitizingCreationMethodAccess sanitisingMethodAccess |
sanitizer.asExpr() = sanitisingMethodAccess.getArgument(0)
)
}
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof WindowsOsBarrierGuard
or
sanitizer instanceof WindowsOsSanitizer
}
}

View File

@@ -58,7 +58,6 @@ private predicate isTaintPropagatingFileTransformation(Expr expSource, Expr expr
* For example, `taintedFile.getCanonicalFile()` is itself tainted.
*/
predicate isAdditionalFileTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
isFileConstructorArgument(node1.asExpr(), node2.asExpr(), _) or
isTaintPropagatingFileTransformation(node1.asExpr(), node2.asExpr())
}

View File

@@ -17,11 +17,11 @@ import java
import semmle.code.xml.MavenPom
predicate isInsecureRepositoryUsage(DeclaredRepository repository) {
repository.getUrl().regexpMatch("(?i)^(http|ftp)://(?!localhost[:/]).*")
repository.getRepositoryUrl().regexpMatch("(?i)^(http|ftp)://(?!localhost[:/]).*")
}
from DeclaredRepository repository
where isInsecureRepositoryUsage(repository)
select repository,
"Downloading or uploading artifacts over insecure protocol (eg. http or ftp) to/from repository " +
repository.getUrl()
repository.getRepositoryUrl()

View File

@@ -1,7 +0,0 @@
---
category: minorAnalysis
---
* Added new guards `IsWindowsGuard`, `IsSpecificWindowsVariant`, `IsUnixGuard`, and `IsSpecificUnixVariant` to detect OS specific guards.
* Added a new predicate `getSystemProperty` that gets all expressions that retrieve system properties from a variety of sources (eg. alternative JDK API's, Google Guava, Apache Commons, Apache IO, etc..).
* Updated "Local information disclosure in a temporary directory" (`java/local-temp-file-or-directory-information-disclosure`) to remove false-positives when OS is properly used as logical guard.

View File

@@ -1,4 +0,0 @@
---
category: newQuery
---
* The query "Insertion of sensitive information into log files" (`java/sensitive-logging`) has been promoted from experimental to the main query pack. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3090).

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The `SwitchCase.getRuleExpression()` predicate now gets expressions for case rules with an expression on the right-hand side of the arrow belonging to both `SwitchStmt` and `SwitchExpr`, and the corresponding `getRuleStatement()` no longer returns an `ExprStmt` in either case. Previously `SwitchStmt` and `SwitchExpr` behaved differently in
this respect.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Fixed "Local information disclosure in a temporary directory" (`java/local-temp-file-or-directory-information-disclosure`) to resolve false-negatives when OS isn't properly used as logical guard.

View File

@@ -0,0 +1,9 @@
## 0.0.12
### New Queries
* The query "Insertion of sensitive information into log files" (`java/sensitive-logging`) has been promoted from experimental to the main query pack. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/3090).
### Minor Analysis Improvements
* Updated "Local information disclosure in a temporary directory" (`java/local-temp-file-or-directory-information-disclosure`) to remove false-positives when OS is properly used as logical guard.

View File

@@ -0,0 +1 @@
## 0.0.13

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.11
lastReleaseVersion: 0.0.13

View File

@@ -1,5 +1,5 @@
name: codeql/java-queries
version: 0.0.12-dev
version: 0.1.0-dev
groups:
- java
- queries

View File

@@ -41,7 +41,7 @@ private class CallableToTest extends Callable {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _) and
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) and
this = interpretElement(namespace, type, subtypes, name, signature, ext) and
this.isPublic() and
getRootType(this.getDeclaringType()).(RefType).isPublic()
@@ -64,7 +64,8 @@ private newtype TTestCase =
string inputSpec, string outputSpec
|
any(TargetSummaryModelCsv tsmc).row(row) and
summaryModel(namespace, type, subtypes, name, signature, ext, inputSpec, outputSpec, kind, row) and
summaryModel(namespace, type, subtypes, name, signature, ext, inputSpec, outputSpec, kind,
false, row) and
callable = interpretElement(namespace, type, subtypes, name, signature, ext) and
Private::External::interpretSpec(inputSpec, input) and
Private::External::interpretSpec(outputSpec, output)

View File

@@ -21,25 +21,25 @@ query string getAParseFailure(string reason) {
any(TargetSummaryModelCsv target).row(result) and
any(SummaryModelCsv model).row(result) and
(
not summaryModel(_, _, _, _, _, _, _, _, _, result) and
not summaryModel(_, _, _, _, _, _, _, _, _, _, result) and
reason = "row could not be parsed"
or
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, result) and
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, result) and
not interpretElement(namespace, type, subtypes, name, signature, ext) instanceof Callable and
reason = "callable could not be resolved"
)
or
exists(string inputSpec |
summaryModel(_, _, _, _, _, _, inputSpec, _, _, result) and
summaryModel(_, _, _, _, _, _, inputSpec, _, _, _, result) and
not Private::External::interpretSpec(inputSpec, _) and
reason = "input spec could not be parsed"
)
or
exists(string outputSpec |
summaryModel(_, _, _, _, _, _, _, outputSpec, _, result) and
summaryModel(_, _, _, _, _, _, _, outputSpec, _, _, result) and
not Private::External::interpretSpec(outputSpec, _) and
reason = "output spec could not be parsed"
)

View File

@@ -44,7 +44,7 @@ private string asSummaryModel(TargetApi api, string input, string output, string
result =
asPartialModel(api) + input + ";" //
+ output + ";" //
+ kind
+ "generated:" + kind
}
/**
@@ -68,7 +68,7 @@ private string asTaintModel(TargetApi api, string input, string output) {
*/
bindingset[input, kind]
private string asSinkModel(TargetApi api, string input, string kind) {
result = asPartialModel(api) + input + ";" + kind
result = asPartialModel(api) + input + ";" + "generated:" + kind
}
/**
@@ -76,7 +76,7 @@ private string asSinkModel(TargetApi api, string input, string kind) {
*/
bindingset[output, kind]
private string asSourceModel(TargetApi api, string output, string kind) {
result = asPartialModel(api) + output + ";" + kind
result = asPartialModel(api) + output + ";" + "generated:" + kind
}
/**

View File

@@ -24,6 +24,16 @@ public class C {
stepQualArg(argOut);
}
void fooGenerated() {
Object arg1 = new Object();
stepArgResGenerated(arg1);
Object arg2 = new Object();
// The summary for the first parameter is ignored, because it is generated and
// because there is hand written summary for the second parameter.
stepArgResGeneratedIgnored(arg1, arg2);
}
Object stepArgRes(Object x) { return null; }
void stepArgArg(Object in, Object out) { }
@@ -33,4 +43,8 @@ public class C {
Object stepQualRes() { return null; }
void stepQualArg(Object out) { }
Object stepArgResGenerated(Object x) { return null; }
Object stepArgResGeneratedIgnored(Object x, Object y) { return null; }
}

View File

@@ -8,3 +8,5 @@ invalidModelRow
| C.java:20:5:20:8 | this | C.java:20:5:20:22 | stepQualRes(...) |
| C.java:21:5:21:17 | this <.method> | C.java:21:5:21:17 | stepQualRes(...) |
| C.java:24:5:24:23 | this <.method> | C.java:24:17:24:22 | argOut [post update] |
| C.java:29:25:29:28 | arg1 | C.java:29:5:29:29 | stepArgResGenerated(...) |
| C.java:34:38:34:41 | arg2 | C.java:34:5:34:42 | stepArgResGeneratedIgnored(...) |

View File

@@ -13,7 +13,10 @@ class SummaryModelTest extends SummaryModelCsv {
"my.qltest;C;false;stepArgArg;(Object,Object);;Argument[0];Argument[1];taint",
"my.qltest;C;false;stepArgQual;(Object);;Argument[0];Argument[-1];taint",
"my.qltest;C;false;stepQualRes;();;Argument[-1];ReturnValue;taint",
"my.qltest;C;false;stepQualArg;(Object);;Argument[-1];Argument[0];taint"
"my.qltest;C;false;stepQualArg;(Object);;Argument[-1];Argument[0];taint",
"my.qltest;C;false;stepArgResGenerated;(Object);;Argument[0];ReturnValue;generated:taint",
"my.qltest;C;false;stepArgResGeneratedIgnored;(Object,Object);;Argument[0];ReturnValue;generated:taint",
"my.qltest;C;false;stepArgResGeneratedIgnored;(Object,Object);;Argument[1];ReturnValue;taint",
]
}
}

View File

@@ -0,0 +1,23 @@
public class TestSwitchExprStmtConsistency {
static int f() { return 0; }
public static void test(int x) {
// Test that getRuleExpression() and getRuleStatement() behave alike for switch expressions and statements using arrow rules.
switch(x) {
case 1 -> f();
case 2 -> f();
default -> f();
}
int result = switch(x) {
case 1 -> f();
case 2 -> f();
default -> f();
};
}
}

View File

@@ -0,0 +1,12 @@
exprs
| TestSwitchExpr.java:9:13:9:41 | case ... | TestSwitchExpr.java:9:43:9:46 | null |
| TestSwitchExpr.java:10:13:10:22 | default | TestSwitchExpr.java:10:24:10:25 | x1 |
| TestSwitchExprStmtConsistency.java:10:7:10:15 | case ... | TestSwitchExprStmtConsistency.java:10:17:10:19 | f(...) |
| TestSwitchExprStmtConsistency.java:11:7:11:15 | case ... | TestSwitchExprStmtConsistency.java:11:17:11:19 | f(...) |
| TestSwitchExprStmtConsistency.java:12:7:12:16 | default | TestSwitchExprStmtConsistency.java:12:18:12:20 | f(...) |
| TestSwitchExprStmtConsistency.java:16:7:16:15 | case ... | TestSwitchExprStmtConsistency.java:16:17:16:19 | f(...) |
| TestSwitchExprStmtConsistency.java:17:7:17:15 | case ... | TestSwitchExprStmtConsistency.java:17:17:17:19 | f(...) |
| TestSwitchExprStmtConsistency.java:18:7:18:16 | default | TestSwitchExprStmtConsistency.java:18:18:18:20 | f(...) |
stmts
| TestSwitchExpr.java:13:13:13:28 | case ... | TestSwitchExpr.java:13:30:13:42 | { ... } |
| TestSwitchExpr.java:14:13:14:22 | default | TestSwitchExpr.java:14:24:14:52 | throw ... |

View File

@@ -0,0 +1,5 @@
import java
query predicate exprs(SwitchCase sc, Expr e) { e = sc.getRuleExpression() }
query predicate stmts(SwitchCase sc, Stmt s) { s = sc.getRuleStatement() }

View File

@@ -1,38 +1,26 @@
edges
| Files.java:10:24:10:69 | new File(...) : File | Files.java:14:37:14:43 | baseDir : File |
| Files.java:10:24:10:69 | new File(...) : File | Files.java:15:17:15:23 | tempDir |
| Files.java:10:33:10:68 | getProperty(...) : String | Files.java:10:24:10:69 | new File(...) : File |
| Files.java:10:33:10:68 | getProperty(...) : String | Files.java:14:37:14:43 | baseDir : File |
| Files.java:10:33:10:68 | getProperty(...) : String | Files.java:15:17:15:23 | tempDir |
| Files.java:14:28:14:64 | new File(...) : File | Files.java:15:17:15:23 | tempDir |
| Files.java:14:37:14:43 | baseDir : File | Files.java:14:28:14:64 | new File(...) : File |
| Test.java:36:24:36:69 | new File(...) : File | Test.java:39:63:39:69 | tempDir |
| Test.java:36:33:36:68 | getProperty(...) : String | Test.java:36:24:36:69 | new File(...) : File |
| Test.java:36:33:36:68 | getProperty(...) : String | Test.java:39:63:39:69 | tempDir |
| Test.java:50:29:50:94 | new File(...) : File | Test.java:53:63:53:74 | tempDirChild |
| Test.java:50:38:50:83 | new File(...) : File | Test.java:50:29:50:94 | new File(...) : File |
| Test.java:50:38:50:83 | new File(...) : File | Test.java:53:63:53:74 | tempDirChild |
| Test.java:50:47:50:82 | getProperty(...) : String | Test.java:50:38:50:83 | new File(...) : File |
| Test.java:50:47:50:82 | getProperty(...) : String | Test.java:53:63:53:74 | tempDirChild |
| Test.java:61:24:61:69 | new File(...) : File | Test.java:64:63:64:69 | tempDir |
| Test.java:61:33:61:68 | getProperty(...) : String | Test.java:61:24:61:69 | new File(...) : File |
| Test.java:61:33:61:68 | getProperty(...) : String | Test.java:64:63:64:69 | tempDir |
| Test.java:75:24:75:69 | new File(...) : File | Test.java:78:63:78:69 | tempDir |
| Test.java:75:33:75:68 | getProperty(...) : String | Test.java:75:24:75:69 | new File(...) : File |
| Test.java:75:33:75:68 | getProperty(...) : String | Test.java:78:63:78:69 | tempDir |
| Test.java:110:29:110:84 | new File(...) : File | Test.java:113:9:113:20 | tempDirChild |
| Test.java:110:38:110:73 | getProperty(...) : String | Test.java:110:29:110:84 | new File(...) : File |
| Test.java:110:38:110:73 | getProperty(...) : String | Test.java:113:9:113:20 | tempDirChild |
| Test.java:134:29:134:84 | new File(...) : File | Test.java:137:9:137:20 | tempDirChild |
| Test.java:134:38:134:73 | getProperty(...) : String | Test.java:134:29:134:84 | new File(...) : File |
| Test.java:134:38:134:73 | getProperty(...) : String | Test.java:137:9:137:20 | tempDirChild |
| Test.java:158:29:158:88 | new File(...) : File | Test.java:159:21:159:32 | tempDirChild : File |
| Test.java:158:38:158:73 | getProperty(...) : String | Test.java:158:29:158:88 | new File(...) : File |
| Test.java:158:38:158:73 | getProperty(...) : String | Test.java:159:21:159:32 | tempDirChild : File |
| Test.java:159:21:159:32 | tempDirChild : File | Test.java:159:21:159:41 | toPath(...) |
| Test.java:187:29:187:88 | new File(...) : File | Test.java:188:21:188:32 | tempDirChild : File |
| Test.java:187:38:187:73 | getProperty(...) : String | Test.java:187:29:187:88 | new File(...) : File |
| Test.java:187:38:187:73 | getProperty(...) : String | Test.java:188:21:188:32 | tempDirChild : File |
| Test.java:188:21:188:32 | tempDirChild : File | Test.java:188:21:188:41 | toPath(...) |
| Test.java:204:29:204:104 | new File(...) : File | Test.java:204:29:204:113 | toPath(...) : Path |
| Test.java:204:29:204:113 | toPath(...) : Path | Test.java:207:33:207:44 | tempDirChild |
@@ -42,28 +30,28 @@ edges
| Test.java:216:38:216:73 | getProperty(...) : String | Test.java:216:29:216:102 | new File(...) : File |
| Test.java:228:29:228:100 | new File(...) : File | Test.java:231:26:231:37 | tempDirChild : File |
| Test.java:228:38:228:73 | getProperty(...) : String | Test.java:228:29:228:100 | new File(...) : File |
| Test.java:228:38:228:73 | getProperty(...) : String | Test.java:231:26:231:37 | tempDirChild : File |
| Test.java:231:26:231:37 | tempDirChild : File | Test.java:231:26:231:46 | toPath(...) |
| Test.java:249:29:249:101 | new File(...) : File | Test.java:252:31:252:42 | tempDirChild : File |
| Test.java:249:38:249:73 | getProperty(...) : String | Test.java:249:29:249:101 | new File(...) : File |
| Test.java:249:38:249:73 | getProperty(...) : String | Test.java:252:31:252:42 | tempDirChild : File |
| Test.java:252:31:252:42 | tempDirChild : File | Test.java:252:31:252:51 | toPath(...) |
| Test.java:260:29:260:109 | new File(...) : File | Test.java:263:33:263:44 | tempDirChild : File |
| Test.java:260:38:260:73 | getProperty(...) : String | Test.java:260:29:260:109 | new File(...) : File |
| Test.java:260:38:260:73 | getProperty(...) : String | Test.java:263:33:263:44 | tempDirChild : File |
| Test.java:263:33:263:44 | tempDirChild : File | Test.java:263:33:263:53 | toPath(...) |
| Test.java:294:29:294:101 | new File(...) : File | Test.java:298:35:298:46 | tempDirChild : File |
| Test.java:294:38:294:73 | getProperty(...) : String | Test.java:294:29:294:101 | new File(...) : File |
| Test.java:294:38:294:73 | getProperty(...) : String | Test.java:298:35:298:46 | tempDirChild : File |
| Test.java:298:35:298:46 | tempDirChild : File | Test.java:298:35:298:55 | toPath(...) |
| Test.java:313:29:313:101 | new File(...) : File | Test.java:316:35:316:46 | tempDirChild : File |
| Test.java:313:38:313:73 | getProperty(...) : String | Test.java:313:29:313:101 | new File(...) : File |
| Test.java:313:38:313:73 | getProperty(...) : String | Test.java:316:35:316:46 | tempDirChild : File |
| Test.java:316:35:316:46 | tempDirChild : File | Test.java:316:35:316:55 | toPath(...) |
| Test.java:322:29:322:101 | new File(...) : File | Test.java:326:35:326:46 | tempDirChild : File |
| Test.java:322:38:322:73 | getProperty(...) : String | Test.java:322:29:322:101 | new File(...) : File |
| Test.java:322:38:322:73 | getProperty(...) : String | Test.java:326:35:326:46 | tempDirChild : File |
| Test.java:326:35:326:46 | tempDirChild : File | Test.java:326:35:326:55 | toPath(...) |
| Test.java:350:29:350:101 | new File(...) : File | Test.java:355:35:355:46 | tempDirChild : File |
| Test.java:350:38:350:73 | getProperty(...) : String | Test.java:350:29:350:101 | new File(...) : File |
| Test.java:355:35:355:46 | tempDirChild : File | Test.java:355:35:355:55 | toPath(...) |
| Test.java:361:29:361:101 | new File(...) : File | Test.java:366:35:366:46 | tempDirChild : File |
| Test.java:361:38:361:73 | getProperty(...) : String | Test.java:361:29:361:101 | new File(...) : File |
| Test.java:366:35:366:46 | tempDirChild : File | Test.java:366:35:366:55 | toPath(...) |
nodes
| Files.java:10:24:10:69 | new File(...) : File | semmle.label | new File(...) : File |
| Files.java:10:33:10:68 | getProperty(...) : String | semmle.label | getProperty(...) : String |
@@ -133,6 +121,14 @@ nodes
| Test.java:322:38:322:73 | getProperty(...) : String | semmle.label | getProperty(...) : String |
| Test.java:326:35:326:46 | tempDirChild : File | semmle.label | tempDirChild : File |
| Test.java:326:35:326:55 | toPath(...) | semmle.label | toPath(...) |
| Test.java:350:29:350:101 | new File(...) : File | semmle.label | new File(...) : File |
| Test.java:350:38:350:73 | getProperty(...) : String | semmle.label | getProperty(...) : String |
| Test.java:355:35:355:46 | tempDirChild : File | semmle.label | tempDirChild : File |
| Test.java:355:35:355:55 | toPath(...) | semmle.label | toPath(...) |
| Test.java:361:29:361:101 | new File(...) : File | semmle.label | new File(...) : File |
| Test.java:361:38:361:73 | getProperty(...) : String | semmle.label | getProperty(...) : String |
| Test.java:366:35:366:46 | tempDirChild : File | semmle.label | tempDirChild : File |
| Test.java:366:35:366:55 | toPath(...) | semmle.label | toPath(...) |
subpaths
#select
| Files.java:10:33:10:68 | getProperty(...) | Files.java:10:33:10:68 | getProperty(...) : String | Files.java:15:17:15:23 | tempDir | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Files.java:10:33:10:68 | getProperty(...) | system temp directory |
@@ -155,3 +151,5 @@ subpaths
| Test.java:294:38:294:73 | getProperty(...) | Test.java:294:38:294:73 | getProperty(...) : String | Test.java:298:35:298:55 | toPath(...) | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Test.java:294:38:294:73 | getProperty(...) | system temp directory |
| Test.java:313:38:313:73 | getProperty(...) | Test.java:313:38:313:73 | getProperty(...) : String | Test.java:316:35:316:55 | toPath(...) | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Test.java:313:38:313:73 | getProperty(...) | system temp directory |
| Test.java:322:38:322:73 | getProperty(...) | Test.java:322:38:322:73 | getProperty(...) : String | Test.java:326:35:326:55 | toPath(...) | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Test.java:322:38:322:73 | getProperty(...) | system temp directory |
| Test.java:350:38:350:73 | getProperty(...) | Test.java:350:38:350:73 | getProperty(...) : String | Test.java:355:35:355:55 | toPath(...) | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Test.java:350:38:350:73 | getProperty(...) | system temp directory |
| Test.java:361:38:361:73 | getProperty(...) | Test.java:361:38:361:73 | getProperty(...) : String | Test.java:366:35:366:55 | toPath(...) | Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users. | Test.java:361:38:361:73 | getProperty(...) | system temp directory |

View File

@@ -344,4 +344,26 @@ public class Test {
Files.createDirectory(tempDirChild.toPath());
}
}
void vulnerableBecauseFileSeparatorCheckElseCase() throws IOException {
// GIVEN:
File tempDirChild = new File(System.getProperty("java.io.tmpdir"), "/child-create-directory");
if (File.separatorChar == '\\') {
Files.createDirectory(tempDirChild.toPath()); // Safe
} else {
Files.createDirectory(tempDirChild.toPath()); // Vulnerable
}
}
void vulnerableBecauseInvertedFileSeperatorCheckElseCase() throws IOException {
// GIVEN:
File tempDirChild = new File(System.getProperty("java.io.tmpdir"), "/child-create-directory");
if (File.separatorChar != '/') {
Files.createDirectory(tempDirChild.toPath()); // Safe
} else {
Files.createDirectory(tempDirChild.toPath()); // Vulnerable
}
}
}

View File

@@ -1,4 +1,4 @@
| p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[-1];create-file |
| p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];create-file |
| p;Sinks;true;readUrl;(URL,Charset);;Argument[0];open-url |
| p;Sources;true;readUrl;(URL);;Argument[0];open-url |
| p;PrivateFlowViaPublicInterface$SPI;true;openStream;();;Argument[-1];generated:create-file |
| p;Sinks;true;copyFileToDirectory;(Path,Path,CopyOption[]);;Argument[1];generated:create-file |
| p;Sinks;true;readUrl;(URL,Charset);;Argument[0];generated:open-url |
| p;Sources;true;readUrl;(URL);;Argument[0];generated:open-url |

View File

@@ -1,5 +1,5 @@
| p;Sources;true;readUrl;(URL);;ReturnValue;remote |
| p;Sources;true;socketStream;();;ReturnValue;remote |
| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0].ArrayElement;remote |
| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1].Element;remote |
| p;Sources;true;wrappedSocketStream;();;ReturnValue;remote |
| p;Sources;true;readUrl;(URL);;ReturnValue;generated:remote |
| p;Sources;true;socketStream;();;ReturnValue;generated:remote |
| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[0].ArrayElement;generated:remote |
| p;Sources;true;sourceToParameter;(InputStream[],List);;Argument[1].Element;generated:remote |
| p;Sources;true;wrappedSocketStream;();;ReturnValue;generated:remote |

View File

@@ -1,46 +1,46 @@
| p;Factory;false;create;(String);;Argument[0];ReturnValue;taint |
| p;Factory;false;create;(String,int);;Argument[0];ReturnValue;taint |
| p;Factory;false;getValue;();;Argument[-1];ReturnValue;taint |
| p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;taint |
| p;FluentAPI;false;returnsThis;(String);;Argument[-1];ReturnValue;value |
| p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[-1];taint |
| p;ImmutablePojo;false;getValue;();;Argument[-1];ReturnValue;taint |
| p;ImmutablePojo;false;or;(String);;Argument[-1];ReturnValue;taint |
| p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;taint |
| p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;taint |
| p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;taint |
| p;InnerHolder;false;append;(String);;Argument[0];Argument[-1];taint |
| p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[-1];taint |
| p;InnerHolder;false;getValue;();;Argument[-1];ReturnValue;taint |
| p;InnerHolder;false;setContext;(String);;Argument[0];Argument[-1];taint |
| p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[-1];taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[-1];taint |
| p;Joiner;false;add;(CharSequence);;Argument[-1];ReturnValue;value |
| p;Joiner;false;merge;(Joiner);;Argument[-1];ReturnValue;value |
| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[-1];ReturnValue;value |
| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[-1];taint |
| p;Joiner;false;toString;();;Argument[-1];ReturnValue;taint |
| p;MultipleImpls$Strat2;true;getValue;();;Argument[-1];ReturnValue;taint |
| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[-1];taint |
| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;taint |
| p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;taint |
| p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint |
| p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;taint |
| p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;taint |
| p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;taint |
| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;taint |
| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;taint |
| p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;taint |
| p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;taint |
| p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];taint |
| p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];taint |
| p;Pojo;false;fillIn;(List);;Argument[-1];Argument[0].Element;taint |
| p;Pojo;false;getBoxedBytes;();;Argument[-1];ReturnValue;taint |
| p;Pojo;false;getBoxedChars;();;Argument[-1];ReturnValue;taint |
| p;Pojo;false;getByteArray;();;Argument[-1];ReturnValue;taint |
| p;Pojo;false;getCharArray;();;Argument[-1];ReturnValue;taint |
| p;Pojo;false;getValue;();;Argument[-1];ReturnValue;taint |
| p;Pojo;false;setValue;(String);;Argument[0];Argument[-1];taint |
| p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;taint |
| p;Factory;false;create;(String);;Argument[0];ReturnValue;generated:taint |
| p;Factory;false;create;(String,int);;Argument[0];ReturnValue;generated:taint |
| p;Factory;false;getValue;();;Argument[-1];ReturnValue;generated:taint |
| p;FinalClass;false;returnsInput;(String);;Argument[0];ReturnValue;generated:taint |
| p;FluentAPI;false;returnsThis;(String);;Argument[-1];ReturnValue;generated:value |
| p;ImmutablePojo;false;ImmutablePojo;(String,int);;Argument[0];Argument[-1];generated:taint |
| p;ImmutablePojo;false;getValue;();;Argument[-1];ReturnValue;generated:taint |
| p;ImmutablePojo;false;or;(String);;Argument[-1];ReturnValue;generated:taint |
| p;ImmutablePojo;false;or;(String);;Argument[0];ReturnValue;generated:taint |
| p;InnerClasses$CaptureMe;true;yesCm;(String);;Argument[0];ReturnValue;generated:taint |
| p;InnerClasses;true;yes;(String);;Argument[0];ReturnValue;generated:taint |
| p;InnerHolder;false;append;(String);;Argument[0];Argument[-1];generated:taint |
| p;InnerHolder;false;explicitSetContext;(String);;Argument[0];Argument[-1];generated:taint |
| p;InnerHolder;false;getValue;();;Argument[-1];ReturnValue;generated:taint |
| p;InnerHolder;false;setContext;(String);;Argument[0];Argument[-1];generated:taint |
| p;Joiner;false;Joiner;(CharSequence);;Argument[0];Argument[-1];generated:taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[0];Argument[-1];generated:taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[1];Argument[-1];generated:taint |
| p;Joiner;false;Joiner;(CharSequence,CharSequence,CharSequence);;Argument[2];Argument[-1];generated:taint |
| p;Joiner;false;add;(CharSequence);;Argument[-1];ReturnValue;generated:value |
| p;Joiner;false;merge;(Joiner);;Argument[-1];ReturnValue;generated:value |
| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[-1];ReturnValue;generated:value |
| p;Joiner;false;setEmptyValue;(CharSequence);;Argument[0];Argument[-1];generated:taint |
| p;Joiner;false;toString;();;Argument[-1];ReturnValue;generated:taint |
| p;MultipleImpls$Strat2;true;getValue;();;Argument[-1];ReturnValue;generated:taint |
| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];Argument[-1];generated:taint |
| p;MultipleImpls$Strategy;true;doSomething;(String);;Argument[0];ReturnValue;generated:taint |
| p;ParamFlow;true;addTo;(String,List);;Argument[0];Argument[1].Element;generated:taint |
| p;ParamFlow;true;returnArrayElement;(String[]);;Argument[0].ArrayElement;ReturnValue;generated:taint |
| p;ParamFlow;true;returnCollectionElement;(List);;Argument[0].Element;ReturnValue;generated:taint |
| p;ParamFlow;true;returnIterableElement;(Iterable);;Argument[0].Element;ReturnValue;generated:taint |
| p;ParamFlow;true;returnIteratorElement;(Iterator);;Argument[0].Element;ReturnValue;generated:taint |
| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[0];ReturnValue;generated:taint |
| p;ParamFlow;true;returnMultipleParameters;(String,String);;Argument[1];ReturnValue;generated:taint |
| p;ParamFlow;true;returnVarArgElement;(String[]);;Argument[0].ArrayElement;ReturnValue;generated:taint |
| p;ParamFlow;true;returnsInput;(String);;Argument[0];ReturnValue;generated:taint |
| p;ParamFlow;true;writeChunked;(byte[],OutputStream);;Argument[0];Argument[1];generated:taint |
| p;ParamFlow;true;writeChunked;(char[],OutputStream);;Argument[0];Argument[1];generated:taint |
| p;Pojo;false;fillIn;(List);;Argument[-1];Argument[0].Element;generated:taint |
| p;Pojo;false;getBoxedBytes;();;Argument[-1];ReturnValue;generated:taint |
| p;Pojo;false;getBoxedChars;();;Argument[-1];ReturnValue;generated:taint |
| p;Pojo;false;getByteArray;();;Argument[-1];ReturnValue;generated:taint |
| p;Pojo;false;getCharArray;();;Argument[-1];ReturnValue;generated:taint |
| p;Pojo;false;getValue;();;Argument[-1];ReturnValue;generated:taint |
| p;Pojo;false;setValue;(String);;Argument[0];Argument[-1];generated:taint |
| p;PrivateFlowViaPublicInterface;true;createAnSPI;(File);;Argument[0];ReturnValue;generated:taint |