mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #17663 from aschackmull/dataflow/speculative-flow
Dataflow: Add support for speculative taint flow.
This commit is contained in:
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -261,13 +261,17 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
predicate isAdditionalFlowStep(
|
||||
Node node1, FlowState state1, Node node2, FlowState state2, string model
|
||||
) {
|
||||
getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and
|
||||
getConfig(state2) = getConfig(state1)
|
||||
getConfig(state2) = getConfig(state1) and
|
||||
model = ""
|
||||
or
|
||||
not singleConfiguration() and
|
||||
getConfig(state1).isAdditionalFlowStep(node1, node2) and
|
||||
state2 = state1
|
||||
state2 = state1 and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate allowImplicitRead(Node node, ContentSet c) {
|
||||
|
||||
@@ -658,3 +658,53 @@ private predicate entrypointFieldStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
) and
|
||||
src.getType().(RefType).getSourceDeclaration() = entrypointType()
|
||||
}
|
||||
|
||||
import SpeculativeTaintFlow
|
||||
|
||||
private module SpeculativeTaintFlow {
|
||||
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
|
||||
private import semmle.code.java.dataflow.internal.DataFlowNodes
|
||||
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as Impl
|
||||
private import semmle.code.java.dispatch.VirtualDispatch
|
||||
private import semmle.code.java.security.Sanitizers
|
||||
|
||||
private predicate hasTarget(Call call) {
|
||||
exists(Impl::Public::SummarizedCallable sc | sc.getACall() = call)
|
||||
or
|
||||
exists(Impl::Public::NeutralSummaryCallable nc | nc.getACall() = call)
|
||||
or
|
||||
call.getCallee().getSourceDeclaration() instanceof ExternalFlow::SinkCallable
|
||||
or
|
||||
exists(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.getACall() = call)
|
||||
or
|
||||
exists(viableCallable(call))
|
||||
or
|
||||
call.getQualifier().getType() instanceof Array
|
||||
or
|
||||
call.getCallee().getSourceDeclaration() instanceof CloneMethod
|
||||
or
|
||||
call.getCallee()
|
||||
.getSourceDeclaration()
|
||||
.getDeclaringType()
|
||||
.getPackage()
|
||||
.hasName("java.util.function")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional step from `src` to `sink` should be considered in
|
||||
* speculative taint flow exploration.
|
||||
*/
|
||||
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
exists(DataFlowCall call, Call srcCall, int argpos |
|
||||
not hasTarget(srcCall) and
|
||||
call.asCall() = srcCall and
|
||||
src.(ArgumentNode).argumentOf(call, argpos) and
|
||||
not src instanceof SimpleTypeSanitizer
|
||||
|
|
||||
argpos != -1 and
|
||||
sink.(DataFlow::PostUpdateNode).getPreUpdateNode() = Public::getInstanceArgument(srcCall)
|
||||
or
|
||||
sink.(OutNode).getCall() = call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user