Merge pull request #21051 from hvitved/shared/flow-summary-provenance-filtering

Shared: Provenance-based filtering of flow summaries
This commit is contained in:
Tom Hvitved
2026-01-26 17:24:34 +01:00
committed by GitHub
142 changed files with 15884 additions and 21193 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The predicate `SummarizedCallable.propagatesFlow` has been extended with the columns `Provenance p` and `boolean isExact`, and as a consequence the predicates `SummarizedCallable.hasProvenance` and `SummarizedCallable.hasExactModel` have been removed.

View File

@@ -8,78 +8,94 @@ private import semmle.javascript.dataflow.internal.FlowSummaryPrivate
private import semmle.javascript.dataflow.internal.sharedlib.DataFlowImplCommon as DataFlowImplCommon
private import semmle.javascript.dataflow.internal.DataFlowPrivate
/**
* A model for a function that can propagate data flow.
*
* This class makes it possible to model flow through functions, using the same mechanism as
* `summaryModel` as described in the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript).
*
* Extend this class to define summary models directly in CodeQL.
* Data extensions and `summaryModel` are usually preferred; but there are a few cases where direct use of this class may be needed:
*
* - The relevant call sites cannot be matched by the access path syntax, and require the full power of CodeQL.
* For example, complex overloading patterns might require more local reasoning at the call site.
* - The input/output behavior cannot be described statically in the access path syntax, but the relevant access paths
* can be generated dynamically in CodeQL, based on the usages found in the codebase.
*
* Subclasses should bind `this` to a unique identifier for the function being modeled. There is no special
* interpreation of the `this` value, it should just not clash with the `this`-value used by other classes.
*
* For example, this models flow through calls such as `require("my-library").myFunction()`:
* ```codeql
* class MyFunction extends SummarizedCallable {
* MyFunction() { this = "MyFunction" }
*
* override predicate propagatesFlow(string input, string output, boolean preservesValues) {
* input = "Argument[0]" and
* output = "ReturnValue" and
* preservesValue = false
* }
*
* override DataFlow::InvokeNode getACall() {
* result = API::moduleImport("my-library").getMember("myFunction").getACall()
* }
* }
* ```
* This would be equivalent to the following model written as a data extension:
* ```yaml
* extensions:
* - addsTo:
* pack: codeql/javascript-all
* extensible: summaryModel
* data:
* - ["my-library", "Member[myFunction]", "Argument[0]", "ReturnValue", "taint"]
* ```
*/
abstract class SummarizedCallable extends LibraryCallable, Impl::Public::SummarizedCallable {
bindingset[this]
SummarizedCallable() { any() }
class Provenance = Impl::Public::Provenance;
/** Provides the `Range` class used to define the extent of `SummarizedCallable`. */
module SummarizedCallable {
/**
* Holds if data may flow from `input` to `output` through this callable.
* A model for a function that can propagate data flow.
*
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
* This class makes it possible to model flow through functions, using the same mechanism as
* `summaryModel` as described in the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript).
*
* See the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript) for
* the syntax of the `input` and `output` parameters.
* Extend this class to define summary models directly in CodeQL.
* Data extensions and `summaryModel` are usually preferred; but there are a few cases where direct use of this class may be needed:
*
* - The relevant call sites cannot be matched by the access path syntax, and require the full power of CodeQL.
* For example, complex overloading patterns might require more local reasoning at the call site.
* - The input/output behavior cannot be described statically in the access path syntax, but the relevant access paths
* can be generated dynamically in CodeQL, based on the usages found in the codebase.
*
* Subclasses should bind `this` to a unique identifier for the function being modeled. There is no special
* interpreation of the `this` value, it should just not clash with the `this`-value used by other classes.
*
* For example, this models flow through calls such as `require("my-library").myFunction()`:
* ```codeql
* class MyFunction extends SummarizedCallable::Range {
* MyFunction() { this = "MyFunction" }
*
* override predicate propagatesFlow(string input, string output, boolean preservesValues) {
* input = "Argument[0]" and
* output = "ReturnValue" and
* preservesValue = false
* }
*
* override DataFlow::InvokeNode getACall() {
* result = API::moduleImport("my-library").getMember("myFunction").getACall()
* }
* }
* ```
* This would be equivalent to the following model written as a data extension:
* ```yaml
* extensions:
* - addsTo:
* pack: codeql/javascript-all
* extensible: summaryModel
* data:
* - ["my-library", "Member[myFunction]", "Argument[0]", "ReturnValue", "taint"]
* ```
*/
pragma[nomagic]
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
abstract class Range extends LibraryCallable, Impl::Public::SummarizedCallable {
bindingset[this]
Range() { any() }
override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
) {
this.propagatesFlow(input, output, preservesValue) and model = this
}
/**
* Holds if data may flow from `input` to `output` through this callable.
*
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
*
* See the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript) for
* the syntax of the `input` and `output` parameters.
*/
pragma[nomagic]
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
/**
* Gets the synthesized parameter that results from an input specification
* that starts with `Argument[s]` for this library callable.
*/
DataFlow::ParameterNode getParameter(string s) {
exists(ParameterPosition pos |
DataFlowImplCommon::parameterNode(result, MkLibraryCallable(this), pos) and
s = encodeParameterPosition(pos)
)
override predicate propagatesFlow(
string input, string output, boolean preservesValue, Provenance provenance, boolean isExact,
string model
) {
this.propagatesFlow(input, output, preservesValue) and
provenance = "manual" and
model = this and
isExact = true
}
/**
* Gets the synthesized parameter that results from an input specification
* that starts with `Argument[s]` for this library callable.
*/
DataFlow::ParameterNode getParameter(string s) {
exists(ParameterPosition pos |
DataFlowImplCommon::parameterNode(result, MkLibraryCallable(this), pos) and
s = encodeParameterPosition(pos)
)
}
}
}
final private class SummarizedCallableFinal = SummarizedCallable::Range;
/** A model for a function that can propagate data flow. */
final class SummarizedCallable extends SummarizedCallableFinal,
Impl::Public::RelevantSummarizedCallable
{ }

View File

@@ -28,6 +28,9 @@ module JSFlowSummary implements FlowSummaryImpl::InputSig<Location, JSDataFlow>
private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate
import FlowSummaryPrivate
overlay[local]
predicate callableFromSource(SummarizedCallableBase c) { none() }
// Explicitly implement signature members that have a default
predicate callbackSelfParameterPosition = FlowSummaryPrivate::callbackSelfParameterPosition/0;

View File

@@ -69,7 +69,7 @@ private module SummaryFlowConfig implements Input {
predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
) {
super.propagatesFlow(input, output, preservesValue, _)
super.propagatesFlow(input, output, preservesValue, _, _, _)
}
string toString() { result = super.toString() }

View File

@@ -173,7 +173,7 @@ module AsyncPackage {
}
overlay[local?]
private class IterationCallFlowSummary extends DataFlow::SummarizedCallable {
private class IterationCallFlowSummary extends DataFlow::SummarizedCallable::Range {
private int callbackArgIndex;
IterationCallFlowSummary() {
@@ -221,7 +221,7 @@ module AsyncPackage {
* For example: `data -> result` in `async.sortBy(data, orderingFn, (err, result) => {})`.
*/
overlay[local?]
private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable {
private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable::Range {
IterationPreserveTaintStepFlowSummary() { this = "async.sortBy" }
override DataFlow::InvokeNode getACallSimple() {

View File

@@ -186,7 +186,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashEach extends DataFlow::SummarizedCallable {
private class LodashEach extends DataFlow::SummarizedCallable::Range {
LodashEach() { this = "_.each-like" }
overlay[global]
@@ -202,7 +202,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashMap extends DataFlow::SummarizedCallable {
private class LodashMap extends DataFlow::SummarizedCallable::Range {
LodashMap() { this = "_.map" }
overlay[global]
@@ -221,7 +221,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashFlatMap extends DataFlow::SummarizedCallable {
private class LodashFlatMap extends DataFlow::SummarizedCallable::Range {
LodashFlatMap() { this = "_.flatMap" }
overlay[global]
@@ -243,7 +243,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashFlatMapDeep extends DataFlow::SummarizedCallable {
private class LodashFlatMapDeep extends DataFlow::SummarizedCallable::Range {
LodashFlatMapDeep() { this = "_.flatMapDeep" }
overlay[global]
@@ -267,7 +267,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashReduce extends DataFlow::SummarizedCallable {
private class LodashReduce extends DataFlow::SummarizedCallable::Range {
LodashReduce() { this = "_.reduce-like" }
overlay[global]
@@ -286,7 +286,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LoashSortBy extends DataFlow::SummarizedCallable {
private class LoashSortBy extends DataFlow::SummarizedCallable::Range {
LoashSortBy() { this = "_.sortBy-like" }
overlay[global]
@@ -304,7 +304,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashMinMaxBy extends DataFlow::SummarizedCallable {
private class LodashMinMaxBy extends DataFlow::SummarizedCallable::Range {
LodashMinMaxBy() { this = "_.minBy / _.maxBy" }
overlay[global]
@@ -318,7 +318,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashPartition extends DataFlow::SummarizedCallable {
private class LodashPartition extends DataFlow::SummarizedCallable::Range {
LodashPartition() { this = "_.partition" }
overlay[global]
@@ -332,7 +332,7 @@ module LodashUnderscore {
}
overlay[local?]
private class UnderscoreMapObject extends DataFlow::SummarizedCallable {
private class UnderscoreMapObject extends DataFlow::SummarizedCallable::Range {
UnderscoreMapObject() { this = "_.mapObject" }
overlay[global]
@@ -353,7 +353,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashTap extends DataFlow::SummarizedCallable {
private class LodashTap extends DataFlow::SummarizedCallable::Range {
LodashTap() { this = "_.tap" }
overlay[global]
@@ -367,7 +367,7 @@ module LodashUnderscore {
}
overlay[local?]
private class LodashGroupBy extends DataFlow::SummarizedCallable {
private class LodashGroupBy extends DataFlow::SummarizedCallable::Range {
LodashGroupBy() { this = "_.groupBy" }
override DataFlow::CallNode getACall() { result = member("groupBy").getACall() }

View File

@@ -423,7 +423,7 @@ private module ClosureLibraryUri {
}
overlay[local?]
private class QueryStringStringification extends DataFlow::SummarizedCallable {
private class QueryStringStringification extends DataFlow::SummarizedCallable::Range {
QueryStringStringification() { this = "query-string stringification" }
overlay[global]

View File

@@ -49,7 +49,7 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang
}
overlay[local?]
private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable {
private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable::Range {
string type;
string path;
@@ -62,9 +62,14 @@ private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable {
override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) }
override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
string input, string output, boolean preservesValue, DataFlow::Provenance provenance,
boolean isExact, string model
) {
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) |
exists(string kind |
ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) and
provenance = "manual" and
isExact = true
|
kind = "value" and
preservesValue = true
or

View File

@@ -29,7 +29,7 @@ private import semmle.javascript.dataflow.FlowSummary
private import Arrays
private import FlowSummaryUtil
class At extends SummarizedCallable {
class At extends SummarizedCallable::Range {
At() { this = "Array#at / String#at" }
override InstanceCall getACallSimple() { result.getMethodName() = "at" }
@@ -43,7 +43,7 @@ class At extends SummarizedCallable {
}
}
class Concat extends SummarizedCallable {
class Concat extends SummarizedCallable::Range {
Concat() { this = "Array#concat / String#concat / Buffer.concat" }
override InstanceCall getACallSimple() { result.getMethodName() = "concat" }
@@ -62,7 +62,7 @@ class Concat extends SummarizedCallable {
}
}
class Slice extends SummarizedCallable {
class Slice extends SummarizedCallable::Range {
Slice() { this = "Array#slice / String#slice" }
override InstanceCall getACallSimple() { result.getMethodName() = "slice" }
@@ -78,7 +78,7 @@ class Slice extends SummarizedCallable {
}
}
class Entries extends SummarizedCallable {
class Entries extends SummarizedCallable::Range {
Entries() { this = "Array#entries / Map#entries / Set#entries" }
override InstanceCall getACall() {
@@ -98,7 +98,7 @@ class Entries extends SummarizedCallable {
}
}
class ForEach extends SummarizedCallable {
class ForEach extends SummarizedCallable::Range {
ForEach() { this = "Array#forEach / Map#forEach / Set#forEach" }
override InstanceCall getACallSimple() { result.getMethodName() = "forEach" }
@@ -126,7 +126,7 @@ class ForEach extends SummarizedCallable {
}
}
class Keys extends SummarizedCallable {
class Keys extends SummarizedCallable::Range {
Keys() { this = "Array#keys / Map#keys / Set#keys" }
override InstanceCall getACallSimple() {
@@ -141,7 +141,7 @@ class Keys extends SummarizedCallable {
}
}
class Values extends SummarizedCallable {
class Values extends SummarizedCallable::Range {
Values() { this = "Array#values / Map#values / Set#values" }
override InstanceCall getACallSimple() {
@@ -156,7 +156,7 @@ class Values extends SummarizedCallable {
}
}
class ToString extends SummarizedCallable {
class ToString extends SummarizedCallable::Range {
ToString() { this = "Object#toString / Array#toString" }
override InstanceCall getACallSimple() {

View File

@@ -94,7 +94,7 @@ class DynamicArrayStoreStep extends DataFlow::AdditionalFlowStep {
}
}
class ArrayConstructorSummary extends SummarizedCallable {
class ArrayConstructorSummary extends SummarizedCallable::Range {
ArrayConstructorSummary() { this = "Array constructor" }
override DataFlow::InvokeNode getACallSimple() {
@@ -118,7 +118,7 @@ class ArrayConstructorSummary extends SummarizedCallable {
*
* Calls without separators are modeled in `StringConcatenation.qll`.
*/
class Join extends SummarizedCallable {
class Join extends SummarizedCallable::Range {
Join() { this = "Array#join" }
override InstanceCall getACallSimple() {
@@ -133,7 +133,7 @@ class Join extends SummarizedCallable {
}
}
class CopyWithin extends SummarizedCallable {
class CopyWithin extends SummarizedCallable::Range {
CopyWithin() { this = "Array#copyWithin" }
override InstanceCall getACallSimple() { result.getMethodName() = "copyWithin" }
@@ -150,7 +150,7 @@ class CopyWithin extends SummarizedCallable {
}
}
class FlowIntoCallback extends SummarizedCallable {
class FlowIntoCallback extends SummarizedCallable::Range {
FlowIntoCallback() { this = "Array method with flow into callback" }
override InstanceCall getACallSimple() {
@@ -169,7 +169,7 @@ class FlowIntoCallback extends SummarizedCallable {
}
}
class Filter extends SummarizedCallable {
class Filter extends SummarizedCallable::Range {
Filter() { this = "Array#filter" }
override InstanceCall getACallSimple() { result.getMethodName() = "filter" }
@@ -196,7 +196,7 @@ class Filter extends SummarizedCallable {
}
}
class Fill extends SummarizedCallable {
class Fill extends SummarizedCallable::Range {
Fill() { this = "Array#fill" } // TODO: clear contents if no interval is given
override InstanceCall getACallSimple() { result.getMethodName() = "fill" }
@@ -208,7 +208,7 @@ class Fill extends SummarizedCallable {
}
}
class FindLike extends SummarizedCallable {
class FindLike extends SummarizedCallable::Range {
FindLike() { this = "Array#find / Array#findLast" }
override InstanceCall getACallSimple() { result.getMethodName() = ["find", "findLast"] }
@@ -225,7 +225,7 @@ class FindLike extends SummarizedCallable {
}
}
class FindLibrary extends SummarizedCallable {
class FindLibrary extends SummarizedCallable::Range {
FindLibrary() { this = "'array.prototype.find' / 'array-find'" }
override DataFlow::CallNode getACallSimple() {
@@ -244,7 +244,7 @@ class FindLibrary extends SummarizedCallable {
}
}
class Flat extends SummarizedCallable {
class Flat extends SummarizedCallable::Range {
private int depth;
Flat() { this = "Array#flat(" + depth + ")" and depth in [1 .. 3] }
@@ -275,7 +275,7 @@ class Flat extends SummarizedCallable {
}
}
class FlatMap extends SummarizedCallable {
class FlatMap extends SummarizedCallable::Range {
FlatMap() { this = "Array#flatMap" }
override InstanceCall getACallSimple() { result.getMethodName() = "flatMap" }
@@ -305,7 +305,7 @@ private DataFlow::CallNode arrayFromCall() {
result = DataFlow::moduleImport("array-from").getACall()
}
class From1Arg extends SummarizedCallable {
class From1Arg extends SummarizedCallable::Range {
From1Arg() { this = "Array.from(arg)" }
override DataFlow::CallNode getACallSimple() {
@@ -338,7 +338,7 @@ class From1Arg extends SummarizedCallable {
}
}
class FromManyArg extends SummarizedCallable {
class FromManyArg extends SummarizedCallable::Range {
FromManyArg() { this = "Array.from(arg, callback, [thisArg])" }
override DataFlow::CallNode getACallSimple() {
@@ -370,7 +370,7 @@ class FromManyArg extends SummarizedCallable {
}
}
class Map extends SummarizedCallable {
class Map extends SummarizedCallable::Range {
Map() { this = "Array#map" }
override InstanceCall getACallSimple() {
@@ -398,7 +398,7 @@ class Map extends SummarizedCallable {
}
}
class Of extends SummarizedCallable {
class Of extends SummarizedCallable::Range {
Of() { this = "Array.of" }
override DataFlow::CallNode getACallSimple() {
@@ -412,7 +412,7 @@ class Of extends SummarizedCallable {
}
}
class Pop extends SummarizedCallable {
class Pop extends SummarizedCallable::Range {
Pop() { this = "Array#pop" }
override InstanceCall getACallSimple() { result.getMethodName() = "pop" }
@@ -424,7 +424,7 @@ class Pop extends SummarizedCallable {
}
}
class PushLike extends SummarizedCallable {
class PushLike extends SummarizedCallable::Range {
PushLike() { this = "Array#push / Array#unshift" }
override InstanceCall getACallSimple() { result.getMethodName() = ["push", "unshift"] }
@@ -436,7 +436,7 @@ class PushLike extends SummarizedCallable {
}
}
class ReduceLike extends SummarizedCallable {
class ReduceLike extends SummarizedCallable::Range {
ReduceLike() { this = "Array#reduce / Array#reduceRight" }
override InstanceCall getACallSimple() { result.getMethodName() = ["reduce", "reduceRight"] }
@@ -465,7 +465,7 @@ class ReduceLike extends SummarizedCallable {
}
}
class Reverse extends SummarizedCallable {
class Reverse extends SummarizedCallable::Range {
Reverse() { this = "Array#reverse / Array#toReversed" }
override InstanceCall getACallSimple() { result.getMethodName() = ["reverse", "toReversed"] }
@@ -477,7 +477,7 @@ class Reverse extends SummarizedCallable {
}
}
class Shift extends SummarizedCallable {
class Shift extends SummarizedCallable::Range {
Shift() { this = "Array#shift" }
override InstanceCall getACallSimple() { result.getMethodName() = "shift" }
@@ -495,7 +495,7 @@ class Shift extends SummarizedCallable {
}
}
class Sort extends SummarizedCallable {
class Sort extends SummarizedCallable::Range {
Sort() { this = "Array#sort / Array#toSorted" }
override InstanceCall getACallSimple() { result.getMethodName() = ["sort", "toSorted"] }
@@ -512,7 +512,7 @@ class Sort extends SummarizedCallable {
}
}
class Splice extends SummarizedCallable {
class Splice extends SummarizedCallable::Range {
Splice() { this = "Array#splice" }
override InstanceCall getACallSimple() { result.getMethodName() = "splice" }
@@ -529,7 +529,7 @@ class Splice extends SummarizedCallable {
}
}
class ToSpliced extends SummarizedCallable {
class ToSpliced extends SummarizedCallable::Range {
ToSpliced() { this = "Array#toSpliced" }
override InstanceCall getACallSimple() { result.getMethodName() = "toSpliced" }
@@ -546,7 +546,7 @@ class ToSpliced extends SummarizedCallable {
}
}
class With extends SummarizedCallable {
class With extends SummarizedCallable::Range {
With() { this = "Array#with" }
override InstanceCall getACallSimple() { result.getMethodName() = "with" }

View File

@@ -16,7 +16,7 @@ private class TextDecoderEntryPoint extends API::EntryPoint {
pragma[nomagic]
API::Node textDecoderConstructorRef() { result = any(TextDecoderEntryPoint e).getANode() }
class Decode extends SummarizedCallable {
class Decode extends SummarizedCallable::Range {
Decode() { this = "TextDecoder#decode" }
override InstanceCall getACall() {

View File

@@ -29,7 +29,7 @@ private predicate isCallback(DataFlow::SourceNode node) {
* See also `FlowSummaryDefaultExceptionalReturn`, which handles calls that have a summary target,
* but where the summary does not mention `ReturnValue[exception]`.
*/
private class ExceptionFlowSummary extends SummarizedCallable, LibraryCallableInternal {
private class ExceptionFlowSummary extends SummarizedCallable::Range, LibraryCallableInternal {
ExceptionFlowSummary() { this = "Exception propagator" }
override DataFlow::CallNode getACallStage2() {

View File

@@ -20,7 +20,7 @@ class InstanceCall extends DataFlow::CallNode {
/**
* A summary a function that is the default export from an NPM package.
*/
abstract class FunctionalPackageSummary extends SummarizedCallable {
abstract class FunctionalPackageSummary extends SummarizedCallable::Range {
bindingset[this]
FunctionalPackageSummary() { any() }

View File

@@ -10,7 +10,7 @@ private import semmle.javascript.dataflow.FlowSummary
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
private import FlowSummaryUtil
class IteratorNext extends SummarizedCallable {
class IteratorNext extends SummarizedCallable::Range {
IteratorNext() { this = "Iterator#next" }
override DataFlow::MethodCallNode getACallSimple() {

View File

@@ -9,7 +9,7 @@ private import FlowSummaryUtil
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
private import semmle.javascript.dataflow.FlowSummary
private class JsonStringifySummary extends SummarizedCallable {
private class JsonStringifySummary extends SummarizedCallable::Range {
JsonStringifySummary() { this = "JSON.stringify" }
override DataFlow::InvokeNode getACall() { result instanceof JsonStringifyCall }

View File

@@ -10,7 +10,7 @@ private import FlowSummaryUtil
private DataFlow::SourceNode mapConstructorRef() { result = DataFlow::globalVarRef("Map") }
class MapConstructor extends SummarizedCallable {
class MapConstructor extends SummarizedCallable::Range {
MapConstructor() { this = "Map constructor" }
override DataFlow::InvokeNode getACallSimple() {
@@ -80,7 +80,7 @@ class MapSetStep extends DataFlow::AdditionalFlowStep {
}
}
class MapGet extends SummarizedCallable {
class MapGet extends SummarizedCallable::Range {
MapGet() { this = "Map#get" }
override DataFlow::MethodCallNode getACallSimple() {
@@ -96,7 +96,7 @@ class MapGet extends SummarizedCallable {
}
}
class MapSet extends SummarizedCallable {
class MapSet extends SummarizedCallable::Range {
MapSet() { this = "Map#set" }
override DataFlow::MethodCallNode getACallSimple() {
@@ -121,7 +121,7 @@ class MapSet extends SummarizedCallable {
}
}
class MapGroupBy extends SummarizedCallable {
class MapGroupBy extends SummarizedCallable::Range {
MapGroupBy() { this = "Map#groupBy" }
override DataFlow::CallNode getACallSimple() {

View File

@@ -23,7 +23,7 @@ DataFlow::SourceNode promiseConstructorRef() {
// Note that the 'Awaited' token has a special interpretation.
// See a write-up here: https://github.com/github/codeql-javascript-team/issues/423
//
private class PromiseConstructor extends SummarizedCallable {
private class PromiseConstructor extends SummarizedCallable::Range {
PromiseConstructor() { this = "new Promise()" }
override DataFlow::InvokeNode getACallSimple() {
@@ -53,7 +53,7 @@ private class PromiseConstructor extends SummarizedCallable {
* for callbacks.
*/
module PromiseConstructorWorkaround {
class ResolveSummary extends SummarizedCallable {
class ResolveSummary extends SummarizedCallable::Range {
ResolveSummary() { this = "new Promise() resolve callback" }
override DataFlow::InvokeNode getACallSimple() {
@@ -68,7 +68,7 @@ module PromiseConstructorWorkaround {
}
}
class RejectCallback extends SummarizedCallable {
class RejectCallback extends SummarizedCallable::Range {
RejectCallback() { this = "new Promise() reject callback" }
override DataFlow::InvokeNode getACallSimple() {
@@ -83,7 +83,7 @@ module PromiseConstructorWorkaround {
}
}
class ConstructorSummary extends SummarizedCallable {
class ConstructorSummary extends SummarizedCallable::Range {
ConstructorSummary() { this = "new Promise() workaround" }
override DataFlow::InvokeNode getACallSimple() {
@@ -106,7 +106,7 @@ module PromiseConstructorWorkaround {
}
}
private class PromiseThen2Arguments extends SummarizedCallable {
private class PromiseThen2Arguments extends SummarizedCallable::Range {
PromiseThen2Arguments() { this = "Promise#then() with 2 arguments" }
override InstanceCall getACallSimple() {
@@ -128,7 +128,7 @@ private class PromiseThen2Arguments extends SummarizedCallable {
}
}
private class PromiseThen1Argument extends SummarizedCallable {
private class PromiseThen1Argument extends SummarizedCallable::Range {
PromiseThen1Argument() { this = "Promise#then() with 1 argument" }
override InstanceCall getACallSimple() {
@@ -150,7 +150,7 @@ private class PromiseThen1Argument extends SummarizedCallable {
}
}
private class PromiseCatch extends SummarizedCallable {
private class PromiseCatch extends SummarizedCallable::Range {
PromiseCatch() { this = "Promise#catch()" }
override InstanceCall getACallSimple() { result.getMethodName() = "catch" }
@@ -169,7 +169,7 @@ private class PromiseCatch extends SummarizedCallable {
}
}
private class PromiseFinally extends SummarizedCallable {
private class PromiseFinally extends SummarizedCallable::Range {
PromiseFinally() { this = "Promise#finally()" }
override InstanceCall getACallSimple() { result.getMethodName() = "finally" }
@@ -186,7 +186,7 @@ private class PromiseFinally extends SummarizedCallable {
}
}
private class PromiseResolve extends SummarizedCallable {
private class PromiseResolve extends SummarizedCallable::Range {
PromiseResolve() { this = "Promise.resolve()" }
override InstanceCall getACallSimple() {
@@ -200,7 +200,7 @@ private class PromiseResolve extends SummarizedCallable {
}
}
private class PromiseReject extends SummarizedCallable {
private class PromiseReject extends SummarizedCallable::Range {
PromiseReject() { this = "Promise.reject()" }
override InstanceCall getACallSimple() {
@@ -261,7 +261,7 @@ private class PromiseAllStep extends SharedTypeTrackingStep {
}
}
private class PromiseAll extends SummarizedCallable {
private class PromiseAll extends SummarizedCallable::Range {
PromiseAll() { this = "Promise.all()" }
override DataFlow::InvokeNode getACallSimple() { result instanceof PromiseAllCall }
@@ -283,7 +283,7 @@ private class PromiseAll extends SummarizedCallable {
}
}
private class PromiseAnyLike extends SummarizedCallable {
private class PromiseAnyLike extends SummarizedCallable::Range {
PromiseAnyLike() { this = "Promise.any() or Promise.race()" }
override DataFlow::InvokeNode getACallSimple() {
@@ -297,7 +297,7 @@ private class PromiseAnyLike extends SummarizedCallable {
}
}
private class PromiseAllSettled extends SummarizedCallable {
private class PromiseAllSettled extends SummarizedCallable::Range {
PromiseAllSettled() { this = "Promise.allSettled()" }
override DataFlow::InvokeNode getACallSimple() {
@@ -318,7 +318,7 @@ private class PromiseAllSettled extends SummarizedCallable {
}
}
private class BluebirdMapSeries extends SummarizedCallable {
private class BluebirdMapSeries extends SummarizedCallable::Range {
BluebirdMapSeries() { this = "bluebird.mapSeries" }
override DataFlow::InvokeNode getACallSimple() {
@@ -351,7 +351,7 @@ private class BluebirdMapSeries extends SummarizedCallable {
* - `goog.Closure.withResolver()` (non-plural spelling)
* - `bluebird.Promise.defer()`
*/
private class PromiseWithResolversLike extends SummarizedCallable {
private class PromiseWithResolversLike extends SummarizedCallable::Range {
PromiseWithResolversLike() { this = "Promise.withResolvers()" }
override DataFlow::InvokeNode getACallSimple() {
@@ -371,7 +371,7 @@ private class PromiseWithResolversLike extends SummarizedCallable {
}
}
class PromiseTry extends DataFlow::SummarizedCallable {
class PromiseTry extends DataFlow::SummarizedCallable::Range {
PromiseTry() { this = "Promise.try()" }
override DataFlow::CallNode getACallSimple() {

View File

@@ -10,7 +10,7 @@ private import FlowSummaryUtil
private DataFlow::SourceNode setConstructorRef() { result = DataFlow::globalVarRef("Set") }
class SetConstructor extends SummarizedCallable {
class SetConstructor extends SummarizedCallable::Range {
SetConstructor() { this = "Set constructor" }
override DataFlow::InvokeNode getACallSimple() {
@@ -32,7 +32,7 @@ class SetConstructor extends SummarizedCallable {
}
}
class SetAdd extends SummarizedCallable {
class SetAdd extends SummarizedCallable::Range {
SetAdd() { this = "Set#add" }
override DataFlow::MethodCallNode getACallSimple() {

View File

@@ -10,7 +10,7 @@ private import semmle.javascript.dataflow.FlowSummary
/**
* Summary for calls to `.replace` or `.replaceAll` (without a regexp pattern containing a wildcard).
*/
private class StringReplaceNoWildcard extends SummarizedCallable {
private class StringReplaceNoWildcard extends SummarizedCallable::Range {
StringReplaceNoWildcard() {
this = "String#replace / String#replaceAll (without wildcard pattern)"
}
@@ -34,7 +34,7 @@ private class StringReplaceNoWildcard extends SummarizedCallable {
*
* In this case, the receiver is considered to flow into the callback.
*/
private class StringReplaceWithWildcard extends SummarizedCallable {
private class StringReplaceWithWildcard extends SummarizedCallable::Range {
StringReplaceWithWildcard() {
this = "String#replace / String#replaceAll (with wildcard pattern)"
}
@@ -53,7 +53,7 @@ private class StringReplaceWithWildcard extends SummarizedCallable {
}
}
class StringSplit extends SummarizedCallable {
class StringSplit extends SummarizedCallable::Range {
StringSplit() { this = "String#split" }
override DataFlow::MethodCallNode getACallSimple() {
@@ -78,7 +78,7 @@ class StringSplit extends SummarizedCallable {
* This summary defaults to the same behavior as the general `.split()` case, but it contains optional steps
* and barriers named `tainted-url-suffix` that should be activated when tracking a tainted URL suffix.
*/
class StringSplitHashOrQuestionMark extends SummarizedCallable {
class StringSplitHashOrQuestionMark extends SummarizedCallable::Range {
StringSplitHashOrQuestionMark() { this = "String#split with '#' or '?'" }
override DataFlow::MethodCallNode getACallSimple() {
@@ -102,7 +102,7 @@ class StringSplitHashOrQuestionMark extends SummarizedCallable {
}
}
class StringFromCharCode extends SummarizedCallable {
class StringFromCharCode extends SummarizedCallable::Range {
StringFromCharCode() { this = "String#fromCharCode" }
override DataFlow::CallNode getACall() {

View File

@@ -16,7 +16,7 @@ private class TypedArrayEntryPoint extends API::EntryPoint {
pragma[nomagic]
API::Node typedArrayConstructorRef() { result = any(TypedArrayEntryPoint e).getANode() }
class TypedArrayConstructorSummary extends SummarizedCallable {
class TypedArrayConstructorSummary extends SummarizedCallable::Range {
TypedArrayConstructorSummary() { this = "TypedArray constructor" }
override DataFlow::InvokeNode getACall() {
@@ -40,7 +40,7 @@ class BufferTypedArray extends DataFlow::AdditionalFlowStep {
}
}
class TypedArraySet extends SummarizedCallable {
class TypedArraySet extends SummarizedCallable::Range {
TypedArraySet() { this = "TypedArray#set" }
override InstanceCall getACall() {
@@ -54,7 +54,7 @@ class TypedArraySet extends SummarizedCallable {
}
}
class TypedArraySubarray extends SummarizedCallable {
class TypedArraySubarray extends SummarizedCallable::Range {
TypedArraySubarray() { this = "TypedArray#subarray" }
override InstanceCall getACall() { result.getMethodName() = "subarray" }
@@ -77,7 +77,7 @@ private class ArrayBufferEntryPoint extends API::EntryPoint {
pragma[nomagic]
API::Node arrayBufferConstructorRef() { result = any(ArrayBufferEntryPoint a).getANode() }
class TransferLike extends SummarizedCallable {
class TransferLike extends SummarizedCallable::Range {
TransferLike() { this = "ArrayBuffer#transfer" }
override InstanceCall getACall() {

View File

@@ -14,7 +14,7 @@ DataFlow::SourceNode urlSearchParamsConstructorRef() {
result = DataFlow::globalVarRef("URLSearchParams")
}
class URLSearchParams extends DataFlow::SummarizedCallable {
class URLSearchParams extends DataFlow::SummarizedCallable::Range {
URLSearchParams() { this = "URLSearchParams" }
override DataFlow::InvokeNode getACallSimple() {
@@ -30,7 +30,7 @@ class URLSearchParams extends DataFlow::SummarizedCallable {
}
}
class GetAll extends DataFlow::SummarizedCallable {
class GetAll extends DataFlow::SummarizedCallable::Range {
GetAll() { this = "getAll" }
override DataFlow::MethodCallNode getACallSimple() {
@@ -44,7 +44,7 @@ class GetAll extends DataFlow::SummarizedCallable {
}
}
class URLConstructor extends DataFlow::SummarizedCallable {
class URLConstructor extends DataFlow::SummarizedCallable::Range {
URLConstructor() { this = "URL" }
override DataFlow::InvokeNode getACallSimple() {

View File

@@ -2,7 +2,7 @@ import javascript
import semmle.javascript.dataflow.FlowSummary
overlay[local?]
class MkSummary extends SummarizedCallable {
class MkSummary extends SummarizedCallable::Range {
private CallExpr mkSummary;
MkSummary() {