|
|
|
|
@@ -25,7 +25,20 @@ predicate isPrimitiveTypeUsedForBulkData(J::Type t) {
|
|
|
|
|
t.hasName(["byte", "char", "Byte", "Character"])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataFlow> {
|
|
|
|
|
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
|
|
|
|
cu.getPackage().getName().matches("javax.swing%") or
|
|
|
|
|
cu.getPackage().getName().matches("java.awt%")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate relevant(Callable api) {
|
|
|
|
|
api.isPublic() and
|
|
|
|
|
api.getDeclaringType().isPublic() and
|
|
|
|
|
api.fromSource() and
|
|
|
|
|
not isUninterestingForModels(api) and
|
|
|
|
|
not isInfrequentlyUsed(api.getCompilationUnit())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Location, JavaDataFlow> {
|
|
|
|
|
class Type = J::Type;
|
|
|
|
|
|
|
|
|
|
class Parameter = J::Parameter;
|
|
|
|
|
@@ -34,96 +47,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
|
|
|
|
|
|
|
|
|
|
class NodeExtended = DataFlow::Node;
|
|
|
|
|
|
|
|
|
|
Callable getAsExprEnclosingCallable(NodeExtended node) {
|
|
|
|
|
result = node.asExpr().getEnclosingCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Callable getEnclosingCallable(NodeExtended node) { result = node.getEnclosingCallable() }
|
|
|
|
|
|
|
|
|
|
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
|
|
|
|
|
|
|
|
|
|
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
|
|
|
|
|
cu.getPackage().getName().matches("javax.swing%") or
|
|
|
|
|
cu.getPackage().getName().matches("java.awt%")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate relevant(Callable api) {
|
|
|
|
|
api.isPublic() and
|
|
|
|
|
api.getDeclaringType().isPublic() and
|
|
|
|
|
api.fromSource() and
|
|
|
|
|
not isUninterestingForModels(api) and
|
|
|
|
|
not isInfrequentlyUsed(api.getCompilationUnit())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private J::Method getARelevantOverride(J::Method m) {
|
|
|
|
|
result = m.getAnOverride() and
|
|
|
|
|
relevant(result) and
|
|
|
|
|
// Other exclusions for overrides.
|
|
|
|
|
not m instanceof J::ToStringMethod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the super implementation of `m` if it is relevant.
|
|
|
|
|
* If such a super implementations does not exist, returns `m` if it is relevant.
|
|
|
|
|
*/
|
|
|
|
|
private J::Callable liftedImpl(J::Callable m) {
|
|
|
|
|
(
|
|
|
|
|
result = getARelevantOverride(m)
|
|
|
|
|
or
|
|
|
|
|
result = m and relevant(m)
|
|
|
|
|
) and
|
|
|
|
|
not exists(getARelevantOverride(result))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate hasManualSummaryModel(Callable api) {
|
|
|
|
|
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()).asCallable() or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate hasManualSourceModel(Callable api) {
|
|
|
|
|
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate hasManualSinkModel(Callable api) {
|
|
|
|
|
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate isUninterestingForDataFlowModels(Callable api) {
|
|
|
|
|
api.getDeclaringType() instanceof J::Interface and not exists(api.getBody())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() }
|
|
|
|
|
|
|
|
|
|
class SourceOrSinkTargetApi extends Callable {
|
|
|
|
|
SourceOrSinkTargetApi() { relevant(this) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SinkTargetApi extends SourceOrSinkTargetApi {
|
|
|
|
|
SinkTargetApi() { not hasManualSinkModel(this) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SourceTargetApi extends SourceOrSinkTargetApi {
|
|
|
|
|
SourceTargetApi() { not hasManualSourceModel(this) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SummaryTargetApi extends Callable {
|
|
|
|
|
private Callable lift;
|
|
|
|
|
|
|
|
|
|
SummaryTargetApi() {
|
|
|
|
|
lift = liftedImpl(this) and
|
|
|
|
|
not hasManualSummaryModel(lift)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Callable lift() { result = lift }
|
|
|
|
|
|
|
|
|
|
predicate isRelevant() {
|
|
|
|
|
relevant(this) and
|
|
|
|
|
not hasManualSummaryModel(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string isExtensible(Callable c) {
|
|
|
|
|
if c.getDeclaringType().isFinal() then result = "false" else result = "true"
|
|
|
|
|
}
|
|
|
|
|
@@ -204,50 +129,90 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
|
|
|
|
|
node.asExpr().(J::ThisAccess).isOwnInstanceAccess()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate sinkModelSanitizer(DataFlow::Node node) {
|
|
|
|
|
// exclude variable capture jump steps
|
|
|
|
|
exists(Ssa::SsaImplicitInit closure |
|
|
|
|
|
closure.captures(_) and
|
|
|
|
|
node.asExpr() = closure.getAFirstUse()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate apiSource(DataFlow::Node source) {
|
|
|
|
|
(
|
|
|
|
|
source.asExpr().(J::FieldAccess).isOwnFieldAccess() or
|
|
|
|
|
source instanceof DataFlow::ParameterNode
|
|
|
|
|
) and
|
|
|
|
|
exists(J::RefType t |
|
|
|
|
|
t = source.getEnclosingCallable().getDeclaringType().getAnAncestor() and
|
|
|
|
|
not t instanceof J::TypeObject and
|
|
|
|
|
t.isPublic()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() }
|
|
|
|
|
|
|
|
|
|
string getInputArgument(DataFlow::Node source) {
|
|
|
|
|
exists(int pos |
|
|
|
|
|
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
|
|
|
|
|
if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString()
|
|
|
|
|
)
|
|
|
|
|
or
|
|
|
|
|
source.asExpr() instanceof J::FieldAccess and
|
|
|
|
|
result = qualifierString()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bindingset[kind]
|
|
|
|
|
predicate isRelevantSinkKind(string kind) {
|
|
|
|
|
not kind = "log-injection" and
|
|
|
|
|
not kind.matches("regex-use%") and
|
|
|
|
|
not kind = "file-content-store"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bindingset[kind]
|
|
|
|
|
predicate isRelevantSourceKind(string kind) { any() }
|
|
|
|
|
|
|
|
|
|
predicate containerContent = DataFlowPrivate::containerContent/1;
|
|
|
|
|
|
|
|
|
|
string partialModelRow(Callable api, int i) {
|
|
|
|
|
i = 0 and qualifiedName(api, result, _) // package
|
|
|
|
|
or
|
|
|
|
|
i = 1 and qualifiedName(api, _, result) // type
|
|
|
|
|
or
|
|
|
|
|
i = 2 and result = isExtensible(api) // extensible
|
|
|
|
|
or
|
|
|
|
|
i = 3 and result = api.getName() // name
|
|
|
|
|
or
|
|
|
|
|
i = 4 and result = ExternalFlow::paramsString(api) // parameters
|
|
|
|
|
or
|
|
|
|
|
i = 5 and result = "" and exists(api) // ext
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string partialNeutralModelRow(Callable api, int i) {
|
|
|
|
|
i = 0 and qualifiedName(api, result, _) // package
|
|
|
|
|
or
|
|
|
|
|
i = 1 and qualifiedName(api, _, result) // type
|
|
|
|
|
or
|
|
|
|
|
i = 2 and result = api.getName() // name
|
|
|
|
|
or
|
|
|
|
|
i = 3 and result = ExternalFlow::paramsString(api) // parameters
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private import ModelGeneratorCommonInput
|
|
|
|
|
private import MakeModelGeneratorFactory<Location, JavaDataFlow, JavaTaintTracking, ModelGeneratorCommonInput>
|
|
|
|
|
|
|
|
|
|
module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
|
|
|
|
|
Callable getAsExprEnclosingCallable(NodeExtended node) {
|
|
|
|
|
result = node.asExpr().getEnclosingCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
|
|
|
|
|
|
|
|
|
|
private J::Method getARelevantOverride(J::Method m) {
|
|
|
|
|
result = m.getAnOverride() and
|
|
|
|
|
relevant(result) and
|
|
|
|
|
// Other exclusions for overrides.
|
|
|
|
|
not m instanceof J::ToStringMethod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the super implementation of `m` if it is relevant.
|
|
|
|
|
* If such a super implementations does not exist, returns `m` if it is relevant.
|
|
|
|
|
*/
|
|
|
|
|
private J::Callable liftedImpl(J::Callable m) {
|
|
|
|
|
(
|
|
|
|
|
result = getARelevantOverride(m)
|
|
|
|
|
or
|
|
|
|
|
result = m and relevant(m)
|
|
|
|
|
) and
|
|
|
|
|
not exists(getARelevantOverride(result))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate hasManualSummaryModel(Callable api) {
|
|
|
|
|
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()).asCallable() or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SummaryTargetApi extends Callable {
|
|
|
|
|
private Callable lift;
|
|
|
|
|
|
|
|
|
|
SummaryTargetApi() {
|
|
|
|
|
lift = liftedImpl(this) and
|
|
|
|
|
not hasManualSummaryModel(lift)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Callable lift() { result = lift }
|
|
|
|
|
|
|
|
|
|
predicate isRelevant() {
|
|
|
|
|
relevant(this) and
|
|
|
|
|
not hasManualSummaryModel(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate isUninterestingForDataFlowModels(Callable api) {
|
|
|
|
|
api.getDeclaringType() instanceof J::Interface and not exists(api.getBody())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() }
|
|
|
|
|
|
|
|
|
|
predicate isAdditionalContentFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
|
|
|
TaintTracking::defaultAdditionalTaintStep(node1, node2, _) and
|
|
|
|
|
not exists(DataFlow::Content f |
|
|
|
|
|
@@ -287,34 +252,76 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
|
|
|
|
|
or
|
|
|
|
|
c instanceof DataFlowUtil::MapKeyContent and result = "MapKey"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string partialModelRow(Callable api, int i) {
|
|
|
|
|
i = 0 and qualifiedName(api, result, _) // package
|
|
|
|
|
or
|
|
|
|
|
i = 1 and qualifiedName(api, _, result) // type
|
|
|
|
|
or
|
|
|
|
|
i = 2 and result = isExtensible(api) // extensible
|
|
|
|
|
or
|
|
|
|
|
i = 3 and result = api.getName() // name
|
|
|
|
|
or
|
|
|
|
|
i = 4 and result = ExternalFlow::paramsString(api) // parameters
|
|
|
|
|
or
|
|
|
|
|
i = 5 and result = "" and exists(api) // ext
|
|
|
|
|
private module SourceModelGeneratorInput implements SourceModelGeneratorInputSig {
|
|
|
|
|
private predicate hasManualSourceModel(Callable api) {
|
|
|
|
|
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string partialNeutralModelRow(Callable api, int i) {
|
|
|
|
|
i = 0 and qualifiedName(api, result, _) // package
|
|
|
|
|
or
|
|
|
|
|
i = 1 and qualifiedName(api, _, result) // type
|
|
|
|
|
or
|
|
|
|
|
i = 2 and result = api.getName() // name
|
|
|
|
|
or
|
|
|
|
|
i = 3 and result = ExternalFlow::paramsString(api) // parameters
|
|
|
|
|
class SourceTargetApi extends Callable {
|
|
|
|
|
SourceTargetApi() { relevant(this) and not hasManualSourceModel(this) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate irrelevantSourceSinkApi(Callable source, SourceTargetApi api) { none() }
|
|
|
|
|
|
|
|
|
|
bindingset[kind]
|
|
|
|
|
predicate isRelevantSourceKind(string kind) { any() }
|
|
|
|
|
|
|
|
|
|
predicate sourceNode = ExternalFlow::sourceNode/2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
|
|
|
|
|
private predicate hasManualSinkModel(Callable api) {
|
|
|
|
|
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
|
|
|
|
|
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel()).asCallable()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SinkTargetApi extends Callable {
|
|
|
|
|
SinkTargetApi() { relevant(this) and not hasManualSinkModel(this) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate sinkModelSanitizer(DataFlow::Node node) {
|
|
|
|
|
// exclude variable capture jump steps
|
|
|
|
|
exists(Ssa::SsaImplicitInit closure |
|
|
|
|
|
closure.captures(_) and
|
|
|
|
|
node.asExpr() = closure.getAFirstUse()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate apiSource(DataFlow::Node source) {
|
|
|
|
|
(
|
|
|
|
|
source.asExpr().(J::FieldAccess).isOwnFieldAccess() or
|
|
|
|
|
source instanceof DataFlow::ParameterNode
|
|
|
|
|
) and
|
|
|
|
|
exists(J::RefType t |
|
|
|
|
|
t = source.getEnclosingCallable().getDeclaringType().getAnAncestor() and
|
|
|
|
|
not t instanceof J::TypeObject and
|
|
|
|
|
t.isPublic()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string getInputArgument(DataFlow::Node source) {
|
|
|
|
|
exists(int pos |
|
|
|
|
|
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
|
|
|
|
|
if pos >= 0 then result = "Argument[" + pos + "]" else result = qualifierString()
|
|
|
|
|
)
|
|
|
|
|
or
|
|
|
|
|
source.asExpr() instanceof J::FieldAccess and
|
|
|
|
|
result = qualifierString()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bindingset[kind]
|
|
|
|
|
predicate isRelevantSinkKind(string kind) {
|
|
|
|
|
not kind = "log-injection" and
|
|
|
|
|
not kind.matches("regex-use%") and
|
|
|
|
|
not kind = "file-content-store"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate sinkNode = ExternalFlow::sinkNode/2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import MakeModelGenerator<Location, JavaDataFlow, JavaTaintTracking, ModelGeneratorInput>
|
|
|
|
|
import MakeSummaryModelGenerator<SummaryModelGeneratorInput> as SummaryModels
|
|
|
|
|
import MakeSourceModelGenerator<SourceModelGeneratorInput> as SourceModels
|
|
|
|
|
import MakeSinkModelGenerator<SinkModelGeneratorInput> as SinkModels
|
|
|
|
|
|