From 93dad867cd8c0804fdc4ea9133008527cfd45f09 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 18 Dec 2025 11:03:37 +0100 Subject: [PATCH] JS: Adapt to changes in `FlowSummaryImpl` --- .../javascript/dataflow/FlowSummary.qll | 148 ++++++++++-------- .../internal/sharedlib/DataFlowArg.qll | 3 + .../internal/sharedlib/SummaryTypeTracker.qll | 2 +- .../javascript/frameworks/AsyncPackage.qll | 4 +- .../frameworks/LodashUnderscore.qll | 22 +-- .../javascript/frameworks/UriLibraries.qll | 2 +- .../frameworks/data/ModelsAsData.qll | 11 +- .../flow_summaries/AmbiguousCoreMethods.qll | 16 +- .../internal/flow_summaries/Arrays.qll | 46 +++--- .../internal/flow_summaries/Decoders.qll | 2 +- .../internal/flow_summaries/ExceptionFlow.qll | 2 +- .../flow_summaries/FlowSummaryUtil.qll | 2 +- .../internal/flow_summaries/Iterators.qll | 2 +- .../internal/flow_summaries/JsonStringify.qll | 2 +- .../internal/flow_summaries/Maps.qll | 8 +- .../internal/flow_summaries/Promises.qll | 32 ++-- .../internal/flow_summaries/Sets.qll | 4 +- .../internal/flow_summaries/Strings.qll | 10 +- .../internal/flow_summaries/TypedArrays.qll | 8 +- .../flow_summaries/UrlSearchParams.qll | 6 +- .../ql/lib/utils/test/InlineSummaries.qll | 2 +- 21 files changed, 179 insertions(+), 155 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll index c4661b321ea..3f809a96723 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll @@ -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 +{ } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll index c911461788d..76992ed02cf 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll @@ -28,6 +28,9 @@ module JSFlowSummary implements FlowSummaryImpl::InputSig 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; diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll index c9acd77db1a..23c897827e2 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll @@ -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() } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll index c95b7a8dc6a..0545f25a184 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index 74808368c71..4d0d3d771e1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -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() } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll index 03887819b25..ec85c376b67 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll @@ -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] diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll index 5d65f901d22..df48a184089 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll @@ -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 diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll index 4e1c9ee6884..f4783b2131b 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll index 1196ffdbac9..984a9537003 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll @@ -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" } diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll index 80e43fdfcd8..6fc26be9a04 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll index 3dff015d9f3..7dff4e71805 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll index 290567efbd9..5d96c57dd1d 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll @@ -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() } diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll index 7f9c13c63df..22529cdde53 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll index 4b8ecdeb4f2..4662aecd735 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll @@ -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 } diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll index 645e36941dc..decc462cb74 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll index 10292958df2..d9421c9d562 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll index e4d0951764f..765ad881559 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll index b5ecc8ef603..4714cb236ec 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll index 0ac2307c81a..71290dfa284 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll @@ -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() { diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll index 3d8d88d8ae4..3386d86bc83 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll @@ -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() { diff --git a/javascript/ql/lib/utils/test/InlineSummaries.qll b/javascript/ql/lib/utils/test/InlineSummaries.qll index 1633e056b7f..5d113049673 100644 --- a/javascript/ql/lib/utils/test/InlineSummaries.qll +++ b/javascript/ql/lib/utils/test/InlineSummaries.qll @@ -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() {