Skip to content

Commit 2d63aaa

Browse files
committed
JS: Adapt to changes in FlowSummaryImpl
1 parent 25d97ad commit 2d63aaa

File tree

21 files changed

+179
-155
lines changed

21 files changed

+179
-155
lines changed

javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll

Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,94 @@ private import semmle.javascript.dataflow.internal.FlowSummaryPrivate
88
private import semmle.javascript.dataflow.internal.sharedlib.DataFlowImplCommon as DataFlowImplCommon
99
private import semmle.javascript.dataflow.internal.DataFlowPrivate
1010

11-
/**
12-
* A model for a function that can propagate data flow.
13-
*
14-
* This class makes it possible to model flow through functions, using the same mechanism as
15-
* `summaryModel` as described in the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript).
16-
*
17-
* Extend this class to define summary models directly in CodeQL.
18-
* Data extensions and `summaryModel` are usually preferred; but there are a few cases where direct use of this class may be needed:
19-
*
20-
* - The relevant call sites cannot be matched by the access path syntax, and require the full power of CodeQL.
21-
* For example, complex overloading patterns might require more local reasoning at the call site.
22-
* - The input/output behavior cannot be described statically in the access path syntax, but the relevant access paths
23-
* can be generated dynamically in CodeQL, based on the usages found in the codebase.
24-
*
25-
* Subclasses should bind `this` to a unique identifier for the function being modeled. There is no special
26-
* interpreation of the `this` value, it should just not clash with the `this`-value used by other classes.
27-
*
28-
* For example, this models flow through calls such as `require("my-library").myFunction()`:
29-
* ```codeql
30-
* class MyFunction extends SummarizedCallable {
31-
* MyFunction() { this = "MyFunction" }
32-
*
33-
* override predicate propagatesFlow(string input, string output, boolean preservesValues) {
34-
* input = "Argument[0]" and
35-
* output = "ReturnValue" and
36-
* preservesValue = false
37-
* }
38-
*
39-
* override DataFlow::InvokeNode getACall() {
40-
* result = API::moduleImport("my-library").getMember("myFunction").getACall()
41-
* }
42-
* }
43-
* ```
44-
* This would be equivalent to the following model written as a data extension:
45-
* ```yaml
46-
* extensions:
47-
* - addsTo:
48-
* pack: codeql/javascript-all
49-
* extensible: summaryModel
50-
* data:
51-
* - ["my-library", "Member[myFunction]", "Argument[0]", "ReturnValue", "taint"]
52-
* ```
53-
*/
54-
abstract class SummarizedCallable extends LibraryCallable, Impl::Public::SummarizedCallable {
55-
bindingset[this]
56-
SummarizedCallable() { any() }
11+
class Provenance = Impl::Public::Provenance;
5712

13+
/** Provides the `Range` class used to define the extent of `SummarizedCallable`. */
14+
module SummarizedCallable {
5815
/**
59-
* Holds if data may flow from `input` to `output` through this callable.
16+
* A model for a function that can propagate data flow.
6017
*
61-
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
18+
* This class makes it possible to model flow through functions, using the same mechanism as
19+
* `summaryModel` as described in the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript).
6220
*
63-
* See the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript) for
64-
* the syntax of the `input` and `output` parameters.
21+
* Extend this class to define summary models directly in CodeQL.
22+
* Data extensions and `summaryModel` are usually preferred; but there are a few cases where direct use of this class may be needed:
23+
*
24+
* - The relevant call sites cannot be matched by the access path syntax, and require the full power of CodeQL.
25+
* For example, complex overloading patterns might require more local reasoning at the call site.
26+
* - The input/output behavior cannot be described statically in the access path syntax, but the relevant access paths
27+
* can be generated dynamically in CodeQL, based on the usages found in the codebase.
28+
*
29+
* Subclasses should bind `this` to a unique identifier for the function being modeled. There is no special
30+
* interpreation of the `this` value, it should just not clash with the `this`-value used by other classes.
31+
*
32+
* For example, this models flow through calls such as `require("my-library").myFunction()`:
33+
* ```codeql
34+
* class MyFunction extends SummarizedCallable::Range {
35+
* MyFunction() { this = "MyFunction" }
36+
*
37+
* override predicate propagatesFlow(string input, string output, boolean preservesValues) {
38+
* input = "Argument[0]" and
39+
* output = "ReturnValue" and
40+
* preservesValue = false
41+
* }
42+
*
43+
* override DataFlow::InvokeNode getACall() {
44+
* result = API::moduleImport("my-library").getMember("myFunction").getACall()
45+
* }
46+
* }
47+
* ```
48+
* This would be equivalent to the following model written as a data extension:
49+
* ```yaml
50+
* extensions:
51+
* - addsTo:
52+
* pack: codeql/javascript-all
53+
* extensible: summaryModel
54+
* data:
55+
* - ["my-library", "Member[myFunction]", "Argument[0]", "ReturnValue", "taint"]
56+
* ```
6557
*/
66-
pragma[nomagic]
67-
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
58+
abstract class Range extends LibraryCallable, Impl::Public::SummarizedCallable {
59+
bindingset[this]
60+
Range() { any() }
6861

69-
override predicate propagatesFlow(
70-
string input, string output, boolean preservesValue, string model
71-
) {
72-
this.propagatesFlow(input, output, preservesValue) and model = this
73-
}
62+
/**
63+
* Holds if data may flow from `input` to `output` through this callable.
64+
*
65+
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
66+
*
67+
* See the [library customization docs](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-javascript) for
68+
* the syntax of the `input` and `output` parameters.
69+
*/
70+
pragma[nomagic]
71+
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
7472

75-
/**
76-
* Gets the synthesized parameter that results from an input specification
77-
* that starts with `Argument[s]` for this library callable.
78-
*/
79-
DataFlow::ParameterNode getParameter(string s) {
80-
exists(ParameterPosition pos |
81-
DataFlowImplCommon::parameterNode(result, MkLibraryCallable(this), pos) and
82-
s = encodeParameterPosition(pos)
83-
)
73+
override predicate propagatesFlow(
74+
string input, string output, boolean preservesValue, Provenance provenance, boolean isExact,
75+
string model
76+
) {
77+
this.propagatesFlow(input, output, preservesValue) and
78+
provenance = "manual" and
79+
model = this and
80+
isExact = true
81+
}
82+
83+
/**
84+
* Gets the synthesized parameter that results from an input specification
85+
* that starts with `Argument[s]` for this library callable.
86+
*/
87+
DataFlow::ParameterNode getParameter(string s) {
88+
exists(ParameterPosition pos |
89+
DataFlowImplCommon::parameterNode(result, MkLibraryCallable(this), pos) and
90+
s = encodeParameterPosition(pos)
91+
)
92+
}
8493
}
8594
}
95+
96+
final private class SummarizedCallableFinal = SummarizedCallable::Range;
97+
98+
/** A model for a function that can propagate data flow. */
99+
final class SummarizedCallable extends SummarizedCallableFinal,
100+
Impl::Public::RelevantSummarizedCallable
101+
{ }

javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ module JSFlowSummary implements FlowSummaryImpl::InputSig<Location, JSDataFlow>
2828
private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate
2929
import FlowSummaryPrivate
3030

31+
overlay[local]
32+
predicate callableFromSource(SummarizedCallableBase c) { none() }
33+
3134
// Explicitly implement signature members that have a default
3235
predicate callbackSelfParameterPosition = FlowSummaryPrivate::callbackSelfParameterPosition/0;
3336

javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private module SummaryFlowConfig implements Input {
6969
predicate propagatesFlow(
7070
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
7171
) {
72-
super.propagatesFlow(input, output, preservesValue, _)
72+
super.propagatesFlow(input, output, preservesValue, _, _, _)
7373
}
7474

7575
string toString() { result = super.toString() }

javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ module AsyncPackage {
173173
}
174174

175175
overlay[local?]
176-
private class IterationCallFlowSummary extends DataFlow::SummarizedCallable {
176+
private class IterationCallFlowSummary extends DataFlow::SummarizedCallable::Range {
177177
private int callbackArgIndex;
178178

179179
IterationCallFlowSummary() {
@@ -221,7 +221,7 @@ module AsyncPackage {
221221
* For example: `data -> result` in `async.sortBy(data, orderingFn, (err, result) => {})`.
222222
*/
223223
overlay[local?]
224-
private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable {
224+
private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable::Range {
225225
IterationPreserveTaintStepFlowSummary() { this = "async.sortBy" }
226226

227227
override DataFlow::InvokeNode getACallSimple() {

javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ module LodashUnderscore {
186186
}
187187

188188
overlay[local?]
189-
private class LodashEach extends DataFlow::SummarizedCallable {
189+
private class LodashEach extends DataFlow::SummarizedCallable::Range {
190190
LodashEach() { this = "_.each-like" }
191191

192192
overlay[global]
@@ -202,7 +202,7 @@ module LodashUnderscore {
202202
}
203203

204204
overlay[local?]
205-
private class LodashMap extends DataFlow::SummarizedCallable {
205+
private class LodashMap extends DataFlow::SummarizedCallable::Range {
206206
LodashMap() { this = "_.map" }
207207

208208
overlay[global]
@@ -221,7 +221,7 @@ module LodashUnderscore {
221221
}
222222

223223
overlay[local?]
224-
private class LodashFlatMap extends DataFlow::SummarizedCallable {
224+
private class LodashFlatMap extends DataFlow::SummarizedCallable::Range {
225225
LodashFlatMap() { this = "_.flatMap" }
226226

227227
overlay[global]
@@ -243,7 +243,7 @@ module LodashUnderscore {
243243
}
244244

245245
overlay[local?]
246-
private class LodashFlatMapDeep extends DataFlow::SummarizedCallable {
246+
private class LodashFlatMapDeep extends DataFlow::SummarizedCallable::Range {
247247
LodashFlatMapDeep() { this = "_.flatMapDeep" }
248248

249249
overlay[global]
@@ -267,7 +267,7 @@ module LodashUnderscore {
267267
}
268268

269269
overlay[local?]
270-
private class LodashReduce extends DataFlow::SummarizedCallable {
270+
private class LodashReduce extends DataFlow::SummarizedCallable::Range {
271271
LodashReduce() { this = "_.reduce-like" }
272272

273273
overlay[global]
@@ -286,7 +286,7 @@ module LodashUnderscore {
286286
}
287287

288288
overlay[local?]
289-
private class LoashSortBy extends DataFlow::SummarizedCallable {
289+
private class LoashSortBy extends DataFlow::SummarizedCallable::Range {
290290
LoashSortBy() { this = "_.sortBy-like" }
291291

292292
overlay[global]
@@ -304,7 +304,7 @@ module LodashUnderscore {
304304
}
305305

306306
overlay[local?]
307-
private class LodashMinMaxBy extends DataFlow::SummarizedCallable {
307+
private class LodashMinMaxBy extends DataFlow::SummarizedCallable::Range {
308308
LodashMinMaxBy() { this = "_.minBy / _.maxBy" }
309309

310310
overlay[global]
@@ -318,7 +318,7 @@ module LodashUnderscore {
318318
}
319319

320320
overlay[local?]
321-
private class LodashPartition extends DataFlow::SummarizedCallable {
321+
private class LodashPartition extends DataFlow::SummarizedCallable::Range {
322322
LodashPartition() { this = "_.partition" }
323323

324324
overlay[global]
@@ -332,7 +332,7 @@ module LodashUnderscore {
332332
}
333333

334334
overlay[local?]
335-
private class UnderscoreMapObject extends DataFlow::SummarizedCallable {
335+
private class UnderscoreMapObject extends DataFlow::SummarizedCallable::Range {
336336
UnderscoreMapObject() { this = "_.mapObject" }
337337

338338
overlay[global]
@@ -353,7 +353,7 @@ module LodashUnderscore {
353353
}
354354

355355
overlay[local?]
356-
private class LodashTap extends DataFlow::SummarizedCallable {
356+
private class LodashTap extends DataFlow::SummarizedCallable::Range {
357357
LodashTap() { this = "_.tap" }
358358

359359
overlay[global]
@@ -367,7 +367,7 @@ module LodashUnderscore {
367367
}
368368

369369
overlay[local?]
370-
private class LodashGroupBy extends DataFlow::SummarizedCallable {
370+
private class LodashGroupBy extends DataFlow::SummarizedCallable::Range {
371371
LodashGroupBy() { this = "_.groupBy" }
372372

373373
override DataFlow::CallNode getACall() { result = member("groupBy").getACall() }

javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ private module ClosureLibraryUri {
423423
}
424424

425425
overlay[local?]
426-
private class QueryStringStringification extends DataFlow::SummarizedCallable {
426+
private class QueryStringStringification extends DataFlow::SummarizedCallable::Range {
427427
QueryStringStringification() { this = "query-string stringification" }
428428

429429
overlay[global]

javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang
4949
}
5050

5151
overlay[local?]
52-
private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable {
52+
private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable::Range {
5353
string type;
5454
string path;
5555

@@ -62,9 +62,14 @@ private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable {
6262
override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) }
6363

6464
override predicate propagatesFlow(
65-
string input, string output, boolean preservesValue, string model
65+
string input, string output, boolean preservesValue, DataFlow::Provenance provenance,
66+
boolean isExact, string model
6667
) {
67-
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) |
68+
exists(string kind |
69+
ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) and
70+
provenance = "manual" and
71+
isExact = true
72+
|
6873
kind = "value" and
6974
preservesValue = true
7075
or

0 commit comments

Comments
 (0)