Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions csharp/ql/lib/semmle/code/csharp/dataflow/DataFlowStack.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import csharp
private import codeql.dataflow.DataFlow
private import semmle.code.csharp.dataflow.internal.DataFlowImplSpecific
private import codeql.dataflowstack.DataFlowStack as DFS
private import DFS::DataFlowStackMake<Location, CsharpDataFlow> as DataFlowStackFactory

private module DataFlowStackInput<DataFlowStackFactory::DataFlow::ConfigSig Config> implements
DFS::DataFlowStackSig<Location, CsharpDataFlow, Config>
module LanguageDataFlowStack = DFS::LanguageDataFlow<Location, CsharpDataFlow>;

private module FlowStackInput<DataFlow::ConfigSig Config>
implements LanguageDataFlowStack::DataFlowGroup<Config>::DataFlowStackSig<DataFlow::Global<Config>>
{
private module Flow = DataFlow::Global<Config>;

Expand All @@ -24,13 +25,13 @@ private module DataFlowStackInput<DataFlowStackFactory::DataFlow::ConfigSig Conf
}
}

module DataFlowStackMake<DataFlowStackFactory::DataFlow::ConfigSig Config> {
import DataFlowStackFactory::FlowStack<Config, DataFlowStackInput<Config>>
module DataFlowStackMake<DataFlow::ConfigSig Config> {
import LanguageDataFlowStack::FlowStack<DataFlow::Global<Config>, Config, FlowStackInput<Config>>
}

module BiStackAnalysisMake<
DataFlowStackFactory::DataFlow::ConfigSig ConfigA,
DataFlowStackFactory::DataFlow::ConfigSig ConfigB>
{
import DataFlowStackFactory::BiStackAnalysis<ConfigA, DataFlowStackInput<ConfigA>, ConfigB, DataFlowStackInput<ConfigB>>
}
DataFlow::ConfigSig ConfigA,
DataFlow::ConfigSig ConfigB
>{
import LanguageDataFlowStack::BiStackAnalysis<ConfigA, DataFlow::Global<ConfigA>, FlowStackInput<ConfigA>, ConfigB, DataFlow::Global<ConfigB>, FlowStackInput<ConfigB>>
}
21 changes: 11 additions & 10 deletions java/ql/lib/semmle/code/java/dataflow/DataFlowStack.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.internal.DataFlowImplSpecific
private import codeql.dataflowstack.DataFlowStack as DFS
private import DFS::DataFlowStackMake<Location, JavaDataFlow> as DataFlowStackFactory

private module DataFlowStackInput<DataFlowStackFactory::DataFlow::ConfigSig Config> implements
DFS::DataFlowStackSig<Location, JavaDataFlow, Config>
module LanguageDataFlowStack = DFS::LanguageDataFlow<Location, JavaDataFlow>;

private module FlowStackInput<DataFlow::ConfigSig Config>
implements LanguageDataFlowStack::DataFlowGroup<Config>::DataFlowStackSig<DataFlow::Global<Config>>
{
private module Flow = DataFlow::Global<Config>;

Expand All @@ -27,13 +28,13 @@ private module DataFlowStackInput<DataFlowStackFactory::DataFlow::ConfigSig Conf
}
}

module DataFlowStackMake<DataFlowStackFactory::DataFlow::ConfigSig Config> {
import DataFlowStackFactory::FlowStack<Config, DataFlowStackInput<Config>>
module DataFlowStackMake<DataFlow::ConfigSig Config> {
import LanguageDataFlowStack::FlowStack<DataFlow::Global<Config>, Config, FlowStackInput<Config>>
}

module BiStackAnalysisMake<
DataFlowStackFactory::DataFlow::ConfigSig ConfigA,
DataFlowStackFactory::DataFlow::ConfigSig ConfigB>
{
import DataFlowStackFactory::BiStackAnalysis<ConfigA, DataFlowStackInput<ConfigA>, ConfigB, DataFlowStackInput<ConfigB>>
}
DataFlow::ConfigSig ConfigA,
DataFlow::ConfigSig ConfigB
>{
import LanguageDataFlowStack::BiStackAnalysis<ConfigA, DataFlow::Global<ConfigA>, FlowStackInput<ConfigA>, ConfigB, DataFlow::Global<ConfigB>, FlowStackInput<ConfigB>>
}
121 changes: 72 additions & 49 deletions shared/dataflowstack/codeql/dataflowstack/DataFlowStack.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,57 @@ module;
private import codeql.dataflow.DataFlow as DF
private import codeql.util.Location

signature module DataFlowStackSig<
LocationSig Location, DF::InputSig<Location> Lang, DF::Configs<Location, Lang>::ConfigSig Config>
{
Lang::Node getNode(DF::DataFlowMake<Location, Lang>::Global<Config>::PathNode n);
/**
* A Language-initialized grouping of DataFlow types and primitives.
*/
module LanguageDataFlow<LocationSig Location, DF::InputSig<Location> Lang>{
module AbstractDF = DF::Configs<Location, Lang>;
module AbstractDataFlow = DF::DataFlowMake<Location, Lang>;
module AbstractDataFlowOverlay = DF::DataFlowMakeOverlay<Location, Lang>;

/**
* A collection of modules that are scoped to a specific DataFlow config implementation
*/
module DataFlowGroup<AbstractDF::ConfigSig Config>{

module MyConfig = Config;
module DataFlowGlobal = AbstractDataFlow::Global<Config>;
module DataFlowOverlayGlobal = AbstractDataFlowOverlay::Global<Config>;

predicate isSource(DF::DataFlowMake<Location, Lang>::Global<Config>::PathNode n);
/**
* A Taint tracking implementation, paramaterized over a DataFlow type
*/
signature module DataFlowStackSig<AbstractDataFlow::GlobalFlowSig GlobalFlow>{

Lang::Node getNode(GlobalFlow::PathNode n);

DF::DataFlowMake<Location, Lang>::Global<Config>::PathNode getASuccessor(
DF::DataFlowMake<Location, Lang>::Global<Config>::PathNode n
);
predicate isSource(GlobalFlow::PathNode n);

Lang::DataFlowCallable getARuntimeTarget(Lang::DataFlowCall call);
GlobalFlow::PathNode getASuccessor(
GlobalFlow::PathNode n
);

Lang::Node getAnArgumentNode(Lang::DataFlowCall call);
}
Lang::DataFlowCallable getARuntimeTarget(Lang::DataFlowCall call);

module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
module DataFlow = DF::DataFlowMake<Location, Lang>;
Lang::Node getAnArgumentNode(Lang::DataFlowCall call);
}
}

module BiStackAnalysis<
DF::Configs<Location, Lang>::ConfigSig ConfigA,
DataFlowStackSig<Location, Lang, ConfigA> DataFlowStackA,
DF::Configs<Location, Lang>::ConfigSig ConfigB,
DataFlowStackSig<Location, Lang, ConfigB> DataFlowStackB>
AbstractDF::ConfigSig ConfigA,
AbstractDataFlow::GlobalFlowSig GlobalFlowA,
DataFlowGroup<ConfigA>::DataFlowStackSig<GlobalFlowA> TaintTrackingStackA,
AbstractDF::ConfigSig ConfigB,
AbstractDataFlow::GlobalFlowSig GlobalFlowB,
DataFlowGroup<ConfigB>::DataFlowStackSig<GlobalFlowB> TaintTrackingStackB>
{
module FlowA = DataFlow::Global<ConfigA>;
module FlowA = GlobalFlowA;

module FlowStackA = FlowStack<ConfigA, DataFlowStackA>;
module FlowStackA = FlowStack<GlobalFlowA, ConfigA, TaintTrackingStackA>;

module FlowB = DataFlow::Global<ConfigB>;
module FlowB = GlobalFlowB;

module FlowStackB = FlowStack<ConfigB, DataFlowStackB>;
module FlowStackB = FlowStack<GlobalFlowB, ConfigB, TaintTrackingStackB>;

/**
* Holds if either the Stack associated with `sourceNodeA` is a subset of the stack associated with `sourceNodeB`
Expand All @@ -53,10 +72,10 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
flowStackA = FlowStackA::createFlowStack(sourceNodeA, sinkNodeA) and
flowStackB = FlowStackB::createFlowStack(sourceNodeB, sinkNodeB) and
(
BiStackAnalysisImpl<ConfigA, DataFlowStackA, ConfigB, DataFlowStackB>::flowStackIsSubsetOf(flowStackA,
BiStackAnalysisImpl<GlobalFlowA, ConfigA, TaintTrackingStackA, GlobalFlowB, ConfigB, TaintTrackingStackB>::flowStackIsSubsetOf(flowStackA,
flowStackB)
or
BiStackAnalysisImpl<ConfigB, DataFlowStackB, ConfigA, DataFlowStackA>::flowStackIsSubsetOf(flowStackB,
BiStackAnalysisImpl<GlobalFlowB, ConfigB, TaintTrackingStackB, GlobalFlowA, ConfigA, TaintTrackingStackA>::flowStackIsSubsetOf(flowStackB,
flowStackA)
)
)
Expand All @@ -81,10 +100,10 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
flowStackA = FlowStackA::createFlowStack(sourceNodeA, sinkNodeA) and
flowStackB = FlowStackB::createFlowStack(sourceNodeB, sinkNodeB) and
(
BiStackAnalysisImpl<ConfigA, DataFlowStackA, ConfigB, DataFlowStackB>::flowStackIsConvergingTerminatingSubsetOf(flowStackA,
BiStackAnalysisImpl<GlobalFlowA, ConfigA, TaintTrackingStackA, GlobalFlowB, ConfigB, TaintTrackingStackB>::flowStackIsConvergingTerminatingSubsetOf(flowStackA,
flowStackB)
or
BiStackAnalysisImpl<ConfigB, DataFlowStackB, ConfigA, DataFlowStackA>::flowStackIsConvergingTerminatingSubsetOf(flowStackB,
BiStackAnalysisImpl<GlobalFlowB, ConfigB, TaintTrackingStackB, GlobalFlowA, ConfigA, TaintTrackingStackA>::flowStackIsConvergingTerminatingSubsetOf(flowStackB,
flowStackA)
)
)
Expand All @@ -97,7 +116,7 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
* The top of stackA is in stackB and the bottom of stackA is then some successor further down stackB.
*/
predicate flowStackIsSubsetOf(FlowStackA::FlowStack flowStackA, FlowStackB::FlowStack flowStackB) {
BiStackAnalysisImpl<ConfigA, DataFlowStackA, ConfigB, DataFlowStackB>::flowStackIsSubsetOf(flowStackA,
BiStackAnalysisImpl<GlobalFlowA, ConfigA, TaintTrackingStackA, GlobalFlowB, ConfigB, TaintTrackingStackB>::flowStackIsSubsetOf(flowStackA,
flowStackB)
}

Expand All @@ -109,20 +128,23 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
predicate flowStackIsConvergingTerminatingSubsetOf(
FlowStackA::FlowStack flowStackA, FlowStackB::FlowStack flowStackB
) {
BiStackAnalysisImpl<ConfigA, DataFlowStackA, ConfigB, DataFlowStackB>::flowStackIsConvergingTerminatingSubsetOf(flowStackA,
BiStackAnalysisImpl<GlobalFlowA, ConfigA, TaintTrackingStackA, GlobalFlowB, ConfigB, TaintTrackingStackB>::flowStackIsConvergingTerminatingSubsetOf(flowStackA,
flowStackB)
}
}

private module BiStackAnalysisImpl<
DF::Configs<Location, Lang>::ConfigSig ConfigA,
DataFlowStackSig<Location, Lang, ConfigA> DataFlowStackA,
DF::Configs<Location, Lang>::ConfigSig ConfigB,
DataFlowStackSig<Location, Lang, ConfigB> DataFlowStackB>
AbstractDataFlow::GlobalFlowSig GlobalFlowA,
AbstractDF::ConfigSig ConfigA,
DataFlowGroup<ConfigA>::DataFlowStackSig<GlobalFlowA> DataFlowStackA,
AbstractDataFlow::GlobalFlowSig GlobalFlowB,
AbstractDF::ConfigSig ConfigB,
DataFlowGroup<ConfigB>::DataFlowStackSig<GlobalFlowB> DataFlowStackB>
{
module FlowStackA = FlowStack<ConfigA, DataFlowStackA>;

module FlowStackB = FlowStack<ConfigB, DataFlowStackB>;
module FlowStackA = FlowStack<GlobalFlowA, ConfigA, DataFlowStackA>;

module FlowStackB = FlowStack<GlobalFlowB, ConfigB, DataFlowStackB>;

/**
* Holds if stackA is a subset of stackB,
Expand Down Expand Up @@ -167,29 +189,30 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
}

module FlowStack<
DF::Configs<Location, Lang>::ConfigSig Config,
DataFlowStackSig<Location, Lang, Config> DataFlowStack>
AbstractDataFlow::GlobalFlowSig GlobalFlow,
AbstractDF::ConfigSig Config,
DataFlowGroup<Config>::DataFlowStackSig<GlobalFlow> TaintTrackingStack>
{
private module Flow = DF::DataFlowMake<Location, Lang>::Global<Config>;
private module Flow = GlobalFlow;

/**
* Determines whether or not the given PathNode is a source
* TODO: Refactor to Flow::PathNode signature
*/
predicate isSource(Flow::PathNode node) { DataFlowStack::isSource(node) }
predicate isSource(Flow::PathNode node) { TaintTrackingStack::isSource(node) }

/**
* Determines whether or not the given PathNode is a sink
* TODO: Refactor to Flow::PathNode signature
*/
predicate isSink(Flow::PathNode node) { not exists(DataFlowStack::getASuccessor(node)) }
predicate isSink(Flow::PathNode node) { not exists(TaintTrackingStack::getASuccessor(node)) }

/** A FlowStack encapsulates flows between a source and a sink, and all the pathways inbetween (possibly multiple) */
private newtype FlowStackType =
TFlowStack(Flow::PathNode source, Flow::PathNode sink) {
DataFlowStack::isSource(source) and
not exists(DataFlowStack::getASuccessor(sink)) and
DataFlowStack::getASuccessor*(source) = sink
TaintTrackingStack::isSource(source) and
not exists(TaintTrackingStack::getASuccessor(sink)) and
TaintTrackingStack::getASuccessor*(source) = sink
}

class FlowStack extends FlowStackType, TFlowStack {
Expand Down Expand Up @@ -238,8 +261,8 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
TFlowStackFrame(FlowStack flowStack, CallFrame frame) {
exists(Flow::PathNode source, Flow::PathNode sink |
flowStack = TFlowStack(source, sink) and
frame.getPathNode() = DataFlowStack::getASuccessor*(source) and
DataFlowStack::getASuccessor*(frame.getPathNode()) = sink
frame.getPathNode() = TaintTrackingStack::getASuccessor*(source) and
TaintTrackingStack::getASuccessor*(frame.getPathNode()) = sink
)
}

Expand Down Expand Up @@ -282,7 +305,7 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
FlowStackFrame getChildStackFrame() {
exists(FlowStackFrame transitiveSuccessor |
transitiveSuccessor = this.getASuccessor+() and
DataFlowStack::getARuntimeTarget(this.getCall()) =
TaintTrackingStack::getARuntimeTarget(this.getCall()) =
transitiveSuccessor.getCall().getEnclosingCallable() and
result = transitiveSuccessor
)
Expand Down Expand Up @@ -315,7 +338,7 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
private newtype TCallFrameType =
TCallFrame(Flow::PathNode node) {
exists(Lang::DataFlowCall c |
DataFlowStack::getAnArgumentNode(c) = DataFlowStack::getNode(node)
TaintTrackingStack::getAnArgumentNode(c) = TaintTrackingStack::getNode(node)
)
}

Expand Down Expand Up @@ -351,7 +374,7 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
Lang::DataFlowCall getCall() {
exists(Lang::DataFlowCall call, Flow::PathNode node |
this = TCallFrame(node) and
DataFlowStack::getAnArgumentNode(call) = DataFlowStack::getNode(node) and
TaintTrackingStack::getAnArgumentNode(call) = TaintTrackingStack::getNode(node) and
result = call
)
}
Expand All @@ -373,10 +396,10 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
*/
private Flow::PathNode getSuccessorCall(Flow::PathNode n) {
exists(Flow::PathNode succ |
succ = DataFlowStack::getASuccessor(n) and
succ = TaintTrackingStack::getASuccessor(n) and
if
exists(Lang::DataFlowCall c |
DataFlowStack::getAnArgumentNode(c) = DataFlowStack::getNode(succ)
TaintTrackingStack::getAnArgumentNode(c) = TaintTrackingStack::getNode(succ)
)
then result = succ
else result = getSuccessorCall(succ)
Expand Down Expand Up @@ -430,4 +453,4 @@ module DataFlowStackMake<LocationSig Location, DF::InputSig<Location> Lang> {
}
}
}
}
}