diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst index cb99bd2a676..73341572940 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst @@ -456,7 +456,7 @@ to wrap it in a new subclass of ``TaintTracking::SharedTaintStep`` like this: If we add this definition to the standard library, it will be picked up by all taint-tracking configurations. Obviously, one has to be careful when adding such new additional taint steps to ensure that they really make sense for `all` configurations. -Analogous to ``TaintTracking::SharedTaintStep``, there is also a class ``DataFlow::AdditionalFlowStep`` that can be extended to add +Analogous to ``TaintTracking::SharedTaintStep``, there is also a class ``DataFlow::SharedFlowStep`` that can be extended to add extra steps to all data-flow configurations, and hence also to all taint-tracking configurations. Exercises diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index baea2b71c84..4739e3f048a 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -72,6 +72,7 @@ private import javascript private import internal.FlowSteps private import internal.AccessPaths private import internal.CallGraphs +private import internal.Unit private import semmle.javascript.internal.CachedStages /** @@ -609,6 +610,54 @@ abstract class AdditionalFlowStep extends DataFlow::Node { } } +/** + * A data flow edge that should be added to all data flow configurations in + * addition to standard data flow edges. + * + * This class is a singleton, and thus subclasses do not need to specify a characteristic predicate. + * + * Note: For performance reasons, all subclasses of this class should be part + * of the standard library. Override `Configuration::isAdditionalFlowStep` + * for analysis-specific flow steps. + */ +class SharedFlowStep extends Unit { + /** + * Holds if `pred` → `succ` should be considered a data flow edge. + */ + predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() } + + /** + * Holds if `pred` → `succ` should be considered a data flow edge + * transforming values with label `predlbl` to have label `succlbl`. + */ + predicate step( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predlbl, + DataFlow::FlowLabel succlbl + ) { + none() + } +} + +/** + * Contributes subclasses of `SharedFlowStep` to `AdditionalFlowStep`. + * + * This is a placeholder until we migrate to the `SharedFlowStep` class and deprecate `AdditionalFlowStep`. + */ +private class SharedStepAsAdditionalFlowStep extends AdditionalFlowStep { + SharedStepAsAdditionalFlowStep() { + any(SharedFlowStep st).step(_, this) or + any(SharedFlowStep st).step(_, this, _, _) + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + any(SharedFlowStep st).step(pred, succ) and succ = this + } + + override predicate step(DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel predlbl, DataFlow::FlowLabel succlbl) { + any(SharedFlowStep st).step(pred, succ, predlbl, succlbl) and succ = this + } +} + /** * A collection of pseudo-properties that are used in multiple files. *