From f0ffcd0d039be9ec79a111354d36e9b25a948e65 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Fri, 7 Nov 2025 13:56:09 -0800 Subject: [PATCH] DataFlowStack updated --- .../code/csharp/dataflow/DataFlowStack.qll | 21 +-- .../code/java/dataflow/DataFlowStack.qll | 21 +-- .../codeql/dataflowstack/DataFlowStack.qll | 121 +++++++++++------- 3 files changed, 94 insertions(+), 69 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlowStack.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlowStack.qll index 0cbca2e92ff5..d6befff5b6b8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlowStack.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlowStack.qll @@ -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 as DataFlowStackFactory -private module DataFlowStackInput implements - DFS::DataFlowStackSig +module LanguageDataFlowStack = DFS::LanguageDataFlow; + +private module FlowStackInput + implements LanguageDataFlowStack::DataFlowGroup::DataFlowStackSig> { private module Flow = DataFlow::Global; @@ -24,13 +25,13 @@ private module DataFlowStackInput { - import DataFlowStackFactory::FlowStack> +module DataFlowStackMake { + import LanguageDataFlowStack::FlowStack, Config, FlowStackInput> } module BiStackAnalysisMake< - DataFlowStackFactory::DataFlow::ConfigSig ConfigA, - DataFlowStackFactory::DataFlow::ConfigSig ConfigB> -{ - import DataFlowStackFactory::BiStackAnalysis, ConfigB, DataFlowStackInput> -} + DataFlow::ConfigSig ConfigA, + DataFlow::ConfigSig ConfigB +>{ + import LanguageDataFlowStack::BiStackAnalysis, FlowStackInput, ConfigB, DataFlow::Global, FlowStackInput> +} \ No newline at end of file diff --git a/java/ql/lib/semmle/code/java/dataflow/DataFlowStack.qll b/java/ql/lib/semmle/code/java/dataflow/DataFlowStack.qll index 260531af95a6..1beb87ff72b6 100644 --- a/java/ql/lib/semmle/code/java/dataflow/DataFlowStack.qll +++ b/java/ql/lib/semmle/code/java/dataflow/DataFlowStack.qll @@ -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 as DataFlowStackFactory -private module DataFlowStackInput implements - DFS::DataFlowStackSig +module LanguageDataFlowStack = DFS::LanguageDataFlow; + +private module FlowStackInput + implements LanguageDataFlowStack::DataFlowGroup::DataFlowStackSig> { private module Flow = DataFlow::Global; @@ -27,13 +28,13 @@ private module DataFlowStackInput { - import DataFlowStackFactory::FlowStack> +module DataFlowStackMake { + import LanguageDataFlowStack::FlowStack, Config, FlowStackInput> } module BiStackAnalysisMake< - DataFlowStackFactory::DataFlow::ConfigSig ConfigA, - DataFlowStackFactory::DataFlow::ConfigSig ConfigB> -{ - import DataFlowStackFactory::BiStackAnalysis, ConfigB, DataFlowStackInput> -} + DataFlow::ConfigSig ConfigA, + DataFlow::ConfigSig ConfigB +>{ + import LanguageDataFlowStack::BiStackAnalysis, FlowStackInput, ConfigB, DataFlow::Global, FlowStackInput> +} \ No newline at end of file diff --git a/shared/dataflowstack/codeql/dataflowstack/DataFlowStack.qll b/shared/dataflowstack/codeql/dataflowstack/DataFlowStack.qll index 21926e06be7a..2598b70e8961 100644 --- a/shared/dataflowstack/codeql/dataflowstack/DataFlowStack.qll +++ b/shared/dataflowstack/codeql/dataflowstack/DataFlowStack.qll @@ -4,38 +4,57 @@ module; private import codeql.dataflow.DataFlow as DF private import codeql.util.Location -signature module DataFlowStackSig< - LocationSig Location, DF::InputSig Lang, DF::Configs::ConfigSig Config> -{ - Lang::Node getNode(DF::DataFlowMake::Global::PathNode n); +/** + * A Language-initialized grouping of DataFlow types and primitives. + */ +module LanguageDataFlow Lang>{ + module AbstractDF = DF::Configs; + module AbstractDataFlow = DF::DataFlowMake; + module AbstractDataFlowOverlay = DF::DataFlowMakeOverlay; + + /** + * A collection of modules that are scoped to a specific DataFlow config implementation + */ + module DataFlowGroup{ + + module MyConfig = Config; + module DataFlowGlobal = AbstractDataFlow::Global; + module DataFlowOverlayGlobal = AbstractDataFlowOverlay::Global; - predicate isSource(DF::DataFlowMake::Global::PathNode n); + /** + * A Taint tracking implementation, paramaterized over a DataFlow type + */ + signature module DataFlowStackSig{ + + Lang::Node getNode(GlobalFlow::PathNode n); - DF::DataFlowMake::Global::PathNode getASuccessor( - DF::DataFlowMake::Global::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 Lang> { - module DataFlow = DF::DataFlowMake; + Lang::Node getAnArgumentNode(Lang::DataFlowCall call); + } + } module BiStackAnalysis< - DF::Configs::ConfigSig ConfigA, - DataFlowStackSig DataFlowStackA, - DF::Configs::ConfigSig ConfigB, - DataFlowStackSig DataFlowStackB> + AbstractDF::ConfigSig ConfigA, + AbstractDataFlow::GlobalFlowSig GlobalFlowA, + DataFlowGroup::DataFlowStackSig TaintTrackingStackA, + AbstractDF::ConfigSig ConfigB, + AbstractDataFlow::GlobalFlowSig GlobalFlowB, + DataFlowGroup::DataFlowStackSig TaintTrackingStackB> { - module FlowA = DataFlow::Global; + module FlowA = GlobalFlowA; - module FlowStackA = FlowStack; + module FlowStackA = FlowStack; - module FlowB = DataFlow::Global; + module FlowB = GlobalFlowB; - module FlowStackB = FlowStack; + module FlowStackB = FlowStack; /** * Holds if either the Stack associated with `sourceNodeA` is a subset of the stack associated with `sourceNodeB` @@ -53,10 +72,10 @@ module DataFlowStackMake Lang> { flowStackA = FlowStackA::createFlowStack(sourceNodeA, sinkNodeA) and flowStackB = FlowStackB::createFlowStack(sourceNodeB, sinkNodeB) and ( - BiStackAnalysisImpl::flowStackIsSubsetOf(flowStackA, + BiStackAnalysisImpl::flowStackIsSubsetOf(flowStackA, flowStackB) or - BiStackAnalysisImpl::flowStackIsSubsetOf(flowStackB, + BiStackAnalysisImpl::flowStackIsSubsetOf(flowStackB, flowStackA) ) ) @@ -81,10 +100,10 @@ module DataFlowStackMake Lang> { flowStackA = FlowStackA::createFlowStack(sourceNodeA, sinkNodeA) and flowStackB = FlowStackB::createFlowStack(sourceNodeB, sinkNodeB) and ( - BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackA, + BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackA, flowStackB) or - BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackB, + BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackB, flowStackA) ) ) @@ -97,7 +116,7 @@ module DataFlowStackMake 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::flowStackIsSubsetOf(flowStackA, + BiStackAnalysisImpl::flowStackIsSubsetOf(flowStackA, flowStackB) } @@ -109,20 +128,23 @@ module DataFlowStackMake Lang> { predicate flowStackIsConvergingTerminatingSubsetOf( FlowStackA::FlowStack flowStackA, FlowStackB::FlowStack flowStackB ) { - BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackA, + BiStackAnalysisImpl::flowStackIsConvergingTerminatingSubsetOf(flowStackA, flowStackB) } } private module BiStackAnalysisImpl< - DF::Configs::ConfigSig ConfigA, - DataFlowStackSig DataFlowStackA, - DF::Configs::ConfigSig ConfigB, - DataFlowStackSig DataFlowStackB> + AbstractDataFlow::GlobalFlowSig GlobalFlowA, + AbstractDF::ConfigSig ConfigA, + DataFlowGroup::DataFlowStackSig DataFlowStackA, + AbstractDataFlow::GlobalFlowSig GlobalFlowB, + AbstractDF::ConfigSig ConfigB, + DataFlowGroup::DataFlowStackSig DataFlowStackB> { - module FlowStackA = FlowStack; - module FlowStackB = FlowStack; + module FlowStackA = FlowStack; + + module FlowStackB = FlowStack; /** * Holds if stackA is a subset of stackB, @@ -167,29 +189,30 @@ module DataFlowStackMake Lang> { } module FlowStack< - DF::Configs::ConfigSig Config, - DataFlowStackSig DataFlowStack> + AbstractDataFlow::GlobalFlowSig GlobalFlow, + AbstractDF::ConfigSig Config, + DataFlowGroup::DataFlowStackSig TaintTrackingStack> { - private module Flow = DF::DataFlowMake::Global; + 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 { @@ -238,8 +261,8 @@ module DataFlowStackMake 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 ) } @@ -282,7 +305,7 @@ module DataFlowStackMake Lang> { FlowStackFrame getChildStackFrame() { exists(FlowStackFrame transitiveSuccessor | transitiveSuccessor = this.getASuccessor+() and - DataFlowStack::getARuntimeTarget(this.getCall()) = + TaintTrackingStack::getARuntimeTarget(this.getCall()) = transitiveSuccessor.getCall().getEnclosingCallable() and result = transitiveSuccessor ) @@ -315,7 +338,7 @@ module DataFlowStackMake Lang> { private newtype TCallFrameType = TCallFrame(Flow::PathNode node) { exists(Lang::DataFlowCall c | - DataFlowStack::getAnArgumentNode(c) = DataFlowStack::getNode(node) + TaintTrackingStack::getAnArgumentNode(c) = TaintTrackingStack::getNode(node) ) } @@ -351,7 +374,7 @@ module DataFlowStackMake 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 ) } @@ -373,10 +396,10 @@ module DataFlowStackMake 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) @@ -430,4 +453,4 @@ module DataFlowStackMake Lang> { } } } -} +} \ No newline at end of file