mirror of
https://github.com/github/codeql.git
synced 2026-02-11 20:51:06 +01:00
JS: Adapt to changes in FlowSummaryImpl
This commit is contained in:
@@ -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
|
||||
{ }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() }
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user