Merge branch 'main' into atorralba/android_slice_models

This commit is contained in:
Tony Torralba
2021-10-18 08:41:48 +02:00
committed by GitHub
535 changed files with 22249 additions and 12215 deletions

View File

@@ -52,6 +52,6 @@ predicate hasSmapLocationInfo(
smap(inputFile, isl, outputFile, osl) and
smap(inputFile, iel - 1, outputFile, oel) and
isc = 1 and
iec = 0
iec = 1
)
}

View File

@@ -156,6 +156,11 @@ class TypeObjectOutputStream extends RefType {
TypeObjectOutputStream() { hasQualifiedName("java.io", "ObjectOutputStream") }
}
/** The type `java.io.ObjectInputStream`. */
class TypeObjectInputStream extends RefType {
TypeObjectInputStream() { hasQualifiedName("java.io", "ObjectInputStream") }
}
/** The class `java.nio.file.Paths`. */
class TypePaths extends Class {
TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") }
@@ -275,7 +280,7 @@ class WriteObjectMethod extends Method {
*/
class ReadObjectMethod extends Method {
ReadObjectMethod() {
this.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and
this.getDeclaringType() instanceof TypeObjectInputStream and
(
this.hasName("readObject") or
this.hasName("readObjectOverride") or

View File

@@ -77,8 +77,9 @@ private import FlowSummary
*/
private module Frameworks {
private import internal.ContainerFlow
private import semmle.code.java.frameworks.android.XssSinks
private import semmle.code.java.frameworks.android.Android
private import semmle.code.java.frameworks.android.Intent
private import semmle.code.java.frameworks.android.XssSinks
private import semmle.code.java.frameworks.ApacheHttp
private import semmle.code.java.frameworks.apache.Collections
private import semmle.code.java.frameworks.apache.Lang
@@ -92,6 +93,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.JsonJava
private import semmle.code.java.frameworks.Objects
private import semmle.code.java.frameworks.Optional
private import semmle.code.java.frameworks.Stream
private import semmle.code.java.frameworks.Strings
private import semmle.code.java.frameworks.spring.SpringCache
private import semmle.code.java.frameworks.spring.SpringHttp
@@ -575,7 +577,7 @@ module CsvValidation {
not (part = "Argument" and pred = "sink") and
not parseArg(part, _)
or
specSplit(input, part, _) and
part = specLast(input) and
parseParam(part, _)
) and
msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
}
override predicate relevantFor(DataFlowCallable callable) {
recordDataFlowCallSite(getCall(), callable)
recordDataFlowCallSite(this.getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
@@ -1236,6 +1236,13 @@ class TypedContent extends MkTypedContent {
/** Gets a textual representation of this content. */
string toString() { result = c.toString() }
/**
* Holds if access paths with this `TypedContent` at their head always should
* be tracked at high precision. This disables adaptive access path precision
* for such access paths.
*/
predicate forceHighPrecision() { forceHighPrecision(c) }
}
/**
@@ -1250,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront {
TypedContent getHead() { this = TFrontHead(result) }
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -2139,7 +2139,8 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
tupleLimit < (tails - 1) * nodes
tupleLimit < (tails - 1) * nodes and
not tc.forceHighPrecision()
)
}
@@ -2973,12 +2974,15 @@ private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
* expected to be expensive. Holds with `unfold = true` otherwise.
*/
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
if apa.getHead().forceHighPrecision()
then unfold = true
else
exists(int aps, int nodes, int apLimit, int tupleLimit |
aps = countPotentialAps(apa, config) and
nodes = countNodesUsingAccessPath(apa, config) and
accessPathCostLimits(apLimit, tupleLimit) and
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
)
}
/**

View File

@@ -234,6 +234,19 @@ class DataFlowCall extends TDataFlowCall {
/** Gets the location of this call. */
abstract Location getLocation();
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
/** A source call, that is, a `Call`. */
@@ -308,6 +321,14 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) {
int accessPathLimit() { result = 5 }
/**
* Holds if access paths with `c` at their head always should be tracked at high
* precision. This disables adaptive access path precision for such access paths.
*/
predicate forceHighPrecision(Content c) {
c instanceof ArrayContent or c instanceof CollectionContent
}
/**
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
* modified or its modification cannot be observed, for example if it is a

View File

@@ -870,4 +870,95 @@ module Private {
)
}
}
/**
* Provides query predicates for rendering the generated data flow graph for
* a summarized callable.
*
* Import this module into a `.ql` file of `@kind graph` to render the graph.
* The graph is restricted to callables from `RelevantSummarizedCallable`.
*/
module RenderSummarizedCallable {
/** A summarized callable to include in the graph. */
abstract class RelevantSummarizedCallable extends SummarizedCallable { }
private newtype TNodeOrCall =
MkNode(Node n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
or
n.(ParamNode).isParameterOf(c, _)
)
} or
MkCall(DataFlowCall call) {
call = summaryDataFlowCall(_) and
call.getEnclosingCallable() instanceof RelevantSummarizedCallable
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
string toString() {
result = this.asNode().toString()
or
result = this.asCall().toString()
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
query predicate nodes(NodeOrCall n, string key, string val) {
key = "semmle.label" and val = n.toString()
}
private predicate edgesComponent(NodeOrCall a, NodeOrCall b, string value) {
exists(boolean preservesValue |
Private::Steps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue) and
if preservesValue = true then value = "value" else value = "taint"
)
or
exists(Content c |
Private::Steps::summaryReadStep(a.asNode(), c, b.asNode()) and
value = "read (" + c + ")"
or
Private::Steps::summaryStoreStep(a.asNode(), c, b.asNode()) and
value = "store (" + c + ")"
or
Private::Steps::summaryClearsContent(a.asNode(), c) and
b = a and
value = "clear (" + c + ")"
)
or
summaryPostUpdateNode(b.asNode(), a.asNode()) and
value = "post-update"
or
b.asCall() = summaryDataFlowCall(a.asNode()) and
value = "receiver"
or
exists(int i |
summaryArgumentNode(b.asCall(), a.asNode(), i) and
value = "argument (" + i + ")"
)
}
query predicate edges(NodeOrCall a, NodeOrCall b, string key, string value) {
key = "semmle.label" and
value = strictconcat(string s | edgesComponent(a, b, s) | s, " / ")
}
}
}

View File

@@ -269,7 +269,7 @@ private predicate taintPreservingQualifierToMethod(Method m) {
m.getName() = "toString"
)
or
m.getDeclaringType().hasQualifiedName("java.io", "ObjectInputStream") and
m.getDeclaringType() instanceof TypeObjectInputStream and
m.getName().matches("read%")
or
m instanceof GetterMethod and

View File

@@ -2,10 +2,10 @@
* Provides Java-specific definitions for use in sign analysis.
*/
module Private {
private import java as J
import semmle.code.java.dataflow.RangeUtils as RU
private import semmle.code.java.dataflow.SSA as Ssa
private import semmle.code.java.controlflow.Guards as G
private import java as J
private import Sign
import Impl

View File

@@ -28,7 +28,7 @@ class SsaReadPositionBlock extends SsaReadPosition, TSsaReadPositionBlock {
/** Gets the basic block corresponding to this position. */
BasicBlock getBlock() { this = TSsaReadPositionBlock(result) }
override predicate hasReadOfVar(SsaVariable v) { getBlock() = getAReadBasicBlock(v) }
override predicate hasReadOfVar(SsaVariable v) { this.getBlock() = getAReadBasicBlock(v) }
override string toString() { result = "block" }
}
@@ -49,8 +49,8 @@ class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiIn
/** Holds if `inp` is an input to `phi` along this edge. */
predicate phiInput(SsaPhiNode phi, SsaVariable inp) {
phi.hasInputFromBlock(inp, getOrigBlock()) and
getPhiBlock() = phi.getBasicBlock()
phi.hasInputFromBlock(inp, this.getOrigBlock()) and
this.getPhiBlock() = phi.getBasicBlock()
}
override string toString() { result = "edge" }

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
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) { isSanitizerOut(node) }
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) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) {
isSanitizer(node) or
this.isSanitizer(node) or
defaultTaintSanitizer(node)
}
/** Holds if taint propagation into `node` is prohibited. */
predicate isSanitizerIn(DataFlow::Node node) { none() }
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
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) { isSanitizerOut(node) }
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) { isSanitizerGuard(guard) }
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
this.isSanitizerGuard(guard)
}
/**
* Holds if the additional taint propagation step from `node1` to `node2`
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalTaintStep(node1, node2) or
this.isAdditionalTaintStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
}

View File

@@ -14,5 +14,5 @@ class RemoteCallableMethod extends Method {
private predicate remoteCallableMethod(Method method) {
method.getDeclaringType().getASupertype() instanceof TypeRemote
or
exists(Method meth | remoteCallableMethod(meth) and method.getAnOverride() = meth)
exists(Method meth | remoteCallableMethod(meth) and method.overrides(meth))
}

View File

@@ -0,0 +1,95 @@
/** Definitions related to `java.util.stream`. */
import semmle.code.java.dataflow.ExternalFlow
private class StreamModel extends SummaryModelCsv {
override predicate row(string s) {
s =
[
"java.util.stream;BaseStream;true;iterator;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;BaseStream;true;onClose;(Runnable);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;BaseStream;true;parallel;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;BaseStream;true;sequential;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;BaseStream;true;spliterator;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;BaseStream;true;unordered;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;allMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;anyMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;ReturnValue of Argument[0];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];ReturnValue;value",
"java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0] of Argument[1];Parameter[0..1] of Argument[2];value",
"java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Parameter[0..1] of Argument[2];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;collect;(Supplier,BiConsumer,BiConsumer);;Element of Argument[-1];Parameter[1] of Argument[1];value",
// Missing: collect(Collector<T,A,R> collector)
"java.util.stream;Stream;true;concat;(Stream,Stream);;Element of Argument[0..1];Element of ReturnValue;value",
"java.util.stream;Stream;true;distinct;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;dropWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;filter;(Predicate);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;findAny;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;findFirst;();;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;flatMap;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;flatMap;(Function);;Element of ReturnValue of Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;flatMapToDouble;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;flatMapToInt;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;flatMapToLong;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;forEach;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;forEachOrdered;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;generate;(Supplier);;ReturnValue of Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;Argument[0];Parameter[0] of Argument[1..2];value",
"java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Element of ReturnValue;value",
"java.util.stream;Stream;true;iterate;(Object,Predicate,UnaryOperator);;ReturnValue of Argument[2];Parameter[0] of Argument[1..2];value",
"java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;Argument[0];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Element of ReturnValue;value",
"java.util.stream;Stream;true;iterate;(Object,UnaryOperator);;ReturnValue of Argument[1];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;limit;(long);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;map;(Function);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;map;(Function);;ReturnValue of Argument[0];Element of ReturnValue;value",
// Missing for mapMulti(BiConsumer) (not currently supported):
// Argument[0] of Parameter[1] of Argument[0] -> Element of Parameter[1] of Argument[0]
// Element of Parameter[1] of Argument[0] -> Element of ReturnValue
"java.util.stream;Stream;true;mapMulti;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapMultiToDouble;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapMultiToInt;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapMultiToLong;(BiConsumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapToDouble;(ToDoubleFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapToInt;(ToIntFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;mapToLong;(ToLongFunction);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;max;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value",
"java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;min;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value",
"java.util.stream;Stream;true;noneMatch;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;of;(Object);;Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;of;(Object[]);;ArrayElement of Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;ofNullable;(Object);;Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;peek;(Consumer);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value",
"java.util.stream;Stream;true;reduce;(BinaryOperator);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Parameter[0..1] of Argument[0];value",
"java.util.stream;Stream;true;reduce;(BinaryOperator);;ReturnValue of Argument[0];Element of ReturnValue;value",
"java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Element of Argument[-1];Parameter[0..1] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;Argument[0];ReturnValue;value",
"java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];Parameter[0..1] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BinaryOperator);;ReturnValue of Argument[1];ReturnValue;value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Element of Argument[-1];Parameter[1] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];Parameter[0..1] of Argument[2];value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;Argument[0];ReturnValue;value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0] of Argument[1];value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];Parameter[0..1] of Argument[2];value",
"java.util.stream;Stream;true;reduce;(Object,BiFunction,BinaryOperator);;ReturnValue of Argument[1..2];ReturnValue;value",
"java.util.stream;Stream;true;skip;(long);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;sorted;;;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;sorted;(Comparator);;Element of Argument[-1];Parameter[0..1] of Argument[0];value",
"java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Parameter[0] of Argument[0];value",
"java.util.stream;Stream;true;takeWhile;(Predicate);;Element of Argument[-1];Element of ReturnValue;value",
"java.util.stream;Stream;true;toArray;;;Element of Argument[-1];ArrayElement of ReturnValue;value",
"java.util.stream;Stream;true;toList;();;Element of Argument[-1];Element of ReturnValue;value"
]
}
}

View File

@@ -202,3 +202,44 @@ private class ContentProviderSourceModels extends SourceModelCsv {
]
}
}
/** Interface for classes whose instances can be written to and restored from a Parcel. */
class TypeParcelable extends Interface {
TypeParcelable() { this.hasQualifiedName("android.os", "Parcelable") }
}
/**
* A method that overrides `android.os.Parcelable.Creator.createFromParcel`.
*/
class CreateFromParcelMethod extends Method {
CreateFromParcelMethod() {
this.hasName("createFromParcel") and
this.getEnclosingCallable().getDeclaringType().getASupertype*() instanceof TypeParcelable
}
}
private class ParcelPropagationModels extends SummaryModelCsv {
override predicate row(string s) {
// Parcel readers that return their value
s =
"android.os;Parcel;false;read" +
[
"Array", "ArrayList", "Boolean", "Bundle", "Byte", "Double", "FileDescriptor", "Float",
"HashMap", "Int", "Long", "Parcelable", "ParcelableArray", "PersistableBundle",
"Serializable", "Size", "SizeF", "SparseArray", "SparseBooleanArray", "String",
"StrongBinder", "TypedObject", "Value"
] + ";;;Argument[-1];ReturnValue;taint"
or
// Parcel readers that write to an existing object
s =
"android.os;Parcel;false;read" +
[
"BinderArray", "BinderList", "BooleanArray", "ByteArray", "CharArray", "DoubleArray",
"FloatArray", "IntArray", "List", "LongArray", "Map", "ParcelableList", "StringArray",
"StringList", "TypedArray", "TypedList"
] + ";;;Argument[-1];Argument[0];taint"
or
// One Parcel method that aliases an argument to a return value
s = "android.os;Parcel;false;readParcelableList;;;Argument[0];ReturnValue;value"
}
}

View File

@@ -3,32 +3,53 @@ private import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSteps
import semmle.code.java.dataflow.ExternalFlow
/**
* The class `android.content.Intent`.
*/
class TypeIntent extends Class {
TypeIntent() { hasQualifiedName("android.content", "Intent") }
}
/**
* The class `android.app.Activity`.
*/
class TypeActivity extends Class {
TypeActivity() { hasQualifiedName("android.app", "Activity") }
}
/**
* The class `android.content.Context`.
*/
class TypeContext extends RefType {
TypeContext() { hasQualifiedName("android.content", "Context") }
}
/**
* The class `android.content.BroadcastReceiver`.
*/
class TypeBroadcastReceiver extends Class {
TypeBroadcastReceiver() { hasQualifiedName("android.content", "BroadcastReceiver") }
}
/**
* The method `Activity.getIntent`
*/
class AndroidGetIntentMethod extends Method {
AndroidGetIntentMethod() { hasName("getIntent") and getDeclaringType() instanceof TypeActivity }
}
/**
* The method `BroadcastReceiver.onReceive`.
*/
class AndroidReceiveIntentMethod extends Method {
AndroidReceiveIntentMethod() {
hasName("onReceive") and getDeclaringType() instanceof TypeBroadcastReceiver
}
}
/**
* The method `Context.startActivity` or `startActivities`.
*/
class ContextStartActivityMethod extends Method {
ContextStartActivityMethod() {
(hasName("startActivity") or hasName("startActivities")) and
@@ -44,6 +65,16 @@ private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent,
IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") }
}
/**
* The method `Intent.getParcelableExtra`.
*/
class IntentGetParcelableExtraMethod extends Method {
IntentGetParcelableExtraMethod() {
hasName("getParcelableExtra") and
getDeclaringType() instanceof TypeIntent
}
}
private class IntentBundleFlowSteps extends SummaryModelCsv {
override predicate row(string row) {
row =

View File

@@ -37,7 +37,7 @@ predicate isGigaSpacesEventMethod(Method eventMethod) {
class GigaSpacesSpaceIdGetterMethod extends Method {
GigaSpacesSpaceIdGetterMethod() {
getAnAnnotation().getType().hasQualifiedName("com.gigaspaces.annotation.pojo", "SpaceId") and
getName().prefix(3) = "get"
getName().matches("get%")
}
}
@@ -48,7 +48,7 @@ class GigaSpacesSpaceIdSetterMethod extends Method {
GigaSpacesSpaceIdSetterMethod() {
exists(GigaSpacesSpaceIdGetterMethod getterMethod |
getterMethod.getDeclaringType() = getDeclaringType() and
getName().prefix(3) = "set"
getName().matches("set%")
|
getterMethod.getName().suffix(3) = getName().suffix(3)
)
@@ -62,6 +62,6 @@ class GigaSpacesSpaceIdSetterMethod extends Method {
class GigaSpacesSpaceRoutingMethod extends Method {
GigaSpacesSpaceRoutingMethod() {
getAnAnnotation().getType().hasQualifiedName("com.gigaspaces.annotation.pojo", "SpaceRouting") and
getName().prefix(3) = "get"
getName().matches("get%")
}
}

View File

@@ -0,0 +1,36 @@
/**
* Provides classes for working with the Gson framework.
*/
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.android.Android
import semmle.code.java.frameworks.android.Intent
/** The class `com.google.gson.Gson`. */
class Gson extends RefType {
Gson() { this.hasQualifiedName("com.google.gson", "Gson") }
}
/** The `fromJson` deserialization method. */
class GsonDeserializeMethod extends Method {
GsonDeserializeMethod() {
this.getDeclaringType() instanceof Gson and
this.hasName("fromJson")
}
}
/**
* Holds if `intentNode` is an `Intent` used in the context `(T)intentNode.getParcelableExtra(...)` and
* `parcelNode` is the corresponding parameter of `Parcelable.Creator<T> { public T createFromParcel(Parcel parcelNode) { }`,
* where `T` is a concrete type implementing `Parcelable`.
*/
predicate intentFlowsToParcel(DataFlow::Node intentNode, DataFlow::Node parcelNode) {
exists(MethodAccess getParcelableExtraCall, CreateFromParcelMethod cfpm, Type createdType |
intentNode.asExpr() = getParcelableExtraCall.getQualifier() and
getParcelableExtraCall.getMethod() instanceof IntentGetParcelableExtraMethod and
DataFlow::localExprFlow(getParcelableExtraCall, any(Expr e | e.getType() = createdType)) and
parcelNode.asParameter() = cfpm.getParameter(0) and
cfpm.getReturnType() = createdType
)
}

View File

@@ -24,11 +24,5 @@ predicate jOOQSqlMethod(Method m) {
}
private class SqlSinkCsv extends SinkModelCsv {
override predicate row(string row) {
row =
[
//"package;type;overrides;name;signature;ext;spec;kind"
"org.jooq;PlainSQL;false;;;Annotated;Argument[0];sql"
]
}
override predicate row(string row) { row = "org.jooq;PlainSQL;false;;;Annotated;Argument[0];sql" }
}

View File

@@ -299,10 +299,7 @@ class RuntimeExitOrHaltMethod extends Method {
(this.hasName("exit") or this.hasName("halt")) and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(PrimitiveType).hasName("int") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.lang", "Runtime")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime
}
}
@@ -315,10 +312,7 @@ class RuntimeAddOrRemoveShutdownHookMethod extends Method {
(this.hasName("addShutdownHook") or this.hasName("removeShutdownHook")) and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "Thread") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.lang", "Runtime")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime
}
}
@@ -414,33 +408,29 @@ class ForbiddenSerializationMethod extends Method {
/**
* A method named `enableReplaceObject` declared in
* the class `java.io.ObjectInputStream` or a subclass thereof.
* the class `java.io.ObjectOutputStream` or a subclass thereof.
*/
class EnableReplaceObjectMethod extends Method {
EnableReplaceObjectMethod() {
this.hasName("enableReplaceObject") and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(PrimitiveType).hasName("boolean") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectOutputStream")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof
TypeObjectOutputStream
}
}
/**
* A method named `replaceObject` declared in
* the class `java.io.ObjectInputStream` or a subclass thereof.
* the class `java.io.ObjectOutputStream` or a subclass thereof.
*/
class ReplaceObjectMethod extends Method {
ReplaceObjectMethod() {
this.hasName("replaceObject") and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType() instanceof TypeObject and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectOutputStream")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof
TypeObjectOutputStream
}
}
@@ -453,10 +443,7 @@ class EnableResolveObjectMethod extends Method {
this.hasName("enableResolveObject") and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(PrimitiveType).hasName("boolean") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectInputStream")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream
}
}
@@ -469,10 +456,7 @@ class ResolveObjectMethod extends Method {
this.hasName("resolveObject") and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType() instanceof TypeObject and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectInputStream")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream
}
}
@@ -485,10 +469,7 @@ class ResolveClassMethod extends Method {
this.hasName("resolveClass") and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(RefType).hasQualifiedName("java.io", "ObjectStreamClass") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectInputStream")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream
}
}
@@ -500,16 +481,8 @@ class ResolveProxyClassMethod extends Method {
ResolveProxyClassMethod() {
this.hasName("resolveProxyClass") and
this.getNumberOfParameters() = 1 and
this.getParameter(0)
.getType()
.(Array)
.getComponentType()
.(RefType)
.hasQualifiedName("java.lang", "String") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.io", "ObjectInputStream")
this.getParameter(0).getType().(Array).getComponentType() instanceof TypeString and
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeObjectInputStream
}
}
@@ -598,16 +571,13 @@ class SystemOrRuntimeLoadLibraryMethod extends Method {
SystemOrRuntimeLoadLibraryMethod() {
(this.hasName("load") or this.hasName("loadLibrary")) and
this.getNumberOfParameters() = 1 and
this.getParameter(0).getType().(RefType).hasQualifiedName("java.lang", "String") and
this.getParameter(0).getType() instanceof TypeString and
(
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.lang", "System") or
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.lang", "Runtime")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime
)
}
}
@@ -619,9 +589,6 @@ class SystemOrRuntimeLoadLibraryMethod extends Method {
class RuntimeExecMethod extends Method {
RuntimeExecMethod() {
this.hasName("exec") and
this.getDeclaringType()
.getASupertype*()
.getSourceDeclaration()
.hasQualifiedName("java.lang", "Runtime")
this.getDeclaringType().getASupertype*().getSourceDeclaration() instanceof TypeRuntime
}
}

View File

@@ -280,7 +280,7 @@ private DataFlow::Node getABodyBuilderWithExplicitContentType(Expr contentType)
.hasQualifiedName("org.springframework.http", "ResponseEntity$BodyBuilder")
)
or
DataFlow::localFlow(getABodyBuilderWithExplicitContentType(contentType), result)
DataFlow::localFlowStep(getABodyBuilderWithExplicitContentType(contentType), result)
}
private DataFlow::Node getASanitizedBodyBuilder() {

View File

@@ -37,7 +37,7 @@ class SpringProfileExpr extends string {
* A Spring profile expression that begins with "!", indicating a negated expression.
*/
class NotSpringProfileExpr extends SpringProfileExpr {
NotSpringProfileExpr() { this.prefix(1) = "!" }
NotSpringProfileExpr() { this.matches("!%") }
/**
* Gets the profile described in this profile expression.

View File

@@ -9,9 +9,7 @@ import semmle.code.java.security.XSS
private class DefaultInformationLeakSinkModel extends SinkModelCsv {
override predicate row(string row) {
row =
[
"javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];information-leak"
]
"javax.servlet.http;HttpServletResponse;false;sendError;(int,String);;Argument[1];information-leak"
}
}

View File

@@ -17,12 +17,13 @@ private import semmle.code.java.frameworks.Jackson
private import semmle.code.java.frameworks.Jabsorb
private import semmle.code.java.frameworks.JoddJson
private import semmle.code.java.frameworks.Flexjson
private import semmle.code.java.frameworks.google.Gson
private import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.Reflection
private class ObjectInputStreamReadObjectMethod extends Method {
ObjectInputStreamReadObjectMethod() {
this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.io", "ObjectInputStream") and
this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInputStream and
(this.hasName("readObject") or this.hasName("readUnshared"))
}
}
@@ -207,6 +208,10 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) {
or
m instanceof FlexjsonDeserializeMethod and
sink = ma.getArgument(0)
or
m instanceof GsonDeserializeMethod and
sink = ma.getArgument(0) and
any(UnsafeTypeConfig config).hasFlowToExpr(ma.getArgument(1))
)
}
@@ -249,6 +254,8 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
createJacksonJsonParserStep(pred, succ)
or
createJacksonTreeNodeStep(pred, succ)
or
intentFlowsToParcel(pred, succ)
}
override predicate isSanitizer(DataFlow::Node node) {
@@ -362,9 +369,15 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration {
ma.getMethod() instanceof JabsorbUnmarshallMethod
or
ma.getMethod() instanceof JoddJsonParseMethod
or
ma.getMethod() instanceof GsonDeserializeMethod
) and
// Note `JacksonTypeDescriptorType` includes plain old `java.lang.Class`
arg.getType() instanceof JacksonTypeDescriptorType and
(
arg.getType() instanceof JacksonTypeDescriptorType
or
arg.getType().(RefType).hasQualifiedName("java.lang.reflect", "Type")
) and
arg = sink.asExpr()
)
}
@@ -375,7 +388,8 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration {
*/
override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
resolveClassStep(fromNode, toNode) or
looksLikeResolveClassStep(fromNode, toNode)
looksLikeResolveClassStep(fromNode, toNode) or
intentFlowsToParcel(fromNode, toNode)
}
}

View File

@@ -129,7 +129,7 @@ class Pom extends ProtoPom {
* occurs by considering the properties defined by this project or an ancestor project.
*/
string resolvePlaceholder(string name) {
if name.prefix(8) = "project."
if name.matches("project.%")
then
exists(PomElement p |
p = getProjectProperty() and

View File

@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
}
/** Gets the text value contained in this XML parent. */
string getTextValue() { result = allCharactersString() }
string getTextValue() { result = this.allCharactersString() }
/** Gets a printable representation of this XML parent. */
string toString() { result = this.getName() }
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
XMLFile() { xmlEncoding(this, _) }
/** Gets a printable representation of this XML file. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
*
* Gets the path of this XML file.
*/
deprecated string getPath() { result = getAbsolutePath() }
deprecated string getPath() { result = this.getAbsolutePath() }
/**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
*
* Gets the path of the folder that contains this XML file.
*/
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) }
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
*/
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
/** Holds if this XML element has the given `name`. */
predicate hasName(string name) { name = getName() }
predicate hasName(string name) { name = this.getName() }
/** Gets the name of this XML element. */
override string getName() { xmlElements(this, result, _, _, _) }
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
/** Gets a printable representation of this XML element. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
}
/**