|
| type_alias.ts:14:9:14:32 | [proper ... ]: Json | any |
@@ -461,6 +541,9 @@ getTypeDefinitionType
| tst.ts:265:3:269:3 | interfa ... an;\\n } | TypeMap |
| tst.ts:271:3:276:7 | type Un ... }[P]; | UnionRecord |
| tst.ts:289:3:289:63 | type Fu ... > void; | Func |
+| tst.ts:332:3:335:16 | type Fi ... never; | FirstString |
+| tst.ts:337:3:337:53 | type F ... lean]>; | "a" \| "b" |
+| tst.ts:343:3:346:3 | interfa ... id;\\n } | State |
| type_alias.ts:1:1:1:17 | type B = boolean; | boolean |
| type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray |
| type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json |
@@ -703,6 +786,39 @@ getTypeExprType
| tst.ts:289:47:289:52 | string | string |
| tst.ts:289:59:289:62 | void | void |
| tst.ts:291:13:291:16 | Func | Func |
+| tst.ts:314:14:314:14 | T | T |
+| tst.ts:314:22:316:29 | {\\n p ... void } | { produce: (n: string) => T; consume: (x: T) =>... |
+| tst.ts:315:14:315:29 | (n: string) => T | (n: string) => T |
+| tst.ts:315:18:315:23 | string | string |
+| tst.ts:315:29:315:29 | T | T |
+| tst.ts:316:14:316:27 | (x: T) => void | (x: T) => void |
+| tst.ts:316:18:316:18 | T | T |
+| tst.ts:316:24:316:27 | void | void |
+| tst.ts:317:6:317:9 | void | void |
+| tst.ts:326:24:326:29 | string | string |
+| tst.ts:326:32:326:36 | Error | Error |
+| tst.ts:332:8:332:18 | FirstString | FirstString |
+| tst.ts:332:20:332:20 | T | T |
+| tst.ts:337:8:337:8 | F | "a" \| "b" |
+| tst.ts:337:12:337:22 | FirstString | FirstString |
+| tst.ts:337:12:337:52 | FirstSt ... olean]> | "a" \| "b" |
+| tst.ts:337:24:337:51 | ['a' \| ... oolean] | ["a" \| "b", number, boolean] |
+| tst.ts:337:25:337:27 | 'a' | "a" |
+| tst.ts:337:25:337:33 | 'a' \| 'b' | "a" \| "b" |
+| tst.ts:337:31:337:33 | 'b' | "b" |
+| tst.ts:337:36:337:41 | number | number |
+| tst.ts:337:44:337:50 | boolean | boolean |
+| tst.ts:339:12:339:12 | F | "a" \| "b" |
+| tst.ts:343:13:343:17 | State | State |
+| tst.ts:343:26:343:26 | T | T |
+| tst.ts:344:10:344:16 | () => T | () => T |
+| tst.ts:344:16:344:16 | T | T |
+| tst.ts:345:10:345:27 | (value: T) => void | (value: T) => void |
+| tst.ts:345:18:345:18 | T | T |
+| tst.ts:345:24:345:27 | void | void |
+| tst.ts:348:16:348:20 | State | State |
+| tst.ts:348:16:348:28 | State | State |
+| tst.ts:348:22:348:27 | number | number |
| type_alias.ts:1:6:1:6 | B | boolean |
| type_alias.ts:1:10:1:16 | boolean | boolean |
| type_alias.ts:3:8:3:8 | B | boolean |
@@ -783,6 +899,7 @@ referenceDefinition
| E | type_definition_objects.ts:6:8:6:16 | enum E {} |
| EnumWithOneMember | type_definitions.ts:18:26:18:31 | member |
| Error | tst.ts:210:10:213:3 | interfa ... ng;\\n } |
+| FirstString | tst.ts:332:3:335:16 | type Fi ... never; |
| Foo | tst.ts:116:3:129:3 | class F ... }\\n } |
| Foo | tst.ts:165:5:167:5 | interfa ... ;\\n } |
| Foo | tst.ts:179:3:192:3 | class F ... \\n } |
@@ -796,6 +913,8 @@ referenceDefinition
| NonAbstractDummy | tst.ts:54:1:56:1 | interfa ... mber;\\n} |
| Person | tst.ts:222:3:234:3 | class P ... }\\n } |
| Shape | tst.ts:140:3:142:47 | type Sh ... mber }; |
+| State | tst.ts:343:3:346:3 | interfa ... id;\\n } |
+| State | tst.ts:343:3:346:3 | interfa ... id;\\n } |
| Sub | tst.ts:97:3:101:3 | class S ... }\\n } |
| Success | tst.ts:205:10:208:3 | interfa ... ng;\\n } |
| Super | tst.ts:91:3:95:3 | class S ... }\\n } |
@@ -852,16 +971,20 @@ abstractSignature
unionIndex
| 1 | 0 | 1 \| 2 |
| 2 | 1 | 1 \| 2 |
+| 42 | 1 | "hello" \| 42 |
| "NumberContents" | 0 | "NumberContents" \| "StringContents" |
| "StringContents" | 1 | "NumberContents" \| "StringContents" |
| "a" | 0 | "a" \| "b" |
| "a" | 1 | number \| "a" |
+| "a" | 3 | number \| boolean \| "a" \| "b" |
| "b" | 1 | "a" \| "b" |
+| "b" | 4 | number \| boolean \| "a" \| "b" |
| "bigint" | 2 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "boolean" | 2 | keyof TypeMap |
| "boolean" | 3 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "circle" | 0 | "circle" \| "square" |
| "function" | 7 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
+| "hello" | 0 | "hello" \| 42 |
| "number" | 1 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "number" | 1 | keyof TypeMap |
| "object" | 6 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
@@ -871,6 +994,7 @@ unionIndex
| "symbol" | 4 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| "undefined" | 5 | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
| Error | 1 | Success \| Error |
+| Error | 1 | string \| Error |
| Json[] | 5 | string \| number \| boolean \| { [property: string... |
| Promise | 2 | boolean \| Promise |
| PromiseLike | 1 | TResult1 \| PromiseLike |
@@ -890,16 +1014,19 @@ unionIndex
| false | 0 | boolean |
| false | 0 | boolean \| Promise |
| false | 1 | number \| boolean |
+| false | 1 | number \| boolean \| "a" \| "b" |
| false | 2 | string \| number \| boolean |
| false | 2 | string \| number \| boolean \| { [property: string... |
| number | 0 | number \| "a" |
| number | 0 | number \| ValueOrArray[] |
| number | 0 | number \| boolean |
+| number | 0 | number \| boolean \| "a" \| "b" |
| number | 1 | string \| number |
| number | 1 | string \| number \| boolean |
| number | 1 | string \| number \| boolean \| { [property: string... |
| number | 1 | string \| number \| true |
| string | 0 | VirtualNode \| { [key: string]: any; } |
+| string | 0 | string \| Error |
| string | 0 | string \| [string, { [key: string]: any; }, ...V... |
| string | 0 | string \| number |
| string | 0 | string \| number \| boolean |
@@ -911,6 +1038,7 @@ unionIndex
| true | 1 | boolean |
| true | 1 | boolean \| Promise |
| true | 2 | number \| boolean |
+| true | 2 | number \| boolean \| "a" \| "b" |
| true | 2 | string \| number \| true |
| true | 3 | string \| number \| boolean |
| true | 3 | string \| number \| boolean \| { [property: string... |
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
index 9fdb0d950c4..8d67f28ad5d 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
@@ -293,4 +293,84 @@ module TS46 {
payload.toFixed(); // <- number
}
};
-}
\ No newline at end of file
+}
+
+function foo_47() {
+ const key = Symbol();
+
+ const numberOrString = Math.random() < 0.5 ? 42 : "hello";
+
+ let obj = {
+ [key]: numberOrString,
+ };
+
+ if (typeof obj[key] === "string") {
+ let str = obj[key]; // <- string
+ str.toUpperCase();
+ }
+
+ //////////
+
+ function f(arg: {
+ produce: (n: string) => T,
+ consume: (x: T) => void }
+ ): void {};
+
+ f({
+ produce: n => n, // <- (n: string) => string
+ consume: x => x.toLowerCase()
+ });
+
+ ///////////
+
+ const ErrorMap = Map;
+
+ const errorMap = new ErrorMap(); // <- Map
+
+ ////////////
+
+ type FirstString =
+ T extends [infer S extends string, ...unknown[]]
+ ? S
+ : never;
+
+ type F = FirstString<['a' | 'b', number, boolean]>;
+
+ const a: F = 'a'; // <- 'a' | 'b'
+
+ ////////////
+
+ interface State {
+ get: () => T;
+ set: (value: T) => void;
+ }
+
+ const state: State = {
+ get: () => 42,
+ set: (value) => { }
+ }
+
+ const fortyTwo = state.get(); // <- number
+
+ ////////////
+
+ // This does not compile as of 2022-05-19 with typescript@4.7.1-rc, but it might
+ // work with the actually released version:
+
+ // class Container {
+ // #data = "hello!";
+
+ // get data(): typeof this.#data {
+ // return this.#data;
+ // }
+
+ // set data(value: typeof this.#data) {
+ // this.#data = value;
+ // }
+ // }
+
+ // const c = new Container();
+
+ // const hello = c.data(); // <- string
+
+}
From 67697e106643972d6debadcb46e69b127096e38f Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Thu, 19 May 2022 15:10:22 +0200
Subject: [PATCH 054/125] update meta information and release note for
typescript 4.7 upgrade
---
docs/codeql/support/reusables/versions-compilers.rst | 2 +-
javascript/extractor/src/com/semmle/js/extractor/Main.java | 2 +-
javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md | 4 ++++
3 files changed, 6 insertions(+), 2 deletions(-)
create mode 100644 javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md
diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst
index a5f68cb64e1..bc175c4e711 100644
--- a/docs/codeql/support/reusables/versions-compilers.rst
+++ b/docs/codeql/support/reusables/versions-compilers.rst
@@ -23,7 +23,7 @@
JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py``
Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
- TypeScript [8]_,"2.6-4.6",Standard TypeScript compiler,"``.ts``, ``.tsx``"
+ TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``"
.. container:: footnote-group
diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java
index 5b425ab8af9..e5196ae1181 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/Main.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java
@@ -43,7 +43,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
- public static final String EXTRACTOR_VERSION = "2022-02-22";
+ public static final String EXTRACTOR_VERSION = "2022-05-24";
public static final Pattern NEWLINE = Pattern.compile("\n");
diff --git a/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md
new file mode 100644
index 00000000000..16fe46c675f
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-7.md
@@ -0,0 +1,4 @@
+---
+category: majorAnalysis
+---
+* Added support for TypeScript 4.7.
From a5b11e88b42d3b46ac84709a3bc31423176ee428 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Thu, 19 May 2022 20:00:43 +0200
Subject: [PATCH 055/125] update doc to make it clear that moduleImport(..)
does not refer to PyPI names
Co-authored-by: Rasmus Wriedt Larsen
---
python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll
index 1ced4d15ee9..2af91a69432 100644
--- a/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll
+++ b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll
@@ -5,7 +5,8 @@
* - Use the `ModelInput` module to contribute new models.
* - Use the `ModelOutput` module to access the model results in terms of API nodes.
*
- * The package name refers to a Pip package name.
+ * The package name refers to the top-level module the import comes from, and not a PyPI package.
+ * So for `from foo.bar import baz`, the package will be `foo`.
*/
private import python
From 204e01fc2438854ff44691eb461108ad364d25e8 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Thu, 19 May 2022 21:03:59 +0200
Subject: [PATCH 056/125] change getNumArgument to only count positional
arguments
---
python/ql/lib/semmle/python/ApiGraphs.qll | 2 +-
python/ql/test/library-tests/frameworks/data/test.expected | 3 ++-
python/ql/test/library-tests/frameworks/data/test.py | 4 ++--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll
index 33aabe35383..43bba85ba79 100644
--- a/python/ql/lib/semmle/python/ApiGraphs.qll
+++ b/python/ql/lib/semmle/python/ApiGraphs.qll
@@ -356,7 +356,7 @@ module API {
}
/** Gets the number of arguments of this call. Both positional and named arguments are counted. */
- int getNumArgument() { result = count([this.getArg(_), this.getArgByName(_)]) }
+ int getNumArgument() { result = count(this.getArg(_)) }
}
/**
diff --git a/python/ql/test/library-tests/frameworks/data/test.expected b/python/ql/test/library-tests/frameworks/data/test.expected
index 08300f4d905..fcf94bb784e 100644
--- a/python/ql/test/library-tests/frameworks/data/test.expected
+++ b/python/ql/test/library-tests/frameworks/data/test.expected
@@ -47,7 +47,8 @@ isSink
| test.py:86:8:86:60 | ControlFlowNode for Attribute() | test-sink |
| test.py:87:8:87:67 | ControlFlowNode for Attribute() | test-sink |
| test.py:89:21:89:23 | ControlFlowNode for one | test-sink |
-| test.py:90:25:90:27 | ControlFlowNode for one | test-sink |
+| test.py:91:21:91:23 | ControlFlowNode for one | test-sink |
+| test.py:91:30:91:32 | ControlFlowNode for two | test-sink |
| test.py:98:6:98:9 | ControlFlowNode for baz2 | test-sink |
isSource
| test.py:3:5:3:15 | ControlFlowNode for getSource() | test-source |
diff --git a/python/ql/test/library-tests/frameworks/data/test.py b/python/ql/test/library-tests/frameworks/data/test.py
index f01b613ce40..6ff4271dca2 100644
--- a/python/ql/test/library-tests/frameworks/data/test.py
+++ b/python/ql/test/library-tests/frameworks/data/test.py
@@ -87,8 +87,8 @@ mySink(Steps.preserveAllButFirstArgument("foo", getSource())) # FLOW
mySink(Steps.preserveAllButFirstArgument("foo", "bar", getSource())) # FLOW
CallFilter.arityOne(one) # match
-CallFilter.arityOne(one=one) # match
-CallFilter.arityOne(one, two=two) # NO match
+CallFilter.arityOne(one=one) # NO match
+CallFilter.arityOne(one, two=two) # match - on both the named and positional arguments
CallFilter.arityOne(one=one, two=two) # NO match
from foo1.bar import baz1
From 813fbf27de510cca61cd65edc6ec277be34fff54 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Fri, 20 May 2022 10:16:45 +0200
Subject: [PATCH 057/125] support for .mts and .cts file extensions
---
.../com/semmle/js/dependencies/Fetcher.java | 5 +-
.../semmle/js/extractor/FileExtractor.java | 2 +-
.../TypeScript/Types/tests.expected | 278 ++++++++++--------
.../library-tests/TypeScript/Types/tst.ts | 160 +++++-----
.../TypeScript/Types/tstModuleCJS.cts | 3 +
.../TypeScript/Types/tstModuleES.mts | 3 +
6 files changed, 255 insertions(+), 196 deletions(-)
create mode 100644 javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts
create mode 100644 javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts
diff --git a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
index fa996f1b34e..d094f05653d 100644
--- a/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
+++ b/javascript/extractor/src/com/semmle/js/dependencies/Fetcher.java
@@ -141,8 +141,9 @@ public class Fetcher {
entryPath = entryPath.subpath(1, entryPath.getNameCount());
String filename = entryPath.getFileName().toString();
- if (!filename.endsWith(".d.ts") && !filename.equals("package.json")) {
- continue; // Only extract .d.ts files and package.json
+ if (!filename.endsWith(".d.ts") && !filename.endsWith(".d.mts") && !filename.endsWith(".d.cts")
+ && !filename.equals("package.json")) {
+ continue; // Only extract .d.ts, .d.mts, .d.cts files, and package.json
}
relativePaths.add(entryPath);
Path outputFile = destDir.resolve(entryPath);
diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
index 1e9b7d6ad84..bc30d83690d 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java
@@ -203,7 +203,7 @@ public class FileExtractor {
}
},
- TYPESCRIPT(".ts", ".tsx") {
+ TYPESCRIPT(".ts", ".tsx", ".mts", ".cts") {
@Override
protected boolean contains(File f, String lcExt, ExtractorConfig config) {
if (config.getTypeScriptMode() == TypeScriptMode.NONE) return false;
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
index 1c6d0182dcb..9a0585b9436 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected
@@ -386,86 +386,122 @@ getExprType
| tst.ts:293:7:293:21 | payload.toFixed | (fractionDigits?: number) => string |
| tst.ts:293:7:293:23 | payload.toFixed() | string |
| tst.ts:293:15:293:21 | toFixed | (fractionDigits?: number) => string |
-| tst.ts:298:10:298:15 | foo_47 | () => void |
-| tst.ts:299:9:299:11 | key | typeof key |
-| tst.ts:299:15:299:20 | Symbol | SymbolConstructor |
-| tst.ts:299:15:299:22 | Symbol() | typeof key |
-| tst.ts:301:9:301:22 | numberOrString | "hello" \| 42 |
-| tst.ts:301:26:301:29 | Math | Math |
-| tst.ts:301:26:301:36 | Math.random | () => number |
-| tst.ts:301:26:301:38 | Math.random() | number |
-| tst.ts:301:26:301:44 | Math.random() < 0.5 | boolean |
-| tst.ts:301:26:301:59 | Math.ra ... "hello" | "hello" \| 42 |
-| tst.ts:301:31:301:36 | random | () => number |
-| tst.ts:301:42:301:44 | 0.5 | 0.5 |
-| tst.ts:301:48:301:49 | 42 | 42 |
-| tst.ts:301:53:301:59 | "hello" | "hello" |
-| tst.ts:303:7:303:9 | obj | { [key]: string \| number; } |
-| tst.ts:303:13:305:3 | {\\n [ ... ng,\\n } | { [key]: string \| number; } |
-| tst.ts:304:6:304:8 | key | typeof key |
-| tst.ts:304:12:304:25 | numberOrString | "hello" \| 42 |
-| tst.ts:307:7:307:21 | typeof obj[key] | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
-| tst.ts:307:7:307:34 | typeof ... string" | boolean |
-| tst.ts:307:14:307:16 | obj | { [key]: string \| number; } |
-| tst.ts:307:14:307:21 | obj[key] | string \| number |
-| tst.ts:307:18:307:20 | key | typeof key |
-| tst.ts:307:27:307:34 | "string" | "string" |
-| tst.ts:308:9:308:11 | str | string |
-| tst.ts:308:15:308:17 | obj | { [key]: string \| number; } |
-| tst.ts:308:15:308:22 | obj[key] | string |
-| tst.ts:308:19:308:21 | key | typeof key |
-| tst.ts:309:5:309:7 | str | string |
-| tst.ts:309:5:309:19 | str.toUpperCase | () => string |
-| tst.ts:309:5:309:21 | str.toUpperCase() | string |
-| tst.ts:309:9:309:19 | toUpperCase | () => string |
-| tst.ts:314:12:314:12 | f | (arg: { produce: (n: string) => T; consume: ... |
-| tst.ts:314:17:314:19 | arg | { produce: (n: string) => T; consume: (x: T) =>... |
-| tst.ts:315:5:315:11 | produce | (n: string) => T |
-| tst.ts:315:14:315:29 | (n: string) => T | (n: string) => T |
-| tst.ts:315:15:315:15 | n | string |
-| tst.ts:316:5:316:11 | consume | (x: T) => void |
-| tst.ts:316:14:316:27 | (x: T) => void | (x: T) => void |
-| tst.ts:316:15:316:15 | x | T |
-| tst.ts:319:3:319:3 | f | (arg: { produce: (n: string) => T; consume: ... |
-| tst.ts:319:3:322:4 | f({\\n ... ()\\n }) | void |
-| tst.ts:319:5:322:3 | {\\n p ... e()\\n } | { produce: (n: string) => string; consume: (x: ... |
-| tst.ts:320:5:320:11 | produce | (n: string) => string |
-| tst.ts:320:14:320:14 | n | string |
-| tst.ts:320:14:320:19 | n => n | (n: string) => string |
-| tst.ts:320:19:320:19 | n | string |
-| tst.ts:321:5:321:11 | consume | (x: string) => string |
-| tst.ts:321:14:321:14 | x | string |
-| tst.ts:321:14:321:33 | x => x.toLowerCase() | (x: string) => string |
-| tst.ts:321:19:321:19 | x | string |
-| tst.ts:321:19:321:31 | x.toLowerCase | () => string |
-| tst.ts:321:19:321:33 | x.toLowerCase() | string |
-| tst.ts:321:21:321:31 | toLowerCase | () => string |
-| tst.ts:326:9:326:16 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
-| tst.ts:326:20:326:22 | Map | MapConstructor |
-| tst.ts:326:20:326:37 | Map | any |
-| tst.ts:328:9:328:16 | errorMap | Map |
-| tst.ts:328:20:328:33 | new ErrorMap() | Map |
-| tst.ts:328:24:328:31 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
-| tst.ts:339:9:339:9 | a | "a" \| "b" |
-| tst.ts:339:16:339:18 | 'a' | "a" |
-| tst.ts:344:5:344:7 | get | () => T |
-| tst.ts:344:10:344:16 | () => T | () => T |
-| tst.ts:345:5:345:7 | set | (value: T) => void |
-| tst.ts:345:10:345:27 | (value: T) => void | (value: T) => void |
-| tst.ts:345:11:345:15 | value | T |
-| tst.ts:348:9:348:13 | state | State |
-| tst.ts:348:32:351:3 | {\\n g ... { }\\n } | State |
-| tst.ts:349:5:349:7 | get | () => number |
-| tst.ts:349:10:349:17 | () => 42 | () => number |
-| tst.ts:349:16:349:17 | 42 | 42 |
-| tst.ts:350:5:350:7 | set | (value: number) => void |
-| tst.ts:350:10:350:23 | (value) => { } | (value: number) => void |
-| tst.ts:350:11:350:15 | value | number |
-| tst.ts:353:9:353:16 | fortyTwo | number |
-| tst.ts:353:20:353:24 | state | State |
-| tst.ts:353:20:353:28 | state.get | () => number |
-| tst.ts:353:20:353:30 | state.get() | number |
-| tst.ts:353:26:353:28 | get | () => number |
+| tst.ts:298:7:298:9 | key | typeof key |
+| tst.ts:298:13:298:18 | Symbol | SymbolConstructor |
+| tst.ts:298:13:298:20 | Symbol() | typeof key |
+| tst.ts:300:7:300:20 | numberOrString | "hello" \| 42 |
+| tst.ts:300:24:300:27 | Math | Math |
+| tst.ts:300:24:300:34 | Math.random | () => number |
+| tst.ts:300:24:300:36 | Math.random() | number |
+| tst.ts:300:24:300:42 | Math.random() < 0.5 | boolean |
+| tst.ts:300:24:300:57 | Math.ra ... "hello" | "hello" \| 42 |
+| tst.ts:300:29:300:34 | random | () => number |
+| tst.ts:300:40:300:42 | 0.5 | 0.5 |
+| tst.ts:300:46:300:47 | 42 | 42 |
+| tst.ts:300:51:300:57 | "hello" | "hello" |
+| tst.ts:302:5:302:7 | obj | { [key]: string \| number; } |
+| tst.ts:302:11:304:1 | {\\n [ke ... ring,\\n} | { [key]: string \| number; } |
+| tst.ts:303:4:303:6 | key | typeof key |
+| tst.ts:303:10:303:23 | numberOrString | "hello" \| 42 |
+| tst.ts:306:5:306:19 | typeof obj[key] | "string" \| "number" \| "bigint" \| "boolean" \| "s... |
+| tst.ts:306:5:306:32 | typeof ... string" | boolean |
+| tst.ts:306:12:306:14 | obj | { [key]: string \| number; } |
+| tst.ts:306:12:306:19 | obj[key] | string \| number |
+| tst.ts:306:16:306:18 | key | typeof key |
+| tst.ts:306:25:306:32 | "string" | "string" |
+| tst.ts:307:7:307:9 | str | string |
+| tst.ts:307:13:307:15 | obj | { [key]: string \| number; } |
+| tst.ts:307:13:307:20 | obj[key] | string |
+| tst.ts:307:17:307:19 | key | typeof key |
+| tst.ts:308:3:308:5 | str | string |
+| tst.ts:308:3:308:17 | str.toUpperCase | () => string |
+| tst.ts:308:3:308:19 | str.toUpperCase() | string |
+| tst.ts:308:7:308:17 | toUpperCase | () => string |
+| tst.ts:313:10:313:10 | f | (arg: { produce: (n: string) => T; consume: ... |
+| tst.ts:313:15:313:17 | arg | { produce: (n: string) => T; consume: (x: T) =>... |
+| tst.ts:314:3:314:9 | produce | (n: string) => T |
+| tst.ts:314:12:314:27 | (n: string) => T | (n: string) => T |
+| tst.ts:314:13:314:13 | n | string |
+| tst.ts:315:3:315:9 | consume | (x: T) => void |
+| tst.ts:315:12:315:25 | (x: T) => void | (x: T) => void |
+| tst.ts:315:13:315:13 | x | T |
+| tst.ts:318:1:318:1 | f | (arg: { produce: (n: string) => T; consume: ... |
+| tst.ts:318:1:321:2 | f({\\n p ... se()\\n}) | void |
+| tst.ts:318:3:321:1 | {\\n pro ... ase()\\n} | { produce: (n: string) => string; consume: (x: ... |
+| tst.ts:319:3:319:9 | produce | (n: string) => string |
+| tst.ts:319:12:319:12 | n | string |
+| tst.ts:319:12:319:17 | n => n | (n: string) => string |
+| tst.ts:319:17:319:17 | n | string |
+| tst.ts:320:3:320:9 | consume | (x: string) => string |
+| tst.ts:320:12:320:12 | x | string |
+| tst.ts:320:12:320:31 | x => x.toLowerCase() | (x: string) => string |
+| tst.ts:320:17:320:17 | x | string |
+| tst.ts:320:17:320:29 | x.toLowerCase | () => string |
+| tst.ts:320:17:320:31 | x.toLowerCase() | string |
+| tst.ts:320:19:320:29 | toLowerCase | () => string |
+| tst.ts:325:7:325:14 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
+| tst.ts:325:18:325:20 | Map | MapConstructor |
+| tst.ts:325:18:325:35 | Map | any |
+| tst.ts:327:7:327:14 | errorMap | Map |
+| tst.ts:327:18:327:31 | new ErrorMap() | Map |
+| tst.ts:327:22:327:29 | ErrorMap | { new (entries?: readonly (readonly [string, Er... |
+| tst.ts:338:7:338:7 | a | "a" \| "b" |
+| tst.ts:338:14:338:16 | 'a' | "a" |
+| tst.ts:343:3:343:5 | get | () => T |
+| tst.ts:343:8:343:14 | () => T | () => T |
+| tst.ts:344:3:344:5 | set | (value: T) => void |
+| tst.ts:344:8:344:25 | (value: T) => void | (value: T) => void |
+| tst.ts:344:9:344:13 | value | T |
+| tst.ts:347:7:347:11 | state | State |
+| tst.ts:347:30:350:1 | {\\n get ... > { }\\n} | State |
+| tst.ts:348:3:348:5 | get | () => number |
+| tst.ts:348:8:348:15 | () => 42 | () => number |
+| tst.ts:348:14:348:15 | 42 | 42 |
+| tst.ts:349:3:349:5 | set | (value: number) => void |
+| tst.ts:349:8:349:21 | (value) => { } | (value: number) => void |
+| tst.ts:349:9:349:13 | value | number |
+| tst.ts:352:7:352:14 | fortyTwo | number |
+| tst.ts:352:18:352:22 | state | State |
+| tst.ts:352:18:352:26 | state.get | () => number |
+| tst.ts:352:18:352:28 | state.get() | number |
+| tst.ts:352:24:352:26 | get | () => number |
+| tst.ts:377:8:377:18 | tstModuleES | () => "a" \| "b" |
+| tst.ts:377:25:377:43 | './tstModuleES.mjs' | any |
+| tst.ts:379:1:379:7 | console | Console |
+| tst.ts:379:1:379:11 | console.log | (...data: any[]) => void |
+| tst.ts:379:1:379:26 | console ... leES()) | void |
+| tst.ts:379:9:379:11 | log | (...data: any[]) => void |
+| tst.ts:379:13:379:23 | tstModuleES | () => "a" \| "b" |
+| tst.ts:379:13:379:25 | tstModuleES() | "a" \| "b" |
+| tst.ts:381:10:381:21 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:381:10:381:21 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:381:30:381:49 | './tstModuleCJS.cjs' | any |
+| tst.ts:383:1:383:7 | console | Console |
+| tst.ts:383:1:383:11 | console.log | (...data: any[]) => void |
+| tst.ts:383:1:383:27 | console ... eCJS()) | void |
+| tst.ts:383:9:383:11 | log | (...data: any[]) => void |
+| tst.ts:383:13:383:24 | tstModuleCJS | () => "a" \| "b" |
+| tst.ts:383:13:383:26 | tstModuleCJS() | "a" \| "b" |
+| tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" |
+| tstModuleCJS.cts:2:12:2:15 | Math | Math |
+| tstModuleCJS.cts:2:12:2:22 | Math.random | () => number |
+| tstModuleCJS.cts:2:12:2:24 | Math.random() | number |
+| tstModuleCJS.cts:2:12:2:30 | Math.random() > 0.5 | boolean |
+| tstModuleCJS.cts:2:12:2:42 | Math.ra ... ' : 'b' | "a" \| "b" |
+| tstModuleCJS.cts:2:17:2:22 | random | () => number |
+| tstModuleCJS.cts:2:28:2:30 | 0.5 | 0.5 |
+| tstModuleCJS.cts:2:34:2:36 | 'a' | "a" |
+| tstModuleCJS.cts:2:40:2:42 | 'b' | "b" |
+| tstModuleES.mts:1:25:1:35 | tstModuleES | () => "a" \| "b" |
+| tstModuleES.mts:2:12:2:15 | Math | Math |
+| tstModuleES.mts:2:12:2:22 | Math.random | () => number |
+| tstModuleES.mts:2:12:2:24 | Math.random() | number |
+| tstModuleES.mts:2:12:2:30 | Math.random() > 0.5 | boolean |
+| tstModuleES.mts:2:12:2:42 | Math.ra ... ' : 'b' | "a" \| "b" |
+| tstModuleES.mts:2:17:2:22 | random | () => number |
+| tstModuleES.mts:2:28:2:30 | 0.5 | 0.5 |
+| tstModuleES.mts:2:34:2:36 | 'a' | "a" |
+| tstModuleES.mts:2:40:2:42 | 'b' | "b" |
| type_alias.ts:3:5:3:5 | b | boolean |
| type_alias.ts:7:5:7:5 | c | ValueOrArray |
| type_alias.ts:14:9:14:32 | [proper ... ]: Json | any |
@@ -541,9 +577,9 @@ getTypeDefinitionType
| tst.ts:265:3:269:3 | interfa ... an;\\n } | TypeMap |
| tst.ts:271:3:276:7 | type Un ... }[P]; | UnionRecord |
| tst.ts:289:3:289:63 | type Fu ... > void; | Func |
-| tst.ts:332:3:335:16 | type Fi ... never; | FirstString |
-| tst.ts:337:3:337:53 | type F ... lean]>; | "a" \| "b" |
-| tst.ts:343:3:346:3 | interfa ... id;\\n } | State |
+| tst.ts:331:1:334:14 | type Fi ... never; | FirstString |
+| tst.ts:336:1:336:51 | type F ... lean]>; | "a" \| "b" |
+| tst.ts:342:1:345:1 | interfa ... void;\\n} | State |
| type_alias.ts:1:1:1:17 | type B = boolean; | boolean |
| type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray |
| type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json |
@@ -786,39 +822,45 @@ getTypeExprType
| tst.ts:289:47:289:52 | string | string |
| tst.ts:289:59:289:62 | void | void |
| tst.ts:291:13:291:16 | Func | Func |
-| tst.ts:314:14:314:14 | T | T |
-| tst.ts:314:22:316:29 | {\\n p ... void } | { produce: (n: string) => T; consume: (x: T) =>... |
-| tst.ts:315:14:315:29 | (n: string) => T | (n: string) => T |
-| tst.ts:315:18:315:23 | string | string |
-| tst.ts:315:29:315:29 | T | T |
-| tst.ts:316:14:316:27 | (x: T) => void | (x: T) => void |
-| tst.ts:316:18:316:18 | T | T |
-| tst.ts:316:24:316:27 | void | void |
-| tst.ts:317:6:317:9 | void | void |
-| tst.ts:326:24:326:29 | string | string |
-| tst.ts:326:32:326:36 | Error | Error |
-| tst.ts:332:8:332:18 | FirstString | FirstString |
-| tst.ts:332:20:332:20 | T | T |
-| tst.ts:337:8:337:8 | F | "a" \| "b" |
-| tst.ts:337:12:337:22 | FirstString | FirstString |
-| tst.ts:337:12:337:52 | FirstSt ... olean]> | "a" \| "b" |
-| tst.ts:337:24:337:51 | ['a' \| ... oolean] | ["a" \| "b", number, boolean] |
-| tst.ts:337:25:337:27 | 'a' | "a" |
-| tst.ts:337:25:337:33 | 'a' \| 'b' | "a" \| "b" |
-| tst.ts:337:31:337:33 | 'b' | "b" |
-| tst.ts:337:36:337:41 | number | number |
-| tst.ts:337:44:337:50 | boolean | boolean |
-| tst.ts:339:12:339:12 | F | "a" \| "b" |
-| tst.ts:343:13:343:17 | State | State |
-| tst.ts:343:26:343:26 | T | T |
-| tst.ts:344:10:344:16 | () => T | () => T |
+| tst.ts:313:12:313:12 | T | T |
+| tst.ts:313:20:315:27 | {\\n pro ... void } | { produce: (n: string) => T; consume: (x: T) =>... |
+| tst.ts:314:12:314:27 | (n: string) => T | (n: string) => T |
+| tst.ts:314:16:314:21 | string | string |
+| tst.ts:314:27:314:27 | T | T |
+| tst.ts:315:12:315:25 | (x: T) => void | (x: T) => void |
+| tst.ts:315:16:315:16 | T | T |
+| tst.ts:315:22:315:25 | void | void |
+| tst.ts:316:4:316:7 | void | void |
+| tst.ts:325:22:325:27 | string | string |
+| tst.ts:325:30:325:34 | Error | Error |
+| tst.ts:331:6:331:16 | FirstString | FirstString |
+| tst.ts:331:18:331:18 | T | T |
+| tst.ts:336:6:336:6 | F | "a" \| "b" |
+| tst.ts:336:10:336:20 | FirstString | FirstString |
+| tst.ts:336:10:336:50 | FirstSt ... olean]> | "a" \| "b" |
+| tst.ts:336:22:336:49 | ['a' \| ... oolean] | ["a" \| "b", number, boolean] |
+| tst.ts:336:23:336:25 | 'a' | "a" |
+| tst.ts:336:23:336:31 | 'a' \| 'b' | "a" \| "b" |
+| tst.ts:336:29:336:31 | 'b' | "b" |
+| tst.ts:336:34:336:39 | number | number |
+| tst.ts:336:42:336:48 | boolean | boolean |
+| tst.ts:338:10:338:10 | F | "a" \| "b" |
+| tst.ts:342:11:342:15 | State | State |
+| tst.ts:342:24:342:24 | T | T |
+| tst.ts:343:8:343:14 | () => T | () => T |
+| tst.ts:343:14:343:14 | T | T |
+| tst.ts:344:8:344:25 | (value: T) => void | (value: T) => void |
| tst.ts:344:16:344:16 | T | T |
-| tst.ts:345:10:345:27 | (value: T) => void | (value: T) => void |
-| tst.ts:345:18:345:18 | T | T |
-| tst.ts:345:24:345:27 | void | void |
-| tst.ts:348:16:348:20 | State | State |
-| tst.ts:348:16:348:28 | State | State |
-| tst.ts:348:22:348:27 | number | number |
+| tst.ts:344:22:344:25 | void | void |
+| tst.ts:347:14:347:18 | State | State |
+| tst.ts:347:14:347:26 | State | State |
+| tst.ts:347:20:347:25 | number | number |
+| tstModuleCJS.cts:1:33:1:35 | 'a' | "a" |
+| tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" |
+| tstModuleCJS.cts:1:39:1:41 | 'b' | "b" |
+| tstModuleES.mts:1:40:1:42 | 'a' | "a" |
+| tstModuleES.mts:1:40:1:48 | 'a' \| 'b' | "a" \| "b" |
+| tstModuleES.mts:1:46:1:48 | 'b' | "b" |
| type_alias.ts:1:6:1:6 | B | boolean |
| type_alias.ts:1:10:1:16 | boolean | boolean |
| type_alias.ts:3:8:3:8 | B | boolean |
@@ -899,7 +941,7 @@ referenceDefinition
| E | type_definition_objects.ts:6:8:6:16 | enum E {} |
| EnumWithOneMember | type_definitions.ts:18:26:18:31 | member |
| Error | tst.ts:210:10:213:3 | interfa ... ng;\\n } |
-| FirstString | tst.ts:332:3:335:16 | type Fi ... never; |
+| FirstString | tst.ts:331:1:334:14 | type Fi ... never; |
| Foo | tst.ts:116:3:129:3 | class F ... }\\n } |
| Foo | tst.ts:165:5:167:5 | interfa ... ;\\n } |
| Foo | tst.ts:179:3:192:3 | class F ... \\n } |
@@ -913,8 +955,8 @@ referenceDefinition
| NonAbstractDummy | tst.ts:54:1:56:1 | interfa ... mber;\\n} |
| Person | tst.ts:222:3:234:3 | class P ... }\\n } |
| Shape | tst.ts:140:3:142:47 | type Sh ... mber }; |
-| State | tst.ts:343:3:346:3 | interfa ... id;\\n } |
-| State | tst.ts:343:3:346:3 | interfa ... id;\\n } |
+| State | tst.ts:342:1:345:1 | interfa ... void;\\n} |
+| State | tst.ts:342:1:345:1 | interfa ... void;\\n} |
| Sub | tst.ts:97:3:101:3 | class S ... }\\n } |
| Success | tst.ts:205:10:208:3 | interfa ... ng;\\n } |
| Super | tst.ts:91:3:95:3 | class S ... }\\n } |
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
index 8d67f28ad5d..278c8e08bac 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
@@ -295,82 +295,92 @@ module TS46 {
};
}
-function foo_47() {
- const key = Symbol();
+const key = Symbol();
- const numberOrString = Math.random() < 0.5 ? 42 : "hello";
+const numberOrString = Math.random() < 0.5 ? 42 : "hello";
- let obj = {
- [key]: numberOrString,
- };
-
- if (typeof obj[key] === "string") {
- let str = obj[key]; // <- string
- str.toUpperCase();
- }
-
- //////////
-
- function f(arg: {
- produce: (n: string) => T,
- consume: (x: T) => void }
- ): void {};
-
- f({
- produce: n => n, // <- (n: string) => string
- consume: x => x.toLowerCase()
- });
-
- ///////////
-
- const ErrorMap = Map;
-
- const errorMap = new ErrorMap(); // <- Map
-
- ////////////
-
- type FirstString =
- T extends [infer S extends string, ...unknown[]]
- ? S
- : never;
-
- type F = FirstString<['a' | 'b', number, boolean]>;
-
- const a: F = 'a'; // <- 'a' | 'b'
-
- ////////////
-
- interface State {
- get: () => T;
- set: (value: T) => void;
- }
-
- const state: State = {
- get: () => 42,
- set: (value) => { }
- }
-
- const fortyTwo = state.get(); // <- number
-
- ////////////
-
- // This does not compile as of 2022-05-19 with typescript@4.7.1-rc, but it might
- // work with the actually released version:
-
- // class Container {
- // #data = "hello!";
-
- // get data(): typeof this.#data {
- // return this.#data;
- // }
-
- // set data(value: typeof this.#data) {
- // this.#data = value;
- // }
- // }
-
- // const c = new Container();
-
- // const hello = c.data(); // <- string
+let obj = {
+ [key]: numberOrString,
+};
+if (typeof obj[key] === "string") {
+ let str = obj[key]; // <- string
+ str.toUpperCase();
}
+
+//////////
+
+function f(arg: {
+ produce: (n: string) => T,
+ consume: (x: T) => void }
+): void {};
+
+f({
+ produce: n => n, // <- (n: string) => string
+ consume: x => x.toLowerCase()
+});
+
+///////////
+
+const ErrorMap = Map;
+
+const errorMap = new ErrorMap(); // <- Map
+
+////////////
+
+type FirstString =
+ T extends [infer S extends string, ...unknown[]]
+ ? S
+ : never;
+
+type F = FirstString<['a' | 'b', number, boolean]>;
+
+const a: F = 'a'; // <- 'a' | 'b'
+
+////////////
+
+interface State {
+ get: () => T;
+ set: (value: T) => void;
+}
+
+const state: State = {
+ get: () => 42,
+ set: (value) => { }
+}
+
+const fortyTwo = state.get(); // <- number
+
+////////////
+
+// This does not compile as of 2022-05-19 with typescript@4.7.1-rc, but it might
+// work with the actually released version:
+
+// class Container {
+// #data = "hello!";
+
+// get data(): typeof this.#data {
+// return this.#data;
+// }
+
+// set data(value: typeof this.#data) {
+// this.#data = value;
+// }
+// }
+
+// const c = new Container();
+
+// const hello = c.data(); // <- string
+
+/////////////////
+
+import tstModuleES from './tstModuleES.mjs';
+
+console.log(tstModuleES());
+
+import { tstModuleCJS } from './tstModuleCJS.cjs';
+
+console.log(tstModuleCJS());
+
+/////////////////
+
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts
new file mode 100644
index 00000000000..c764c1e1243
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleCJS.cts
@@ -0,0 +1,3 @@
+export function tstModuleCJS(): 'a' | 'b' {
+ return Math.random() > 0.5 ? 'a' : 'b';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts
new file mode 100644
index 00000000000..cf735d1bb49
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstModuleES.mts
@@ -0,0 +1,3 @@
+export default function tstModuleES(): 'a' | 'b' {
+ return Math.random() > 0.5 ? 'a' : 'b';
+}
From cb4b2e983b7dbf4ef322bc8774bb1b6bcf8f68b0 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Fri, 20 May 2022 14:33:07 +0200
Subject: [PATCH 058/125] delete test of removed feature
---
.../library-tests/TypeScript/Types/tst.ts | 21 -------------------
1 file changed, 21 deletions(-)
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
index 278c8e08bac..aa6024ad088 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
@@ -351,27 +351,6 @@ const state: State = {
const fortyTwo = state.get(); // <- number
-////////////
-
-// This does not compile as of 2022-05-19 with typescript@4.7.1-rc, but it might
-// work with the actually released version:
-
-// class Container {
-// #data = "hello!";
-
-// get data(): typeof this.#data {
-// return this.#data;
-// }
-
-// set data(value: typeof this.#data) {
-// this.#data = value;
-// }
-// }
-
-// const c = new Container();
-
-// const hello = c.data(); // <- string
-
/////////////////
import tstModuleES from './tstModuleES.mjs';
From d6abb2e6bd83e46392001dac143b6473af9e55f7 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Fri, 20 May 2022 14:34:53 +0200
Subject: [PATCH 059/125] add new supported file types to
versions-compilers.rst
Co-authored-by: Erik Krogh Kristensen
---
docs/codeql/support/reusables/versions-compilers.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst
index bc175c4e711..c524b16d459 100644
--- a/docs/codeql/support/reusables/versions-compilers.rst
+++ b/docs/codeql/support/reusables/versions-compilers.rst
@@ -23,7 +23,7 @@
JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py``
Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
- TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``"
+ TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group
From cdceb66b07ededc3ad65b83e4edc3987e5794175 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Fri, 20 May 2022 15:09:37 +0200
Subject: [PATCH 060/125] add test for moduleSuffixes
---
.../test/library-tests/TypeScript/Types/tsconfig.json | 3 ++-
.../ql/test/library-tests/TypeScript/Types/tst.ts | 10 ++++++++++
.../test/library-tests/TypeScript/Types/tstSuffixA.ts | 3 +++
.../library-tests/TypeScript/Types/tstSuffixB.ios.ts | 3 +++
.../test/library-tests/TypeScript/Types/tstSuffixB.ts | 3 +++
5 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts
create mode 100644 javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts
create mode 100644 javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json b/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
index f6aa3a1e752..2235cec7f7d 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tsconfig.json
@@ -3,6 +3,7 @@
"module": "esnext",
"target": "esnext",
"lib": ["dom", "esnext"],
- "resolveJsonModule": true
+ "resolveJsonModule": true,
+ "moduleSuffixes": [".ios", ""]
}
}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
index aa6024ad088..ed8787112d3 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts
@@ -363,3 +363,13 @@ console.log(tstModuleCJS());
/////////////////
+// test file resolution order (see tsconfig: moduleSuffixes setting)
+
+import * as A from './tstSuffixA';
+
+console.log(A.resolvedFile()); // <- 'tstSuffixA.ts'
+
+import * as B from './tstSuffixB';
+
+console.log(B.resolvedFile()); // <- 'tstSuffixB.ios.ts'
+
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts
new file mode 100644
index 00000000000..ffe0b811492
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixA.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixA.ts' {
+ return 'tstSuffixA.ts';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts
new file mode 100644
index 00000000000..04463fc7699
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ios.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixB.ios.ts' {
+ return 'tstSuffixB.ios.ts';
+}
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts
new file mode 100644
index 00000000000..cdb26f8f614
--- /dev/null
+++ b/javascript/ql/test/library-tests/TypeScript/Types/tstSuffixB.ts
@@ -0,0 +1,3 @@
+export function resolvedFile(): 'tstSuffixB.ts' {
+ return 'tstSuffixB.ts';
+}
From b6a4f4373730722f6f23cbd77cfb9478439b05bb Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Mon, 23 May 2022 18:51:33 +0200
Subject: [PATCH 061/125] expand qldoc for `getNumArgument`
Co-authored-by: Rasmus Wriedt Larsen
---
python/ql/lib/semmle/python/ApiGraphs.qll | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll
index 43bba85ba79..11ad08f1341 100644
--- a/python/ql/lib/semmle/python/ApiGraphs.qll
+++ b/python/ql/lib/semmle/python/ApiGraphs.qll
@@ -355,7 +355,12 @@ module API {
result.getAnImmediateUse() = this
}
- /** Gets the number of arguments of this call. Both positional and named arguments are counted. */
+ /**
+ * Gets the number of positional arguments of this call.
+ *
+ * Note: This is used for `WithArity[]` in modeling-as-data, where we thought
+ * including keyword arguments didn't make much sense.
+ */
int getNumArgument() { result = count(this.getArg(_)) }
}
From f8281b43b16fd47909e1c6b66cda463b4b3ab28d Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Mon, 23 May 2022 19:58:48 +0200
Subject: [PATCH 062/125] autoformat
---
python/ql/lib/semmle/python/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll
index 11ad08f1341..fcb89e5f866 100644
--- a/python/ql/lib/semmle/python/ApiGraphs.qll
+++ b/python/ql/lib/semmle/python/ApiGraphs.qll
@@ -358,7 +358,7 @@ module API {
/**
* Gets the number of positional arguments of this call.
*
- * Note: This is used for `WithArity[]` in modeling-as-data, where we thought
+ * Note: This is used for `WithArity[]` in modeling-as-data, where we thought
* including keyword arguments didn't make much sense.
*/
int getNumArgument() { result = count(this.getArg(_)) }
From 6a12864dab7d40cb32150cf9130c4a1f30638d78 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 29 Mar 2022 14:08:57 +0200
Subject: [PATCH 063/125] JS: Document how API graphs should be interpreted
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 112 ++++++++++++++++--
1 file changed, 104 insertions(+), 8 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 51101e3182a..9aef10a64e4 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -2,11 +2,7 @@
* Provides an implementation of _API graphs_, which are an abstract representation of the API
* surface used and/or defined by a code base.
*
- * The nodes of the API graph represent definitions and uses of API components. The edges are
- * directed and labeled; they specify how the components represented by nodes relate to each other.
- * For example, if one of the nodes represents a definition of an API function, then there
- * will be nodes corresponding to the function's parameters, which are connected to the function
- * node by edges labeled `parameter `.
+ * See `API::Node` for more in-depth documentation.
*/
import javascript
@@ -14,12 +10,112 @@ private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
private import internal.CachedStages
/**
- * Provides classes and predicates for working with APIs defined or used in a database.
+ * Provides classes and predicates for working with the API boundary between the current
+ * codebase and external libraries.
+ *
+ * See `API::Node` for more in-depth documentation.
*/
module API {
/**
- * An abstract representation of a definition or use of an API component such as a function
- * exported by an npm package, a parameter of such a function, or its result.
+ * A node in the API graph, representing a value that has crossed the boundary between this
+ * codebase and an external library.
+ *
+ * ### Basic usage
+ *
+ * API graphs are typically used to identify "API calls", that is, calls to an external function
+ * whose implementation is not necessarily part of the current codebase.
+ *
+ * The most basic use of API graphs is typically as follows:
+ * 1. Start with `API::moduleImport` for the relevant library.
+ * 2. Follow up with a chain of accessors such as `getMember` describing how to get to the relevant API function.
+ * 3. Map the resulting API graph nodes to data-flow nodes, using `getAnImmediateUse` or `getARhs`.
+ *
+ * For example, a simplified way to get arguments to `underscore.extend` would be
+ * ```codeql
+ * API::moduleImport("underscore").getMember("extend").getParameter(0).getARhs()
+ * ```
+ *
+ * The most commonly used accessors are `getMember`, `getParameter`, and `getReturn`.
+ *
+ * ### API graph nodes
+ *
+ * There are two kinds of nodes in the API graphs, distinguished by who is "holding" the value:
+ * - **Use-nodes** represent values held by the current codebase, which came from an external library.
+ * (The current codebase is "using" a value that came from the library).
+ * - **Def-nodes** represent values held by the external library, which came from this codebase.
+ * (The current codebase "defines" the value seen by the library).
+ *
+ * API graph nodes are associated with data-flow nodes in the current codebase.
+ * (Since external libraries are not part of the database, there is no way to associate with concrete
+ * data-flow nodes from the external library).
+ * - **Use-nodes** are associated with data-flow nodes where a value enters the current codebase,
+ * such as the return value of a call to an external function.
+ * - **Def-nodes** are associated with data-flow nodes where a value leaves the current codebase,
+ * such as an argument passed in a call to an external function.
+ *
+ *
+ * ### Access paths and edge labels
+ *
+ * Nodes in the API graph nodes are associated with a set of access paths, describing a series of operations
+ * that may be performed to obtain that value.
+ *
+ * For example, the access path `API::moduleImport("lodash").getMember("extend")` represents the action of
+ * importing `lodash` and then accessing the member `extend` on the resulting object.
+ * It would be associated with an expression such as `require("lodash").extend`.
+ *
+ * Each edge in the graph is labelled by such an "operation". For an edge `A->B`, the type of the `A` node
+ * determines who is performing the operation, and the type of the `B` node determines who ends up holding
+ * the result:
+ * - An edge starting from a use-node describes what the current codebase is doing to a value that
+ * came from a library.
+ * - An edge starting from a def-node describes what the external library might do to a value that
+ * came from the current codebase.
+ * - An edge ending in a use-node means the result ends up in the current codebase (at its associated data-flow node).
+ * - An edge ending in a def-node means the result ends up in external code (its associated data-flow node is
+ * the place where it was "last seen" in the current codebase before flowing out)
+ *
+ * Because the implementation of the external library is not visible, it is not known exactly what operations
+ * it will perform on values that flow there. Instead, the edges starting from a def-node are operations that would
+ * lead to an observable effect within the current codebase; without knowing for certain if the library will actually perform
+ * those operations. (When constructing these edge, we assume the library is somewhat well-behaved).
+ *
+ * For example, given this snippet:
+ * ```js
+ * require('foo')(x => { doSomething(x) })
+ * ```
+ * A callback is passed to the external function `foo`. We can't know if `foo` will actually invoke this callback.
+ * But _if_ the library should decide to invoke the callback, then a value will flow into the current codebase via the `x` parameter.
+ * For that reason, an edge is generated representing the argument-passing operation that might be performed by `foo`.
+ * This edge is going from the def-node associated with the callback to the use-node associated with the parameter `x`.
+ *
+ * ### Thinking in operations versus code patterns
+ *
+ * Treating edges as "operations" helps avoid a pitfall in which library models become overly specific to certain code patterns.
+ * Consider the following two equivalent calls to `foo`:
+ * ```js
+ * const foo = require('foo');
+ *
+ * foo({
+ * myMethod(x) {...}
+ * });
+ *
+ * foo({
+ * get myMethod() {
+ * return function(x) {...}
+ * }
+ * });
+ * ```
+ * If `foo` calls `myMethod` on its first parameter, either of the `myMethod` implementations will be invoked.
+ * An indeed, the access path `API::moduleImport("foo").getParameter(0).getMember("myMethod").getParameter(0)` correctly
+ * identifies both `x` parameters.
+ *
+ * Observe how `getMember("myMethod")` behaves when the member is defined via a getter. When thinking in code patterns,
+ * it might seem obvious that `getMember` should have obtained a reference the getter method itself.
+ * But when seeing it as an access to `myMethod` performed by the library, we can deduce that the relevant expression
+ * on the client side is actually the return-value of the getter.
+ *
+ * Although one may think of API graphs as a tool to find certain program elements in the codebase,
+ * it can lead to some situations where intuition does not match what works best in practice.
*/
class Node extends Impl::TApiNode {
/**
From 82c35e6f659b33aa436d28dfedce891c8d812ea1 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Wed, 30 Mar 2022 16:01:53 +0200
Subject: [PATCH 064/125] Mention that the interaction and be with any external
codebase
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 9aef10a64e4..654b62dd26b 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -18,7 +18,7 @@ private import internal.CachedStages
module API {
/**
* A node in the API graph, representing a value that has crossed the boundary between this
- * codebase and an external library.
+ * codebase and an external library (or in general, any external codebase).
*
* ### Basic usage
*
From 73baa49c5d69b4cb1ef78805a162ff7e7492e02d Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 30 Mar 2022 14:15:42 +0200
Subject: [PATCH 065/125] Update
javascript/ql/lib/semmle/javascript/ApiGraphs.qll
Co-authored-by: yoff
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 654b62dd26b..79aa8a2ee5c 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -110,7 +110,7 @@ module API {
* identifies both `x` parameters.
*
* Observe how `getMember("myMethod")` behaves when the member is defined via a getter. When thinking in code patterns,
- * it might seem obvious that `getMember` should have obtained a reference the getter method itself.
+ * it might seem obvious that `getMember` should have obtained a reference to the getter method itself.
* But when seeing it as an access to `myMethod` performed by the library, we can deduce that the relevant expression
* on the client side is actually the return-value of the getter.
*
From a7b73f44b2b5a65f093cc2a830605b7e37117ca9 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 30 Mar 2022 15:59:47 +0200
Subject: [PATCH 066/125] Update
javascript/ql/lib/semmle/javascript/ApiGraphs.qll
Co-authored-by: Calum Grant <42069085+calumgrant@users.noreply.github.com>
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 79aa8a2ee5c..89135485152 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -106,7 +106,7 @@ module API {
* });
* ```
* If `foo` calls `myMethod` on its first parameter, either of the `myMethod` implementations will be invoked.
- * An indeed, the access path `API::moduleImport("foo").getParameter(0).getMember("myMethod").getParameter(0)` correctly
+ * And indeed, the access path `API::moduleImport("foo").getParameter(0).getMember("myMethod").getParameter(0)` correctly
* identifies both `x` parameters.
*
* Observe how `getMember("myMethod")` behaves when the member is defined via a getter. When thinking in code patterns,
From 4c6192670efaaba9ecc9a9ac4d22df1062d6195d Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:17:35 +0200
Subject: [PATCH 067/125] JS: Rename getAnImmediateUse -> getASource
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 61 +++++++++++--------
.../ql/lib/semmle/javascript/JsonParsers.qll | 2 +-
.../ql/lib/semmle/javascript/JsonSchema.qll | 2 +-
.../semmle/javascript/JsonStringifiers.qll | 2 +-
.../semmle/javascript/frameworks/Babel.qll | 2 +-
.../semmle/javascript/frameworks/Cheerio.qll | 2 +-
.../javascript/frameworks/ClassValidator.qll | 2 +-
.../javascript/frameworks/ClientRequests.qll | 4 +-
.../lib/semmle/javascript/frameworks/D3.qll | 6 +-
.../semmle/javascript/frameworks/Electron.qll | 4 +-
.../semmle/javascript/frameworks/Files.qll | 12 ++--
.../javascript/frameworks/FormParsers.qll | 6 +-
.../semmle/javascript/frameworks/History.qll | 6 +-
.../lib/semmle/javascript/frameworks/Knex.qll | 2 +-
.../javascript/frameworks/LiveServer.qll | 2 +-
.../semmle/javascript/frameworks/Logging.qll | 2 +-
.../lib/semmle/javascript/frameworks/Nest.qll | 14 ++---
.../lib/semmle/javascript/frameworks/Next.qll | 2 +-
.../javascript/frameworks/NodeJSLib.qll | 2 +-
.../semmle/javascript/frameworks/Prettier.qll | 2 +-
.../semmle/javascript/frameworks/Redux.qll | 28 ++++-----
.../lib/semmle/javascript/frameworks/SQL.qll | 4 +-
.../javascript/frameworks/Snapdragon.qll | 4 +-
.../semmle/javascript/frameworks/SocketIO.qll | 8 +--
.../javascript/frameworks/Templating.qll | 2 +-
.../frameworks/TorrentLibraries.qll | 6 +-
.../javascript/frameworks/UriLibraries.qll | 2 +-
.../lib/semmle/javascript/frameworks/Vue.qll | 18 +++---
.../lib/semmle/javascript/frameworks/Vuex.qll | 16 ++---
.../javascript/frameworks/XmlParsers.qll | 4 +-
.../frameworks/data/ModelsAsData.qll | 4 +-
.../heuristics/AdditionalSources.qll | 2 +-
.../dataflow/DomBasedXssCustomizations.qll | 2 +-
.../dataflow/ExceptionXssCustomizations.qll | 2 +-
...APIUsedWithUntrustedDataCustomizations.qll | 4 +-
...IndirectCommandInjectionCustomizations.qll | 2 +-
.../security/dataflow/MissingRateLimiting.qll | 6 +-
.../security/dataflow/RemoteFlowSources.qll | 2 +-
.../dataflow/XssThroughDomCustomizations.qll | 2 +-
.../dataflow/ZipSlipCustomizations.qll | 4 +-
.../ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql | 2 +-
.../ql/test/ApiGraphs/VerifyAssertions.qll | 2 +-
.../ql/test/ApiGraphs/typed/NodeOfType.ql | 2 +-
.../ql/test/library-tests/Routing/test.ql | 2 +-
.../frameworks/Express/MiddlewareFlow.qll | 2 +-
.../library-tests/frameworks/data/test.ql | 2 +-
46 files changed, 141 insertions(+), 130 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 89135485152..c4f2feaab67 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -119,41 +119,52 @@ module API {
*/
class Node extends Impl::TApiNode {
/**
- * Gets a data-flow node corresponding to a use of the API component represented by this node.
+ * Get a data-flow node where this value may flow after entering the current codebase.
*
- * For example, `require('fs').readFileSync` is a use of the function `readFileSync` from the
- * `fs` module, and `require('fs').readFileSync(file)` is a use of the return of that function.
- *
- * This includes indirect uses found via data flow, meaning that in
- * `f(obj.foo); function f(x) {};` both `obj.foo` and `x` are uses of the `foo` member from `obj`.
- *
- * As another example, in the assignment `exports.plusOne = (x) => x+1` the two references to
- * `x` are uses of the first parameter of `plusOne`.
+ * This is similar to `getASource()` but additionally includes nodes that are transitively reachable by data flow.
+ * See `getASource()` for examples.
*/
pragma[inline]
- DataFlow::Node getAUse() {
+ DataFlow::Node getAValueReachableFromSource() {
exists(DataFlow::SourceNode src | Impl::use(this, src) |
Impl::trackUseNode(src).flowsTo(result)
)
}
/**
- * Gets an immediate use of the API component represented by this node.
+ * Get a data-flow node where this value enters the current codebase.
*
- * For example, `require('fs').readFileSync` is a an immediate use of the `readFileSync` member
- * from the `fs` module.
+ * For example:
+ * ```js
+ * // API::moduleImport("fs").getASource()
+ * require('fs');
*
- * Unlike `getAUse()`, this predicate only gets the immediate references, not the indirect uses
- * found via data flow. This means that in `const x = fs.readFile` only `fs.readFile` is a reference
- * to the `readFile` member of `fs`, neither `x` nor any node that `x` flows to is a reference to
- * this API component.
+ * // API::moduleImport("fs").getMember("readFile").getASource()
+ * require('fs').readFile;
+ *
+ * // API::moduleImport("fs").getMember("readFile").getReturn().getASource()
+ * require('fs').readFile();
+ *
+ * require('fs').readFile(
+ * filename,
+ * // 'y' matched by API::moduleImport("fs").getMember("readFile").getParameter(1).getParameter(0).getASource()
+ * y => {
+ * ...
+ * });
+ * ```
*/
- DataFlow::SourceNode getAnImmediateUse() { Impl::use(this, result) }
+ DataFlow::SourceNode getASource() { Impl::use(this, result) }
+
+ /** DEPRECATED. This predicate has been renamed to `getASource`. */
+ deprecated DataFlow::SourceNode getAnImmediateUse() { result = this.getASource() }
+
+ /** DEPRECATED. This predicate has been renamed to `getAValueReachableFromSource`. */
+ deprecated DataFlow::Node getAUse() { result = this.getAValueReachableFromSource() }
/**
* Gets a call to the function represented by this API component.
*/
- CallNode getACall() { result = this.getReturn().getAnImmediateUse() }
+ CallNode getACall() { result = this.getReturn().getASource() }
/**
* Gets a call to the function represented by this API component,
@@ -168,7 +179,7 @@ module API {
/**
* Gets a `new` call to the function represented by this API component.
*/
- NewNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
+ NewNode getAnInstantiation() { result = this.getInstance().getASource() }
/**
* Gets an invocation (with our without `new`) to the function represented by this API component.
@@ -430,7 +441,7 @@ module API {
* In other words, the value of a use of `that` may flow into the right-hand side of a
* definition of this node.
*/
- predicate refersTo(Node that) { this.getARhs() = that.getAUse() }
+ predicate refersTo(Node that) { this.getARhs() = that.getAValueReachableFromSource() }
/**
* Gets the data-flow node that gives rise to this node, if any.
@@ -1274,8 +1285,8 @@ module API {
API::Node callee;
InvokeNode() {
- this = callee.getReturn().getAnImmediateUse() or
- this = callee.getInstance().getAnImmediateUse() or
+ this = callee.getReturn().getASource() or
+ this = callee.getInstance().getASource() or
this = Impl::getAPromisifiedInvocation(callee, _, _)
}
@@ -1301,13 +1312,13 @@ module API {
/** Gets the API node for the return value of this call. */
Node getReturn() {
result = callee.getReturn() and
- result.getAnImmediateUse() = this
+ result.getASource() = this
}
/** Gets the API node for the object constructed by this invocation. */
Node getInstance() {
result = callee.getInstance() and
- result.getAnImmediateUse() = this
+ result.getASource() = this
}
}
diff --git a/javascript/ql/lib/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
index 35a227c3ad8..cd4a104679f 100644
--- a/javascript/ql/lib/semmle/javascript/JsonParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
@@ -29,7 +29,7 @@ private class PlainJsonParserCall extends JsonParserCall {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"parse") or
- callee = API::moduleImport("replicator").getInstance().getMember("decode").getAnImmediateUse() or
+ callee = API::moduleImport("replicator").getInstance().getMember("decode").getASource() or
callee = DataFlow::moduleImport("parse-json") or
callee = DataFlow::moduleImport("json-parse-better-errors") or
callee = DataFlow::moduleImport("json-safe-parse") or
diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
index bf45bcdd7b4..b108bde91f6 100644
--- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
@@ -184,7 +184,7 @@ module JsonSchema {
override boolean getPolarity() { none() }
override DataFlow::Node getAValidationResultAccess(boolean polarity) {
- result = this.getReturn().getMember("error").getAnImmediateUse() and
+ result = this.getReturn().getMember("error").getASource() and
polarity = false
}
}
diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
index 03ca152471f..fc6d1dfe1f5 100644
--- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
@@ -14,7 +14,7 @@ class JsonStringifyCall extends DataFlow::CallNode {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"stringify") or
- callee = API::moduleImport("replicator").getInstance().getMember("encode").getAnImmediateUse() or
+ callee = API::moduleImport("replicator").getInstance().getMember("encode").getASource() or
callee =
DataFlow::moduleImport([
"json-stringify-safe", "json-stable-stringify", "stringify-object",
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
index 3d061eb2aef..2134a84fb10 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
@@ -198,7 +198,7 @@ module Babel {
.getMember(["transform", "transformSync", "transformAsync"])
.getACall() and
pred = call.getArgument(0) and
- succ = [call, call.getParameter(2).getParameter(0).getAnImmediateUse()]
+ succ = [call, call.getParameter(2).getParameter(0).getASource()]
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
index 7c8e4a040a4..fdc820861b1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll
@@ -14,7 +14,7 @@ module Cheerio {
}
/** Gets a reference to the `cheerio` function, possibly with a loaded DOM. */
- DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAUse() }
+ DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAValueReachableFromSource() }
/**
* A creation of `cheerio` object, a collection of virtual DOM elements
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
index 381451c393c..cff8da8aaf8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
@@ -39,7 +39,7 @@ module ClassValidator {
/** Holds if the given field has a decorator that sanitizes its value for the purpose of taint tracking. */
predicate isFieldSanitizedByDecorator(FieldDefinition field) {
- field.getADecorator().getExpression().flow() = sanitizingDecorator().getReturn().getAUse()
+ field.getADecorator().getExpression().flow() = sanitizingDecorator().getReturn().getAValueReachableFromSource()
}
pragma[noinline]
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
index e86af94463f..b9054fdee41 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
@@ -265,7 +265,7 @@ module ClientRequest {
or
responseType = this.getResponseType() and
promise = false and
- result = this.getReturn().getPromisedError().getMember("response").getAnImmediateUse()
+ result = this.getReturn().getPromisedError().getMember("response").getASource()
}
}
@@ -463,7 +463,7 @@ module ClientRequest {
*/
private API::Node netSocketInstantiation(DataFlow::NewNode socket) {
result = API::moduleImport("net").getMember("Socket").getInstance() and
- socket = result.getAnImmediateUse()
+ socket = result.getASource()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index 1dda09dedb8..d8478002fc2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -78,11 +78,11 @@ module D3 {
private class D3DomValueSource extends DOM::DomValueSource::Range {
D3DomValueSource() {
- this = d3Selection().getMember("each").getReceiver().getAnImmediateUse()
+ this = d3Selection().getMember("each").getReceiver().getASource()
or
- this = d3Selection().getMember("node").getReturn().getAnImmediateUse()
+ this = d3Selection().getMember("node").getReturn().getASource()
or
- this = d3Selection().getMember("nodes").getReturn().getUnknownMember().getAnImmediateUse()
+ this = d3Selection().getMember("nodes").getReturn().getUnknownMember().getASource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
index 1b3ee3dfea5..f0ab6a75bc5 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
@@ -56,13 +56,13 @@ module Electron {
}
}
- private API::Node browserObject() { result.getAnImmediateUse() instanceof NewBrowserObject }
+ private API::Node browserObject() { result.getASource() instanceof NewBrowserObject }
/**
* A data flow node whose value may originate from a browser object instantiation.
*/
private class BrowserObjectByFlow extends BrowserObject {
- BrowserObjectByFlow() { browserObject().getAUse() = this }
+ BrowserObjectByFlow() { browserObject().getAValueReachableFromSource() = this }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
index 0bad9367b7f..8420ade8039 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
@@ -89,7 +89,7 @@ private API::Node globbyFileNameSource() {
* A file name or an array of file names from the `globby` library.
*/
private class GlobbyFileNameSource extends FileNameSource {
- GlobbyFileNameSource() { this = globbyFileNameSource().getAnImmediateUse() }
+ GlobbyFileNameSource() { this = globbyFileNameSource().getASource() }
}
/** Gets a file name or an array of file names from the `fast-glob` library. */
@@ -116,7 +116,7 @@ private API::Node fastGlobFileName() {
* A file name or an array of file names from the `fast-glob` library.
*/
private class FastGlobFileNameSource extends FileNameSource {
- FastGlobFileNameSource() { this = fastGlobFileName().getAnImmediateUse() }
+ FastGlobFileNameSource() { this = fastGlobFileName().getASource() }
}
/**
@@ -200,7 +200,7 @@ private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, API::
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().getASource() }
private API::Node trackFileSource() {
result = this.getParameter([1 .. 2]).getParameter(1)
@@ -223,7 +223,7 @@ private module JsonFile {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().getASource() }
private API::Node trackRead() {
this.getCalleeName() = "readFile" and
@@ -272,7 +272,7 @@ private class LoadJsonFile extends FileSystemReadAccess, API::CallNode {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getAnImmediateUse() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().getASource() }
private API::Node trackRead() {
this.getCalleeName() = "sync" and result = this.getReturn()
@@ -310,7 +310,7 @@ private class WalkDir extends FileNameProducer, FileSystemAccess, API::CallNode
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getAnImmediateUse() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().getASource() }
private API::Node trackFileSource() {
not this.getCalleeName() = ["sync", "async"] and
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
index c5fa208406f..37d20219ab8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
@@ -15,7 +15,7 @@ private class BusBoyRemoteFlow extends RemoteFlowSource {
.getMember("on")
.getParameter(1)
.getAParameter()
- .getAnImmediateUse()
+ .getASource()
}
override string getSourceType() { result = "parsed user value from Busbuy" }
@@ -49,12 +49,12 @@ private class MultipartyRemoteFlow extends RemoteFlowSource {
MultipartyRemoteFlow() {
exists(API::Node form | form = API::moduleImport("multiparty").getMember("Form").getInstance() |
exists(API::CallNode parse | parse = form.getMember("parse").getACall() |
- this = parse.getParameter(1).getAParameter().getAnImmediateUse()
+ this = parse.getParameter(1).getAParameter().getASource()
)
or
exists(API::CallNode on | on = form.getMember("on").getACall() |
on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and
- this = on.getParameter(1).getAParameter().getAnImmediateUse()
+ this = on.getParameter(1).getAParameter().getASource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
index 200c111c6b0..3907b80af1d 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
@@ -40,11 +40,11 @@ module History {
HistoryLibaryRemoteFlow() {
exists(API::Node loc | loc = [getBrowserHistory(), getHashHistory()].getMember("location") |
- this = loc.getMember("hash").getAnImmediateUse() and kind.isFragment()
+ this = loc.getMember("hash").getASource() and kind.isFragment()
or
- this = loc.getMember("pathname").getAnImmediateUse() and kind.isPath()
+ this = loc.getMember("pathname").getASource() and kind.isPath()
or
- this = loc.getMember("search").getAnImmediateUse() and kind.isQuery()
+ this = loc.getMember("search").getASource() and kind.isQuery()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
index 6f2098f27c9..e768a9feaff 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll
@@ -69,7 +69,7 @@ module Knex {
private class KnexDatabaseAwait extends DatabaseAccess, DataFlow::ValueNode {
KnexDatabaseAwait() {
exists(AwaitExpr enclosingAwait | this = enclosingAwait.flow() |
- enclosingAwait.getOperand() = knexObject().getAUse().asExpr()
+ enclosingAwait.getOperand() = knexObject().getAValueReachableFromSource().asExpr()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
index aa365680cd2..f842cf86628 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
@@ -12,7 +12,7 @@ private module LiveServer {
class ServerDefinition extends HTTP::Servers::StandardServerDefinition {
ServerDefinition() { this = DataFlow::moduleImport("live-server").asExpr() }
- API::Node getImportNode() { result.getAnImmediateUse().asExpr() = this }
+ API::Node getImportNode() { result.getASource().asExpr() = this }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
index aa79a35785b..993df7ff10a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
@@ -352,7 +352,7 @@ private module Pino {
// `pino` is installed as the "log" property on the request object in `Express` and similar libraries.
// in `Hapi` the property is "logger".
exists(HTTP::RequestExpr req, API::Node reqNode |
- reqNode.getAnImmediateUse() = req.flow().getALocalSource() and
+ reqNode.getASource() = req.flow().getALocalSource() and
result = reqNode.getMember(["log", "logger"])
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index bc2bf109fdf..02e2b4fbe9b 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -181,7 +181,7 @@ module NestJS {
predicate hasGlobalValidationPipe(Folder folder) {
exists(DataFlow::CallNode call |
call.getCalleeName() = "useGlobalPipes" and
- call.getArgument(0) = validationPipe().getInstance().getAUse() and
+ call.getArgument(0) = validationPipe().getInstance().getAValueReachableFromSource() and
folder = call.getFile().getParentContainer()
)
or
@@ -193,7 +193,7 @@ module NestJS {
.getAMember()
.getMember("useFactory")
.getReturn()
- .getARhs() = validationPipe().getInstance().getAUse() and
+ .getARhs() = validationPipe().getInstance().getAValueReachableFromSource() and
folder = decorator.getFile().getParentContainer()
)
or
@@ -204,7 +204,7 @@ module NestJS {
* Holds if `param` is affected by a pipe that sanitizes inputs.
*/
private predicate hasSanitizingPipe(NestJSRequestInput param, boolean dependsOnType) {
- param.getAPipe() = sanitizingPipe(dependsOnType).getAUse()
+ param.getAPipe() = sanitizingPipe(dependsOnType).getAValueReachableFromSource()
or
hasGlobalValidationPipe(param.getFile().getParentContainer()) and
dependsOnType = true
@@ -395,7 +395,7 @@ module NestJS {
/** Gets a parameter with this decorator applied. */
DataFlow::ParameterNode getADecoratedParameter() {
- result.getADecorator() = getReturn().getReturn().getAUse()
+ result.getADecorator() = getReturn().getReturn().getAValueReachableFromSource()
}
/** Gets a value returned by the decorator's callback, which becomes the value of the decorated parameter. */
@@ -427,7 +427,7 @@ module NestJS {
private class ExpressRequestSource extends Express::RequestSource {
ExpressRequestSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Req", "Request"]).getReturn().getAnImmediateUse()
+ nestjs().getMember(["Req", "Request"]).getReturn().getASource()
or
this =
executionContext()
@@ -435,7 +435,7 @@ module NestJS {
.getReturn()
.getMember("getRequest")
.getReturn()
- .getAnImmediateUse()
+ .getASource()
}
/**
@@ -452,7 +452,7 @@ module NestJS {
private class ExpressResponseSource extends Express::ResponseSource {
ExpressResponseSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Res", "Response"]).getReturn().getAnImmediateUse()
+ nestjs().getMember(["Res", "Response"]).getReturn().getASource()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
index 644754ce75e..d131e6b3674 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
@@ -252,6 +252,6 @@ module NextJS {
.getParameter(0)
.getParameter(0)
.getMember("router")
- .getAnImmediateUse()
+ .getASource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
index 2adc68f907a..3174cae8d2d 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
@@ -1070,7 +1070,7 @@ module NodeJSLib {
*/
private class EventEmitterSubClass extends DataFlow::ClassNode {
EventEmitterSubClass() {
- this.getASuperClassNode() = getAnEventEmitterImport().getAUse() or
+ this.getASuperClassNode() = getAnEventEmitterImport().getAValueReachableFromSource() or
this.getADirectSuperClass() instanceof EventEmitterSubClass
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
index ec9e490159e..3b7accdaa26 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
@@ -22,7 +22,7 @@ private module Prettier {
call = API::moduleImport("prettier").getMember("formatWithCursor").getACall()
|
pred = call.getArgument(0) and
- succ = call.getReturn().getMember("formatted").getAnImmediateUse()
+ succ = call.getReturn().getMember("formatted").getASource()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index fae5a1c76d7..2ea6e564ed1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -58,10 +58,10 @@ module Redux {
*/
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
/** Gets a reference to the store. */
- DataFlow::SourceNode ref() { result = asApiNode().getAUse() }
+ DataFlow::SourceNode ref() { result = asApiNode().getAValueReachableFromSource() }
/** Gets an API node that refers to this store creation. */
- API::Node asApiNode() { result.getAnImmediateUse() = this }
+ API::Node asApiNode() { result.getASource() = this }
/** Gets the data flow node holding the root reducer for this store. */
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
@@ -106,7 +106,7 @@ module Redux {
private API::Node rootState() {
result instanceof RootStateSource
or
- stateStep(rootState().getAUse(), result.getAnImmediateUse())
+ stateStep(rootState().getAValueReachableFromSource(), result.getASource())
}
/**
@@ -120,7 +120,7 @@ module Redux {
accessPath = joinAccessPaths(base, prop)
)
or
- stateStep(rootStateAccessPath(accessPath).getAUse(), result.getAnImmediateUse())
+ stateStep(rootStateAccessPath(accessPath).getAValueReachableFromSource(), result.getASource())
}
/**
@@ -374,7 +374,7 @@ module Redux {
CreateSliceReducer() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("reducer").getAnImmediateUse()
+ this = call.getReturn().getMember("reducer").getASource()
}
private API::Node getABuilderRef() {
@@ -386,7 +386,7 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(string name |
result = call.getParameter(0).getMember("reducers").getMember(name).getARhs() and
- actionType = call.getReturn().getMember("actions").getMember(name).getAnImmediateUse()
+ actionType = call.getReturn().getMember("actions").getMember(name).getASource()
)
or
// Properties of 'extraReducers':
@@ -445,7 +445,7 @@ module Redux {
// x -> bindActionCreators({ x, ... })
exists(BindActionCreatorsCall bind, string prop |
ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).getARhs()) and
- result = bind.getReturn().getMember(prop).getAnImmediateUse()
+ result = bind.getReturn().getMember(prop).getASource()
)
or
// x -> combineActions(x, ...)
@@ -580,7 +580,7 @@ module Redux {
MultiAction() {
createActions = API::moduleImport("redux-actions").getMember("createActions").getACall() and
- this = createActions.getReturn().getMember(name).getAnImmediateUse()
+ this = createActions.getReturn().getMember(name).getASource()
}
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
@@ -614,7 +614,7 @@ module Redux {
CreateSliceAction() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("actions").getMember(actionName).getAnImmediateUse()
+ this = call.getReturn().getMember("actions").getMember(actionName).getASource()
}
override string getTypeTag() {
@@ -885,12 +885,12 @@ module Redux {
accessPath = getAffectedStateAccessPath(reducer)
|
pred = function.getReturnNode() and
- succ = rootStateAccessPath(accessPath).getAnImmediateUse()
+ succ = rootStateAccessPath(accessPath).getASource()
or
exists(string suffix, DataFlow::SourceNode base |
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(accessPath + "." + suffix).getAnImmediateUse()
+ succ = rootStateAccessPath(accessPath + "." + suffix).getASource()
)
)
or
@@ -901,7 +901,7 @@ module Redux {
reducer.isRootStateHandler() and
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(suffix).getAnImmediateUse()
+ succ = rootStateAccessPath(suffix).getASource()
)
}
@@ -1205,7 +1205,7 @@ module Redux {
// Selector functions may be given as an array
exists(DataFlow::ArrayCreationNode array |
array.flowsTo(getArgument(0)) and
- result.getAUse() = array.getElement(i)
+ result.getAValueReachableFromSource() = array.getElement(i)
)
}
}
@@ -1222,7 +1222,7 @@ module Redux {
exists(CreateSelectorCall call, int index |
call.getNumArgument() > 1 and
pred = call.getSelectorFunction(index).getReturn().getARhs() and
- succ = call.getLastParameter().getParameter(index).getAnImmediateUse()
+ succ = call.getLastParameter().getParameter(index).getASource()
)
or
// The result of the last callback is the final result
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
index 03c78c2561f..f8f3fb08ff0 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
@@ -383,7 +383,7 @@ private module Sqlite {
/** A call to a Sqlite query method. */
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
QueryCall() {
- this = getAChainingQueryCall().getAnImmediateUse()
+ this = getAChainingQueryCall().getASource()
or
this = database().getMember("prepare").getACall()
}
@@ -440,7 +440,7 @@ private module MsSql {
override TaggedTemplateExpr astNode;
QueryTemplateExpr() {
- mssql().getMember("query").getAUse() = DataFlow::valueNode(astNode.getTag())
+ mssql().getMember("query").getAValueReachableFromSource() = DataFlow::valueNode(astNode.getTag())
}
override DataFlow::Node getAResult() {
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
index d5692c3d2c2..2569d205473 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
@@ -27,7 +27,7 @@ private module Snapdragon {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(string methodName, API::CallNode set, API::CallNode call, API::Node base |
// the handler, registered with a call to `.set`.
- set = getSetCall+(base.getMember(methodName + "r")).getAnImmediateUse() and
+ set = getSetCall+(base.getMember(methodName + "r")).getASource() and
// the snapdragon instance. The API is chaining, you can also use the instance directly.
base = API::moduleImport("snapdragon").getInstance() and
methodName = ["parse", "compile"] and
@@ -47,7 +47,7 @@ private module Snapdragon {
or
// for compiler handlers the input is the first parameter.
methodName = "compile" and
- succ = set.getParameter(1).getParameter(0).getAnImmediateUse()
+ succ = set.getParameter(1).getParameter(0).getASource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
index df761420e29..7e0cc61c3ca 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
@@ -41,7 +41,7 @@ module SocketIO {
class ServerObject extends SocketIOObject {
API::Node node;
- ServerObject() { node = newServer() and this = node.getAnImmediateUse() }
+ ServerObject() { node = newServer() and this = node.getASource() }
/** Gets the Api node for this server. */
API::Node asApiNode() { result = node }
@@ -81,7 +81,7 @@ module SocketIO {
)
}
- override DataFlow::SourceNode ref() { result = this.server().getAUse() }
+ override DataFlow::SourceNode ref() { result = this.server().getAValueReachableFromSource() }
}
/** A data flow node that may produce (that is, create or return) a socket.io server. */
@@ -119,7 +119,7 @@ module SocketIO {
API::Node node;
NamespaceBase() {
- this = node.getAnImmediateUse() and
+ this = node.getASource() and
exists(ServerObject srv |
// namespace lookup on `srv`
node = srv.asApiNode().getMember("sockets") and
@@ -158,7 +158,7 @@ module SocketIO {
)
}
- override DataFlow::SourceNode ref() { result = this.namespace().getAUse() }
+ override DataFlow::SourceNode ref() { result = this.namespace().getAValueReachableFromSource() }
}
/** A data flow node that may produce a namespace object. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index c1e6cb342f1..b26d4e56339 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -718,7 +718,7 @@ module Templating {
override TemplateSyntax getTemplateSyntax() { result.getAPackageName() = engine }
override DataFlow::SourceNode getOutput() {
- result = this.getParameter([1, 2]).getParameter(1).getAnImmediateUse()
+ result = this.getParameter([1, 2]).getParameter(1).getASource()
or
not exists(this.getParameter([1, 2]).getParameter(1)) and
result = this
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
index 1724e1174aa..a9ab45ba821 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
@@ -21,7 +21,7 @@ module ParseTorrent {
node = mod().getReturn() or
node = mod().getMember("remote").getParameter(1).getParameter(1)
) and
- this = node.getAnImmediateUse()
+ this = node.getASource()
}
/** Gets the API node for this torrent object. */
@@ -29,7 +29,7 @@ module ParseTorrent {
}
/** Gets a data flow node referring to a parsed torrent. */
- DataFlow::SourceNode parsedTorrentRef() { result = any(ParsedTorrent t).asApiNode().getAUse() }
+ DataFlow::SourceNode parsedTorrentRef() { result = any(ParsedTorrent t).asApiNode().getAValueReachableFromSource() }
/**
* An access to user-controlled torrent information.
@@ -38,7 +38,7 @@ module ParseTorrent {
UserControlledTorrentInfo() {
exists(API::Node read |
read = any(ParsedTorrent t).asApiNode().getAMember() and
- this = read.getAnImmediateUse()
+ this = read.getASource()
|
exists(string prop |
not (
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
index 5357259b9eb..6e59884237d 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
@@ -190,7 +190,7 @@ module Querystringify {
* Gets a data flow source node for member `name` of the querystringify library.
*/
DataFlow::SourceNode querystringifyMember(string name) {
- result = querystringify().getMember(name).getAnImmediateUse()
+ result = querystringify().getMember(name).getASource()
}
/** Gets an API node referring to the `querystringify` module. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index d32db710fa8..0e7031bbe9a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -41,7 +41,7 @@ module Vue {
/**
* Gets a reference to the 'Vue' object.
*/
- DataFlow::SourceNode vue() { result = vueLibrary().getAnImmediateUse() }
+ DataFlow::SourceNode vue() { result = vueLibrary().getASource() }
/** Gets an API node referring to a component or `Vue`. */
private API::Node component() {
@@ -176,7 +176,7 @@ module Vue {
/** Gets a component which is extended by this one. */
Component getABaseComponent() {
- result.getComponentRef().getAUse() =
+ result.getComponentRef().getAValueReachableFromSource() =
getOwnOptions().getMember(["extends", "mixins"]).getARhs()
}
@@ -328,10 +328,10 @@ module Vue {
}
/** Gets an API node referring to an instance of this component. */
- API::Node getInstance() { result.getAnImmediateUse() = getABoundFunction().getReceiver() }
+ API::Node getInstance() { result.getASource() = getABoundFunction().getReceiver() }
/** Gets a data flow node referring to an instance of this component. */
- DataFlow::SourceNode getAnInstanceRef() { result = getInstance().getAnImmediateUse() }
+ DataFlow::SourceNode getAnInstanceRef() { result = getInstance().getASource() }
pragma[noinline]
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
@@ -533,7 +533,7 @@ module Vue {
// of the .vue file.
exists(Import imprt |
imprt.getImportedPath().resolve() = file and
- result.getAnImmediateUse() = imprt.getImportedModuleNode()
+ result.getASource() = imprt.getImportedModuleNode()
)
}
@@ -695,7 +695,7 @@ module Vue {
t.start() and
(
exists(API::Node router | router = API::moduleImport("vue-router") |
- result = router.getInstance().getMember("currentRoute").getAnImmediateUse()
+ result = router.getInstance().getMember("currentRoute").getASource()
or
result =
router
@@ -703,17 +703,17 @@ module Vue {
.getMember(["beforeEach", "beforeResolve", "afterEach"])
.getParameter(0)
.getParameter([0, 1])
- .getAnImmediateUse()
+ .getASource()
or
result =
router
.getParameter(0)
.getMember("scrollBehavior")
.getParameter([0, 1])
- .getAnImmediateUse()
+ .getASource()
)
or
- result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getAnImmediateUse()
+ result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getASource()
or
exists(Component c |
result = c.getABoundFunction().getAFunctionValue().getReceiver().getAPropertyRead("$route")
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
index 8d062a447aa..5efef1271e7 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
@@ -116,7 +116,7 @@ module Vuex {
/** Gets the Vue component in which the generated functions are installed. */
Vue::Component getVueComponent() {
exists(DataFlow::ObjectLiteralNode obj |
- obj.getASpreadProperty() = getReturn().getAUse() and
+ obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
result.getOwnOptions().getAMember().getARhs() = obj
)
or
@@ -154,12 +154,12 @@ module Vuex {
/** Gets a property access that may receive the produced by a getter of the given name. */
private DataFlow::Node getterSucc(string name) {
exists(string prefix, string prop |
- result = storeRef(prefix).getMember("getters").getMember(prop).getAnImmediateUse() and
+ result = storeRef(prefix).getMember("getters").getMember(prop).getASource() and
prop != "*" and
name = prefix + prop
)
or
- result = getAMappedAccess("mapGetters", name).getAnImmediateUse()
+ result = getAMappedAccess("mapGetters", name).getASource()
}
/** Holds if `pred -> succ` is a step from a getter function to a relevant property access. */
@@ -238,7 +238,7 @@ module Vuex {
.getMember(getStorePropForCommitKind(kind))
.getMember(prop)
.getParameter(1)
- .getAnImmediateUse() and
+ .getASource() and
prop != "*" and
name = prefix + prop
)
@@ -296,7 +296,7 @@ module Vuex {
result = stateRefByAccessPath(path).getARhs()
or
exists(ExtendCall call, string base, string prop |
- call.getDestinationOperand() = stateRefByAccessPath(base).getAUse() and
+ call.getDestinationOperand() = stateRefByAccessPath(base).getAValueReachableFromSource() and
result = call.getASourceOperand().getALocalSource().getAPropertyWrite(prop).getRhs() and
path = appendToNamespace(base, prop)
)
@@ -304,7 +304,7 @@ module Vuex {
/** Gets a value that refers to the given access path of the state. */
DataFlow::Node stateMutationSucc(string path) {
- result = stateRefByAccessPath(path).getAnImmediateUse()
+ result = stateRefByAccessPath(path).getASource()
}
/** Holds if `pred -> succ` is a step from state mutation to state access. */
@@ -336,7 +336,7 @@ module Vuex {
predicate mapStateHelperStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Vue::Component component, string name |
pred = mapStateHelperPred(component, name) and
- succ = pragma[only_bind_out](component).getInstance().getMember(name).getAnImmediateUse()
+ succ = pragma[only_bind_out](component).getInstance().getMember(name).getASource()
)
}
@@ -378,7 +378,7 @@ module Vuex {
/** Gets a package that can be considered an entry point for a Vuex app. */
private PackageJson entryPointPackage() {
- result = getPackageJson(storeRef().getAnImmediateUse().getFile())
+ result = getPackageJson(storeRef().getASource().getFile())
or
// Any package that imports a store-creating package is considered a potential entry point.
packageDependsOn(result, entryPointPackage())
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
index 41cecb36941..bd57a4ab1f8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
@@ -100,7 +100,7 @@ module XML {
}
override DataFlow::Node getAResult() {
- result = [doc(), element(), attr()].getAnImmediateUse()
+ result = [doc(), element(), attr()].getASource()
or
result = element().getMember(["name", "text"]).getACall()
or
@@ -286,7 +286,7 @@ module XML {
.getReturn()
.getMember(any(string s | s.matches("on%")))
.getAParameter()
- .getAnImmediateUse()
+ .getASource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
index f8b2118a55f..06059ec2680 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
@@ -26,7 +26,7 @@ import Shared::ModelOutput as ModelOutput
* A remote flow source originating from a CSV source row.
*/
private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
- RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").getAnImmediateUse() }
+ RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").getASource() }
override string getSourceType() { result = "Remote flow" }
}
@@ -38,7 +38,7 @@ private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, str
exists(API::Node predNode, API::Node succNode |
Specific::summaryStep(predNode, succNode, kind) and
pred = predNode.getARhs() and
- succ = succNode.getAnImmediateUse()
+ succ = succNode.getASource()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
index 35b1ac83e2d..40c86ed4855 100644
--- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
+++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll
@@ -58,7 +58,7 @@ class RemoteServerResponse extends HeuristicSource, RemoteFlowSource {
*/
private class RemoteFlowSourceFromDBAccess extends RemoteFlowSource, HeuristicSource {
RemoteFlowSourceFromDBAccess() {
- this = ModelOutput::getASourceNode("database-access-result").getAUse() or
+ this = ModelOutput::getASourceNode("database-access-result").getAValueReachableFromSource() or
exists(DatabaseAccess dba | this = dba.getAResult())
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
index 93c9fa63a59..879a03ca029 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
@@ -49,7 +49,7 @@ module DomBasedXss {
or
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
exists(DataFlow::NewNode instance |
- instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
+ instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getASource() and
this = instance.getArgument(0) and
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
index 36fed7c2106..26c5ded744f 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
@@ -62,7 +62,7 @@ module ExceptionXss {
*/
private class JsonSchemaValidationError extends Source {
JsonSchemaValidationError() {
- this = any(JsonSchema::Ajv::Instance i).getAValidationError().getAnImmediateUse()
+ this = any(JsonSchema::Ajv::Instance i).getAValidationError().getASource()
or
this = any(JsonSchema::Joi::JoiValidationErrorRead r).getAValidationResultAccess(_)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
index a061fd5bc6f..fb1e4a903db 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
@@ -165,9 +165,9 @@ module ExternalApiUsedWithUntrustedData {
not param = base.getReceiver()
|
result = param and
- name = param.getAnImmediateUse().asExpr().(Parameter).getName()
+ name = param.getASource().asExpr().(Parameter).getName()
or
- param.getAnImmediateUse().asExpr() instanceof DestructuringPattern and
+ param.getASource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
index a410bda46b5..9a0fb9c4e2c 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
@@ -74,7 +74,7 @@ module IndirectCommandInjection {
].getMember("parse").getACall()
or
// `require('commander').myCmdArgumentName`
- this = commander().getAMember().getAnImmediateUse()
+ this = commander().getAMember().getASource()
or
// `require('commander').opt()` => `{a: ..., b: ...}`
this = commander().getMember("opts").getACall()
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
index fc30c91018a..d5b2f11f1c1 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
@@ -153,7 +153,7 @@ abstract class RateLimitingMiddleware extends DataFlow::SourceNode {
*/
class ExpressRateLimit extends RateLimitingMiddleware {
ExpressRateLimit() {
- this = API::moduleImport("express-rate-limit").getReturn().getAnImmediateUse()
+ this = API::moduleImport("express-rate-limit").getReturn().getASource()
}
}
@@ -162,7 +162,7 @@ class ExpressRateLimit extends RateLimitingMiddleware {
*/
class BruteForceRateLimit extends RateLimitingMiddleware {
BruteForceRateLimit() {
- this = API::moduleImport("express-brute").getInstance().getMember("prevent").getAnImmediateUse()
+ this = API::moduleImport("express-brute").getInstance().getMember("prevent").getASource()
}
}
@@ -174,7 +174,7 @@ class BruteForceRateLimit extends RateLimitingMiddleware {
*/
class RouteHandlerLimitedByExpressLimiter extends RateLimitingMiddleware {
RouteHandlerLimitedByExpressLimiter() {
- this = API::moduleImport("express-limiter").getReturn().getReturn().getAnImmediateUse()
+ this = API::moduleImport("express-limiter").getReturn().getReturn().getASource()
}
override Routing::Node getRoutingNode() {
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
index ff026f3a3a4..5f5cf99bdd2 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
@@ -175,7 +175,7 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
private class ExternalRemoteFlowSource extends RemoteFlowSource {
RemoteFlowSourceAccessPath ap;
- ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().getAnImmediateUse() }
+ ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().getASource() }
override string getSourceType() { result = ap.getSourceType() }
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index b869b028902..924176d99c5 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -209,7 +209,7 @@ module XssThroughDom {
useForm = API::moduleImport("react-hook-form").getMember("useForm").getReturn()
|
this =
- useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getAnImmediateUse()
+ useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getASource()
or
this = useForm.getMember("getValues").getACall()
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
index 3c4c5f66b75..2e417d018db 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
@@ -103,7 +103,7 @@ module ZipSlip {
class JSZipFilesSource extends Source instanceof DynamicPropertyAccess::EnumeratedPropName {
JSZipFilesSource() {
super.getSourceObject() =
- API::moduleImport("jszip").getInstance().getMember("files").getAnImmediateUse()
+ API::moduleImport("jszip").getInstance().getMember("files").getASource()
}
}
@@ -116,7 +116,7 @@ module ZipSlip {
.getMember(["forEach", "filter"])
.getParameter(0)
.getParameter(0)
- .getAnImmediateUse()
+ .getASource()
}
}
diff --git a/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql b/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
index 446df101364..8f6629cc624 100644
--- a/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
+++ b/javascript/ql/src/meta/ApiGraphs/ApiGraphUseNodes.ql
@@ -11,4 +11,4 @@
import javascript
import meta.MetaMetrics
-select projectRoot(), count(any(API::Node nd).getAUse())
+select projectRoot(), count(any(API::Node nd).getAValueReachableFromSource())
diff --git a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
index 9b5c0594a72..57e7c3d3a99 100644
--- a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
+++ b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
@@ -24,7 +24,7 @@ private DataFlow::Node getNode(API::Node nd, string kind) {
result = nd.getARhs()
or
kind = "use" and
- result = nd.getAUse()
+ result = nd.getAValueReachableFromSource()
}
private string getLoc(DataFlow::Node nd) {
diff --git a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
index 582385c802a..b703739ff04 100644
--- a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
+++ b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
@@ -1,4 +1,4 @@
import javascript
from string mod, string tp
-select mod, tp, API::Node::ofType(mod, tp).getAnImmediateUse()
+select mod, tp, API::Node::ofType(mod, tp).getASource()
diff --git a/javascript/ql/test/library-tests/Routing/test.ql b/javascript/ql/test/library-tests/Routing/test.ql
index aa89c7212d2..2593f8263b3 100644
--- a/javascript/ql/test/library-tests/Routing/test.ql
+++ b/javascript/ql/test/library-tests/Routing/test.ql
@@ -9,7 +9,7 @@ class Taint extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node node) {
node.(DataFlow::CallNode).getCalleeName() = "source"
or
- node = testInstance().getMember("getSource").getReturn().getAnImmediateUse()
+ node = testInstance().getMember("getSource").getReturn().getASource()
}
override predicate isSink(DataFlow::Node node) {
diff --git a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
index 76a21469f6b..e1a8e825099 100644
--- a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
+++ b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
@@ -1,3 +1,3 @@
import javascript
-query DataFlow::Node dbUse() { result = API::moduleImport("@example/db").getInstance().getAUse() }
+query DataFlow::Node dbUse() { result = API::moduleImport("@example/db").getInstance().getAValueReachableFromSource() }
diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql
index bdc08e3706f..a73cccfd94c 100644
--- a/javascript/ql/test/library-tests/frameworks/data/test.ql
+++ b/javascript/ql/test/library-tests/frameworks/data/test.ql
@@ -62,7 +62,7 @@ class BasicTaintTracking extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CallNode).getCalleeName() = "source"
or
- source = ModelOutput::getASourceNode("test-source").getAnImmediateUse()
+ source = ModelOutput::getASourceNode("test-source").getASource()
}
override predicate isSink(DataFlow::Node sink) {
From 19a5db9f897dae8e8cbd2716943a2212678b4923 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:33:16 +0200
Subject: [PATCH 068/125] JS: Rename getARhs -> getASink
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 38 +++++++++++-------
.../ql/lib/semmle/javascript/JsonSchema.qll | 2 +-
.../javascript/frameworks/ClientRequests.qll | 6 +--
.../javascript/frameworks/Credentials.qll | 2 +-
.../lib/semmle/javascript/frameworks/D3.qll | 2 +-
.../javascript/frameworks/HttpProxy.qll | 12 +++---
.../semmle/javascript/frameworks/LdapJS.qll | 4 +-
.../javascript/frameworks/LiveServer.qll | 2 +-
.../semmle/javascript/frameworks/Markdown.qll | 4 +-
.../lib/semmle/javascript/frameworks/Nest.qll | 4 +-
.../semmle/javascript/frameworks/NoSQL.qll | 10 ++---
.../javascript/frameworks/NodeJSLib.qll | 8 ++--
.../javascript/frameworks/Puppeteer.qll | 2 +-
.../semmle/javascript/frameworks/Redux.qll | 40 +++++++++----------
.../lib/semmle/javascript/frameworks/SQL.qll | 12 +++---
.../javascript/frameworks/Templating.qll | 10 ++---
.../javascript/frameworks/TrustedTypes.qll | 2 +-
.../lib/semmle/javascript/frameworks/Vue.qll | 18 ++++-----
.../lib/semmle/javascript/frameworks/Vuex.qll | 26 ++++++------
.../frameworks/data/ModelsAsData.qll | 2 +-
.../data/internal/ApiGraphModelsSpecific.qll | 2 +-
...APIUsedWithUntrustedDataCustomizations.qll | 2 +-
.../security/dataflow/MissingRateLimiting.qll | 2 +-
.../dataflow/SqlInjectionCustomizations.qll | 2 +-
.../dataflow/TaintedPathCustomizations.qll | 10 ++---
.../CWE-295/DisablingCertificateValidation.ql | 2 +-
.../Security/CWE-352/MissingCsrfMiddleware.ql | 2 +-
.../ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql | 2 +-
.../ql/test/ApiGraphs/VerifyAssertions.qll | 2 +-
.../ql/test/ApiGraphs/call-nodes/test.ql | 4 +-
.../ql/test/library-tests/Routing/test.ql | 2 +-
.../library-tests/frameworks/data/test.ql | 4 +-
32 files changed, 126 insertions(+), 116 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index c4f2feaab67..45864ec8ccc 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -187,26 +187,36 @@ module API {
InvokeNode getAnInvocation() { result = this.getACall() or result = this.getAnInstantiation() }
/**
- * Gets a data-flow node corresponding to the right-hand side of a definition of the API
- * component represented by this node.
+ * Get a data-flow node where this value leaves the current codebase and flows into an
+ * external library (or in general, any external codebase).
*
- * For example, in the assignment `exports.plusOne = (x) => x+1`, the function expression
- * `(x) => x+1` is the right-hand side of the definition of the member `plusOne` of
- * the enclosing module, and the expression `x+1` is the right-had side of the definition of
- * its result.
+ * Concretely, this is either an argument passed to a call to external code,
+ * or the right-hand side of a property write on an object flows into such a call.
*
- * Note that for parameters, it is the arguments flowing into that parameter that count as
- * right-hand sides of the definition, not the declaration of the parameter itself.
- * Consequently, in `require('fs').readFileSync(file)`, `file` is the right-hand
- * side of a definition of the first parameter of `readFileSync` from the `fs` module.
+ * For example:
+ * ```js
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).getASink()
+ * require('foo')(x);
+ *
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).getMember("prop").getASink()
+ * require('foo')({
+ * prop: x
+ * });
+ * ```
*/
- DataFlow::Node getARhs() { Impl::rhs(this, result) }
+ DataFlow::Node getASink() { Impl::rhs(this, result) }
/**
* Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition
* of the API component represented by this node.
*/
- DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(this.getARhs()) }
+ DataFlow::Node getAValueReachingSink() { result = Impl::trackDefNode(this.getASink()) }
+
+ /** DEPRECATED. This predicate has been renamed to `getASink`. */
+ deprecated DataFlow::Node getARhs() { result = this.getASink() }
+
+ /** DEPRECATED. This predicate has been renamed to `getAValueReachingSink`. */
+ deprecated DataFlow::Node getAValueReachingRhs() { result = this.getAValueReachingSink() }
/**
* Gets a node representing member `m` of this API component.
@@ -441,7 +451,7 @@ module API {
* In other words, the value of a use of `that` may flow into the right-hand side of a
* definition of this node.
*/
- predicate refersTo(Node that) { this.getARhs() = that.getAValueReachableFromSource() }
+ predicate refersTo(Node that) { this.getASink() = that.getAValueReachableFromSource() }
/**
* Gets the data-flow node that gives rise to this node, if any.
@@ -1301,7 +1311,7 @@ module API {
* Gets an API node where a RHS of the node is the `i`th argument to this call.
*/
pragma[noinline]
- private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) }
+ private Node getAParameterCandidate(int i) { result.getASink() = this.getArgument(i) }
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = this.getParameter(_) }
diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
index b108bde91f6..4c6540efc13 100644
--- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
@@ -134,7 +134,7 @@ module JsonSchema {
.ref()
.getMember(["addSchema", "validate", "compile", "compileAsync"])
.getParameter(0)
- .getARhs()
+ .getASink()
}
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
index b9054fdee41..c14d4047602 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
@@ -827,7 +827,7 @@ module ClientRequest {
class ApolloClientRequest extends ClientRequest::Range, API::InvokeNode {
ApolloClientRequest() { this = apolloUriCallee().getAnInvocation() }
- override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").getARhs() }
+ override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").getASink() }
override DataFlow::Node getHost() { none() }
@@ -848,10 +848,10 @@ module ClientRequest {
override DataFlow::Node getUrl() { result = this.getArgument(0) }
- override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").getARhs() }
+ override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").getASink() }
override DataFlow::Node getADataNode() {
- result = form.getMember("append").getACall().getParameter(1).getARhs()
+ result = form.getMember("append").getACall().getParameter(1).getASink()
}
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
index b6892b5aa49..925dba2305b 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
@@ -21,7 +21,7 @@ private class CredentialsFromModel extends CredentialsExpr {
string kind;
CredentialsFromModel() {
- this = ModelOutput::getASinkNode("credentials[" + kind + "]").getARhs().asExpr()
+ this = ModelOutput::getASinkNode("credentials[" + kind + "]").getASink().asExpr()
}
override string getCredentialsKind() { result = kind }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index d8478002fc2..7ec3f0d95fe 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -71,7 +71,7 @@ module D3 {
D3XssSink() {
exists(API::Node htmlArg |
htmlArg = d3Selection().getMember("html").getParameter(0) and
- this = [htmlArg, htmlArg.getReturn()].getARhs()
+ this = [htmlArg, htmlArg.getReturn()].getASink()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
index 2467ca0973b..b879207c602 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
@@ -19,10 +19,10 @@ private module HttpProxy {
.getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").getARhs() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").getASink() }
override DataFlow::Node getHost() {
- result = getParameter(0).getMember("target").getMember("host").getARhs()
+ result = getParameter(0).getMember("target").getMember("host").getASink()
}
override DataFlow::Node getADataNode() { none() }
@@ -49,10 +49,10 @@ private module HttpProxy {
)
}
- override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").getARhs() }
+ override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").getASink() }
override DataFlow::Node getHost() {
- result = getOptionsObject().getMember("target").getMember("host").getARhs()
+ result = getOptionsObject().getMember("target").getMember("host").getASink()
}
override DataFlow::Node getADataNode() { none() }
@@ -78,8 +78,8 @@ private module HttpProxy {
ProxyListenerCallback() {
exists(API::CallNode call |
call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and
- call.getParameter(0).getARhs().mayHaveStringValue(event) and
- this = call.getParameter(1).getARhs().getAFunctionValue()
+ call.getParameter(0).getASink().mayHaveStringValue(event) and
+ this = call.getParameter(1).getASink().getAFunctionValue()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
index 853b76afdda..9a50f2315fe 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
@@ -61,10 +61,10 @@ module LdapJS {
SearchFilter() {
options = ldapClient().getMember("search").getACall().getParameter(1) and
- this = options.getARhs()
+ this = options.getASink()
}
- override DataFlow::Node getInput() { result = options.getMember("filter").getARhs() }
+ override DataFlow::Node getInput() { result = options.getMember("filter").getASink() }
override DataFlow::Node getOutput() { result = this }
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
index f842cf86628..5272881c7d8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
@@ -41,7 +41,7 @@ private module LiveServer {
override DataFlow::SourceNode getARouteHandler() {
exists(DataFlow::SourceNode middleware |
- middleware = call.getParameter(0).getMember("middleware").getAValueReachingRhs()
+ middleware = call.getParameter(0).getMember("middleware").getAValueReachingSink()
|
result = middleware.getAMemberCall(["push", "unshift"]).getArgument(0).getAFunctionValue()
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
index d131c70773a..d22d64b1adc 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
@@ -163,14 +163,14 @@ module Markdown {
or
call = API::moduleImport("markdown-it").getMember("Markdown").getAnInvocation()
|
- call.getParameter(0).getMember("html").getARhs().mayHaveBooleanValue(true) and
+ call.getParameter(0).getMember("html").getASink().mayHaveBooleanValue(true) and
result = call.getReturn()
)
or
exists(API::CallNode call |
call = markdownIt().getMember(["use", "set", "configure", "enable", "disable"]).getACall() and
result = call.getReturn() and
- not call.getParameter(0).getAValueReachingRhs() =
+ not call.getParameter(0).getAValueReachingSink() =
DataFlow::moduleImport("markdown-it-sanitizer")
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index 02e2b4fbe9b..0a8ba5ca632 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -193,7 +193,7 @@ module NestJS {
.getAMember()
.getMember("useFactory")
.getReturn()
- .getARhs() = validationPipe().getInstance().getAValueReachableFromSource() and
+ .getASink() = validationPipe().getInstance().getAValueReachableFromSource() and
folder = decorator.getFile().getParentContainer()
)
or
@@ -399,7 +399,7 @@ module NestJS {
}
/** Gets a value returned by the decorator's callback, which becomes the value of the decorated parameter. */
- DataFlow::Node getResult() { result = getParameter(0).getReturn().getARhs() }
+ DataFlow::Node getResult() { result = getParameter(0).getReturn().getASink() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
index b04467a93ec..122d3b994be 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
@@ -20,7 +20,7 @@ deprecated module NoSQL = NoSql;
* Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`.
*/
private DataFlow::Node getADollarWhereProperty(API::Node queryArg) {
- result = queryArg.getMember("$where").getARhs()
+ result = queryArg.getMember("$where").getASink()
}
/**
@@ -501,7 +501,7 @@ private module Mongoose {
Credentials() {
exists(string prop |
- this = createConnection().getParameter(3).getMember(prop).getARhs().asExpr()
+ this = createConnection().getParameter(3).getMember(prop).getASink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -518,7 +518,7 @@ private module Mongoose {
class MongoDBQueryPart extends NoSql::Query {
MongooseFunction f;
- MongoDBQueryPart() { this = f.getQueryArgument().getARhs().asExpr() }
+ MongoDBQueryPart() { this = f.getQueryArgument().getASink().asExpr() }
override DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(f.getQueryArgument())
@@ -540,7 +540,7 @@ private module Mongoose {
override DataFlow::Node getAQueryArgument() {
// NB: the complete information is not easily accessible for deeply chained calls
- f.getQueryArgument().getARhs() = result
+ f.getQueryArgument().getASink() = result
}
override DataFlow::Node getAResult() {
@@ -770,7 +770,7 @@ private module Redis {
RedisKeyArgument() {
exists(string method, int argIndex |
QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and
- this = redis().getMember(method).getParameter(argIndex).getARhs().asExpr()
+ this = redis().getMember(method).getParameter(argIndex).getASink().asExpr()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
index 3174cae8d2d..580109b6cc4 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
@@ -739,7 +739,7 @@ module NodeJSLib {
methodName = ["execFile", "execFileSync", "spawn", "spawnSync", "fork"]
) and
// all of the above methods take the command as their first argument
- result = this.getParameter(0).getARhs()
+ result = this.getParameter(0).getASink()
}
override DataFlow::Node getACommandArgument() { result = this.getACommandArgument(_) }
@@ -751,7 +751,7 @@ module NodeJSLib {
override DataFlow::Node getArgumentList() {
methodName = ["execFile", "execFileSync", "fork", "spawn", "spawnSync"] and
// all of the above methods take the argument list as their second argument
- result = this.getParameter(1).getARhs()
+ result = this.getParameter(1).getASink()
}
override predicate isSync() { methodName.matches("%Sync") }
@@ -759,7 +759,7 @@ module NodeJSLib {
override DataFlow::Node getOptionsArg() {
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode and // looks like argumentlist
- not result = this.getParameter(0).getARhs() and
+ not result = this.getParameter(0).getASink() and
// fork/spawn and all sync methos always has options as the last argument
if
methodName.matches("fork%") or
@@ -768,7 +768,7 @@ module NodeJSLib {
then result = this.getLastArgument()
else
// the rest (exec/execFile) has the options argument as their second last.
- result = this.getParameter(this.getNumArgument() - 2).getARhs()
+ result = this.getParameter(this.getNumArgument() - 2).getASink()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
index b7bef025d23..94e98a5bdee 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
@@ -86,7 +86,7 @@ module Puppeteer {
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").getARhs() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").getASink() }
override DataFlow::Node getHost() { none() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index 2ea6e564ed1..fe05080c25c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -94,7 +94,7 @@ module Redux {
}
override DataFlow::Node getReducerArg() {
- result = getParameter(0).getMember("reducer").getARhs()
+ result = getParameter(0).getMember("reducer").getASink()
}
}
}
@@ -193,7 +193,7 @@ module Redux {
CombineReducers() { this = combineReducers().getACall() }
override DataFlow::Node getStateHandlerArg(string prop) {
- result = getParameter(0).getMember(prop).getARhs()
+ result = getParameter(0).getMember(prop).getASink()
}
}
@@ -207,7 +207,7 @@ module Redux {
*/
private class NestedCombineReducers extends DelegatingReducer, DataFlow::ObjectLiteralNode {
NestedCombineReducers() {
- this = combineReducers().getParameter(0).getAMember+().getAValueReachingRhs()
+ this = combineReducers().getParameter(0).getAMember+().getAValueReachingSink()
}
override DataFlow::Node getStateHandlerArg(string prop) {
@@ -235,7 +235,7 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(DataFlow::PropWrite write |
- result = getParameter(0).getAMember().getARhs() and
+ result = getParameter(0).getAMember().getASink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -385,14 +385,14 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(string name |
- result = call.getParameter(0).getMember("reducers").getMember(name).getARhs() and
+ result = call.getParameter(0).getMember("reducers").getMember(name).getASink() and
actionType = call.getReturn().getMember("actions").getMember(name).getASource()
)
or
// Properties of 'extraReducers':
// { extraReducers: { [action]: reducer }}
exists(DataFlow::PropWrite write |
- result = call.getParameter(0).getMember("extraReducers").getAMember().getARhs() and
+ result = call.getParameter(0).getMember("extraReducers").getAMember().getASink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -444,7 +444,7 @@ module Redux {
or
// x -> bindActionCreators({ x, ... })
exists(BindActionCreatorsCall bind, string prop |
- ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).getARhs()) and
+ ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).getASink()) and
result = bind.getReturn().getMember(prop).getASource()
)
or
@@ -584,7 +584,7 @@ module Redux {
}
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
- result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).getARhs()) and
+ result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).getASink()) and
async = false
}
@@ -619,7 +619,7 @@ module Redux {
override string getTypeTag() {
exists(string prefix |
- call.getParameter(0).getMember("name").getARhs().mayHaveStringValue(prefix) and
+ call.getParameter(0).getMember("name").getASink().mayHaveStringValue(prefix) and
result = prefix + "/" + actionName
)
}
@@ -640,7 +640,7 @@ module Redux {
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
async = true and
- result = getParameter(1).getAValueReachingRhs()
+ result = getParameter(1).getAValueReachingSink()
}
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) }
@@ -916,7 +916,7 @@ module Redux {
*/
private DataFlow::ObjectLiteralNode getAManuallyDispatchedValue(string actionType) {
result.getAPropertyWrite("type").getRhs().mayHaveStringValue(actionType) and
- result = getADispatchedValueNode().getAValueReachingRhs()
+ result = getADispatchedValueNode().getAValueReachingSink()
}
/**
@@ -994,7 +994,7 @@ module Redux {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(API::CallNode call |
call = useSelector().getACall() and
- pred = call.getParameter(0).getReturn().getARhs() and
+ pred = call.getParameter(0).getReturn().getASink() and
succ = call
)
}
@@ -1046,19 +1046,19 @@ module Redux {
//
// const mapDispatchToProps = { foo }
//
- result = getMapDispatchToProps().getMember(name).getARhs()
+ result = getMapDispatchToProps().getMember(name).getASink()
or
//
// const mapDispatchToProps = dispatch => ( { foo } )
//
- result = getMapDispatchToProps().getReturn().getMember(name).getARhs()
+ result = getMapDispatchToProps().getReturn().getMember(name).getASink()
or
// Explicitly bound by bindActionCreators:
//
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
//
exists(BindActionCreatorsCall bind |
- bind.flowsTo(getMapDispatchToProps().getReturn().getARhs()) and
+ bind.flowsTo(getMapDispatchToProps().getReturn().getASink()) and
result = bind.getOptionArgument(0, name)
)
}
@@ -1115,12 +1115,12 @@ module Redux {
override API::Node getMapStateToProps() {
result = getAParameter() and
- result.getARhs().asExpr().(Identifier).getName() = "mapStateToProps"
+ result.getASink().asExpr().(Identifier).getName() = "mapStateToProps"
}
override API::Node getMapDispatchToProps() {
result = getAParameter() and
- result.getARhs().asExpr().(Identifier).getName() = "mapDispatchToProps"
+ result.getASink().asExpr().(Identifier).getName() = "mapDispatchToProps"
}
}
@@ -1130,7 +1130,7 @@ module Redux {
private class StateToPropsStep extends StateStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ConnectCall call |
- pred = call.getMapStateToProps().getReturn().getARhs() and
+ pred = call.getMapStateToProps().getReturn().getASink() and
succ = call.getReactComponent().getADirectPropsAccess()
)
}
@@ -1221,13 +1221,13 @@ module Redux {
// Return value of `i`th callback flows to the `i`th parameter of the last callback.
exists(CreateSelectorCall call, int index |
call.getNumArgument() > 1 and
- pred = call.getSelectorFunction(index).getReturn().getARhs() and
+ pred = call.getSelectorFunction(index).getReturn().getASink() and
succ = call.getLastParameter().getParameter(index).getASource()
)
or
// The result of the last callback is the final result
exists(CreateSelectorCall call |
- pred = call.getLastParameter().getReturn().getARhs() and
+ pred = call.getLastParameter().getReturn().getASink() and
succ = call
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
index f8f3fb08ff0..bd4e2b8c139 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
@@ -9,7 +9,7 @@ module SQL {
abstract class SqlString extends Expr { }
private class SqlStringFromModel extends SqlString {
- SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").getARhs().asExpr() }
+ SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").getASink().asExpr() }
}
/**
@@ -109,7 +109,7 @@ private module MySql {
Credentials() {
exists(API::Node callee, string prop |
callee in [createConnection(), createPool()] and
- this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
+ this = callee.getParameter(0).getMember(prop).getASink().asExpr() and
(
prop = "user" and kind = "user name"
or
@@ -200,7 +200,7 @@ private module Postgres {
QueryString() {
this = any(QueryCall qc).getAQueryArgument().asExpr()
or
- this = API::moduleImport("pg-cursor").getParameter(0).getARhs().asExpr()
+ this = API::moduleImport("pg-cursor").getParameter(0).getASink().asExpr()
}
}
@@ -210,9 +210,9 @@ private module Postgres {
Credentials() {
exists(string prop |
- this = [newClient(), newPool()].getParameter(0).getMember(prop).getARhs().asExpr()
+ this = [newClient(), newPool()].getParameter(0).getMember(prop).getASink().asExpr()
or
- this = pgPromise().getParameter(0).getMember(prop).getARhs().asExpr()
+ this = pgPromise().getParameter(0).getMember(prop).getASink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -494,7 +494,7 @@ private module MsSql {
or
callee = mssql().getMember("ConnectionPool")
) and
- this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
+ this = callee.getParameter(0).getMember(prop).getASink().asExpr() and
(
prop = "user" and kind = "user name"
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index b26d4e56339..9e2315c13ee 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -233,7 +233,7 @@ module Templating {
/** Gets an API node that may flow to `succ` through a template instantiation. */
private API::Node getTemplateInput(DataFlow::SourceNode succ) {
exists(TemplateInstantiation inst, API::Node base, string name |
- base.getARhs() = inst.getTemplateParamsNode() and
+ base.getASink() = inst.getTemplateParamsNode() and
result = base.getMember(name) and
succ =
inst.getTemplateFile()
@@ -244,7 +244,7 @@ module Templating {
)
or
exists(TemplateInstantiation inst, string accessPath |
- result.getARhs() = inst.getTemplateParamForValue(accessPath) and
+ result.getASink() = inst.getTemplateParamForValue(accessPath) and
succ =
inst.getTemplateFile()
.getAnImportedFile*()
@@ -261,7 +261,7 @@ module Templating {
private class TemplateInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
- getTemplateInput(succ).getARhs() = pred
+ getTemplateInput(succ).getASink() = pred
}
}
@@ -321,8 +321,8 @@ module Templating {
result = this.getStringValue()
or
exists(API::Node node |
- this = node.getARhs() and
- result = node.getAValueReachingRhs().getStringValue()
+ this = node.getASink() and
+ result = node.getAValueReachingSink().getStringValue()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
index 8335600f9db..222bcf0830c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
@@ -38,7 +38,7 @@ module TrustedTypes {
private class PolicyInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(PolicyCreation policy, string method |
- pred = policy.getReturn().getMember(method).getParameter(0).getARhs() and
+ pred = policy.getReturn().getMember(method).getParameter(0).getASink() and
succ = policy.getPolicyCallback(method).getParameter(0)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index 0e7031bbe9a..cfabf6d291a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -177,7 +177,7 @@ module Vue {
/** Gets a component which is extended by this one. */
Component getABaseComponent() {
result.getComponentRef().getAValueReachableFromSource() =
- getOwnOptions().getMember(["extends", "mixins"]).getARhs()
+ getOwnOptions().getMember(["extends", "mixins"]).getASink()
}
/**
@@ -200,7 +200,7 @@ module Vue {
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
* or the default export of a single-file component.
*/
- deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().getARhs() }
+ deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().getASink() }
/**
* Gets the class implementing this Vue component, if any.
@@ -208,19 +208,19 @@ module Vue {
* Specifically, this is a class annotated with `@Component` which flows to the options
* object of this Vue component.
*/
- ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingRhs() }
+ ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingSink() }
/**
* Gets the node for option `name` for this component, not including
* those from extended objects and mixins.
*/
- DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).getARhs() }
+ DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).getASink() }
/**
* Gets the node for option `name` for this component, including those from
* extended objects and mixins.
*/
- DataFlow::Node getOption(string name) { result = getOptions().getMember(name).getARhs() }
+ DataFlow::Node getOption(string name) { result = getOptions().getMember(name).getASink() }
/**
* Gets a source node flowing into the option `name` of this component, including those from
@@ -228,7 +228,7 @@ module Vue {
*/
pragma[nomagic]
DataFlow::SourceNode getOptionSource(string name) {
- result = getOptions().getMember(name).getAValueReachingRhs()
+ result = getOptions().getMember(name).getAValueReachingSink()
}
/**
@@ -289,7 +289,7 @@ module Vue {
DataFlow::FunctionNode getWatchHandler(string propName) {
exists(API::Node propWatch |
propWatch = getOptions().getMember("watch").getMember(propName) and
- result = [propWatch, propWatch.getMember("handler")].getAValueReachingRhs()
+ result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink()
)
}
@@ -322,7 +322,7 @@ module Vue {
* Gets a node for a function that will be invoked with `this` bound to this component.
*/
DataFlow::FunctionNode getABoundFunction() {
- result = getOptions().getAMember+().getAValueReachingRhs()
+ result = getOptions().getAMember+().getAValueReachingSink()
or
result = getAsClassComponent().getAnInstanceMember()
}
@@ -539,7 +539,7 @@ module Vue {
override API::Node getOwnOptions() {
// Use the entry point generated by `VueExportEntryPoint`
- result.getARhs() = getModule().getDefaultOrBulkExport()
+ result.getASink() = getModule().getDefaultOrBulkExport()
}
override string toString() { result = file.toString() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
index 5efef1271e7..ea6e64b4e79 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
@@ -75,7 +75,7 @@ module Vuex {
or
exists(API::CallNode call |
call = vuex().getMember("createNamespacedHelpers").getACall() and
- namespace = call.getParameter(0).getAValueReachingRhs().getStringValue() + "/" and
+ namespace = call.getParameter(0).getAValueReachingSink().getStringValue() + "/" and
this = call.getReturn().getMember(helperName).getACall()
)
)
@@ -88,7 +88,7 @@ module Vuex {
pragma[noinline]
string getNamespace() {
getNumArgument() = 2 and
- result = appendToNamespace(namespace, getParameter(0).getAValueReachingRhs().getStringValue())
+ result = appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
or
getNumArgument() = 1 and
result = namespace
@@ -99,17 +99,17 @@ module Vuex {
*/
predicate hasMapping(string localName, string storeName) {
// mapGetters('foo')
- getLastParameter().getAValueReachingRhs().getStringValue() = localName and
+ getLastParameter().getAValueReachingSink().getStringValue() = localName and
storeName = getNamespace() + localName
or
// mapGetters(['foo', 'bar'])
- getLastParameter().getUnknownMember().getAValueReachingRhs().getStringValue() = localName and
+ getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() = localName and
storeName = getNamespace() + localName
or
// mapGetters({foo: 'bar'})
storeName =
getNamespace() +
- getLastParameter().getMember(localName).getAValueReachingRhs().getStringValue() and
+ getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
localName != "*" // ignore special API graph member named "*"
}
@@ -117,10 +117,10 @@ module Vuex {
Vue::Component getVueComponent() {
exists(DataFlow::ObjectLiteralNode obj |
obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
- result.getOwnOptions().getAMember().getARhs() = obj
+ result.getOwnOptions().getAMember().getASink() = obj
)
or
- result.getOwnOptions().getAMember().getARhs() = this
+ result.getOwnOptions().getAMember().getASink() = this
}
}
@@ -146,7 +146,7 @@ module Vuex {
/** Gets a value that is returned by a getter registered with the given name. */
private DataFlow::Node getterPred(string name) {
exists(string prefix, string prop |
- result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().getARhs() and
+ result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().getASink() and
name = prefix + prop
)
}
@@ -212,19 +212,19 @@ module Vuex {
commitCall = commitLikeFunctionRef(kind, prefix).getACall()
|
// commit('name', payload)
- name = prefix + commitCall.getParameter(0).getAValueReachingRhs().getStringValue() and
+ name = prefix + commitCall.getParameter(0).getAValueReachingSink().getStringValue() and
result = commitCall.getArgument(1)
or
// commit({type: 'name', ......})
name =
prefix +
- commitCall.getParameter(0).getMember("type").getAValueReachingRhs().getStringValue() and
+ commitCall.getParameter(0).getMember("type").getAValueReachingSink().getStringValue() and
result = commitCall.getArgument(0)
)
or
// this.name(payload)
// methods: {...mapMutations(['name'])} }
- result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).getARhs()
+ result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).getASink()
}
/** Gets a node that refers the payload of a committed mutation with the given `name.` */
@@ -293,7 +293,7 @@ module Vuex {
/** Gets a value that flows into the given access path of the state. */
DataFlow::Node stateMutationPred(string path) {
- result = stateRefByAccessPath(path).getARhs()
+ result = stateRefByAccessPath(path).getASink()
or
exists(ExtendCall call, string base, string prop |
call.getDestinationOperand() = stateRefByAccessPath(base).getAValueReachableFromSource() and
@@ -325,7 +325,7 @@ module Vuex {
exists(MapHelperCall call |
call.getHelperName() = "mapState" and
component = call.getVueComponent() and
- result = call.getLastParameter().getMember(name).getReturn().getARhs()
+ result = call.getLastParameter().getMember(name).getReturn().getASink()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
index 06059ec2680..3276a0feb30 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
@@ -37,7 +37,7 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(API::Node predNode, API::Node succNode |
Specific::summaryStep(predNode, succNode, kind) and
- pred = predNode.getARhs() and
+ pred = predNode.getASink() and
succ = succNode.getASource()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index a5e366a671f..6cc06e97488 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -151,7 +151,7 @@ API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken toke
or
token.getName() = "Argument" and
token.getAnArgument() = "this" and
- result.getARhs() = node.(DataFlow::CallNode).getReceiver()
+ result.getASink() = node.(DataFlow::CallNode).getReceiver()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
index fb1e4a903db..b627f8fadac 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
@@ -48,7 +48,7 @@ module ExternalApiUsedWithUntrustedData {
}
/** Holds if `node` corresponds to a deep object argument. */
- private predicate isDeepObjectSink(API::Node node) { node.getARhs() instanceof DeepObjectSink }
+ private predicate isDeepObjectSink(API::Node node) { node.getASink() instanceof DeepObjectSink }
/**
* A sanitizer for data flowing to an external API.
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
index d5b2f11f1c1..b762198a25f 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
@@ -211,7 +211,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
- request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().getARhs())
+ request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().getASink())
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
index e3bf02362a4..dd634de28ea 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
@@ -51,7 +51,7 @@ module SqlInjection {
this = any(LdapJS::ClientCall call).getArgument(0)
or
// A search options object, which contains a filter and a baseDN.
- this = any(LdapJS::SearchOptions opt).getARhs()
+ this = any(LdapJS::SearchOptions opt).getASink()
or
// A call to "parseDN", which parses a DN from a string.
this = LdapJS::ldapjs().getMember("parseDN").getACall().getArgument(0)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
index c094d82163c..cb93bd39432 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
@@ -681,7 +681,7 @@ module TaintedPath {
.getMember(["pdf", "screenshot"])
.getParameter(0)
.getMember("path")
- .getARhs()
+ .getASink()
}
}
@@ -702,7 +702,7 @@ module TaintedPath {
.getACall()
.getParameter(1)
.getMember("config")
- .getARhs()
+ .getASink()
}
}
@@ -716,7 +716,7 @@ module TaintedPath {
.getMember(["readPackageAsync", "readPackageSync"])
.getParameter(0)
.getMember("cwd")
- .getARhs()
+ .getASink()
}
}
@@ -726,8 +726,8 @@ module TaintedPath {
private class ShellCwdSink extends TaintedPath::Sink {
ShellCwdSink() {
exists(SystemCommandExecution sys, API::Node opts |
- opts.getARhs() = sys.getOptionsArg() and // assuming that an API::Node exists here.
- this = opts.getMember("cwd").getARhs()
+ opts.getASink() = sys.getOptionsArg() and // assuming that an API::Node exists here.
+ this = opts.getMember("cwd").getASink()
)
}
}
diff --git a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
index 42861fcb9be..c8a36ed78f3 100644
--- a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
+++ b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
@@ -45,7 +45,7 @@ where
or
// the same thing, but with API-nodes if they happen to be available
exists(API::Node tlsInvk | tlsInvk.getAnInvocation() = tlsInvocation() |
- disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").getARhs()
+ disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").getASink()
)
) and
disable.getRhs().(AnalyzedNode).getTheBooleanValue() = false
diff --git a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
index 52617ce675d..1a366c66710 100644
--- a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
+++ b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
@@ -143,7 +143,7 @@ API::CallNode passportAuthenticateCall() {
*/
API::CallNode nonSessionBasedAuthMiddleware() {
result = passportAuthenticateCall() and
- result.getParameter(1).getMember("session").getARhs().mayHaveBooleanValue(false)
+ result.getParameter(1).getMember("session").getASink().mayHaveBooleanValue(false)
}
/**
diff --git a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
index fcb98dc57af..0057d186e52 100644
--- a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
+++ b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
@@ -12,4 +12,4 @@
import javascript
import meta.MetaMetrics
-select projectRoot(), count(any(API::Node nd).getARhs())
+select projectRoot(), count(any(API::Node nd).getASink())
diff --git a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
index 57e7c3d3a99..0a472c090a6 100644
--- a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
+++ b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
@@ -21,7 +21,7 @@ import javascript
private DataFlow::Node getNode(API::Node nd, string kind) {
kind = "def" and
- result = nd.getARhs()
+ result = nd.getASink()
or
kind = "use" and
result = nd.getAValueReachableFromSource()
diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.ql b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
index cbea83fa4be..d4f086923a3 100644
--- a/javascript/ql/test/ApiGraphs/call-nodes/test.ql
+++ b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
@@ -3,9 +3,9 @@ import javascript
class FooCall extends API::CallNode {
FooCall() { this = API::moduleImport("mylibrary").getMember("foo").getACall() }
- DataFlow::Node getFirst() { result = getParameter(0).getMember("value").getARhs() }
+ DataFlow::Node getFirst() { result = getParameter(0).getMember("value").getASink() }
- DataFlow::Node getSecond() { result = getParameter(1).getMember("value").getARhs() }
+ DataFlow::Node getSecond() { result = getParameter(1).getMember("value").getASink() }
}
query predicate values(FooCall call, int first, int second) {
diff --git a/javascript/ql/test/library-tests/Routing/test.ql b/javascript/ql/test/library-tests/Routing/test.ql
index 2593f8263b3..ea546c0722d 100644
--- a/javascript/ql/test/library-tests/Routing/test.ql
+++ b/javascript/ql/test/library-tests/Routing/test.ql
@@ -15,6 +15,6 @@ class Taint extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node node) {
node = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- node = testInstance().getMember("getSink").getAParameter().getARhs()
+ node = testInstance().getMember("getSink").getAParameter().getASink()
}
}
diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql
index a73cccfd94c..ee889cb9161 100644
--- a/javascript/ql/test/library-tests/frameworks/data/test.ql
+++ b/javascript/ql/test/library-tests/frameworks/data/test.ql
@@ -68,7 +68,7 @@ class BasicTaintTracking extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- sink = ModelOutput::getASinkNode("test-sink").getARhs()
+ sink = ModelOutput::getASinkNode("test-sink").getASink()
}
}
@@ -77,7 +77,7 @@ query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
}
query predicate isSink(DataFlow::Node node, string kind) {
- node = ModelOutput::getASinkNode(kind).getARhs()
+ node = ModelOutput::getASinkNode(kind).getASink()
}
class SyntaxErrorTest extends ModelInput::SinkModelCsv {
From ce9c3b3eb59c91ce294e714a3de13f216ab887e6 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:37:30 +0200
Subject: [PATCH 069/125] JS: Also rename predicates on API::EntryPoint
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 18 ++++++++++++------
.../ql/lib/semmle/javascript/frameworks/D3.qll | 4 ++--
.../semmle/javascript/frameworks/History.qll | 4 ++--
.../semmle/javascript/frameworks/Immutable.qll | 4 ++--
.../semmle/javascript/frameworks/Logging.qll | 4 ++--
.../lib/semmle/javascript/frameworks/Nest.qll | 4 ++--
.../lib/semmle/javascript/frameworks/Redux.qll | 4 ++--
.../javascript/frameworks/Templating.qll | 4 ++--
.../javascript/frameworks/TrustedTypes.qll | 4 ++--
.../lib/semmle/javascript/frameworks/Vue.qll | 12 ++++++------
.../data/internal/ApiGraphModelsSpecific.qll | 4 ++--
.../security/dataflow/RemoteFlowSources.qll | 4 ++--
.../custom-entry-point/VerifyAssertions.ql | 4 ++--
13 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 45864ec8ccc..d935819861a 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -562,11 +562,17 @@ module API {
bindingset[this]
EntryPoint() { any() }
- /** Gets a data-flow node that uses this entry point. */
- abstract DataFlow::SourceNode getAUse();
+ /** DEPRECATED. This predicate has been renamed to `getASource`. */
+ deprecated DataFlow::SourceNode getAUse() { none() }
- /** Gets a data-flow node that defines this entry point. */
- abstract DataFlow::Node getARhs();
+ /** DEPRECATED. This predicate has been renamed to `getASink`. */
+ deprecated DataFlow::SourceNode getARhs() { none() }
+
+ /** Gets a data-flow node where a value enters the current codebase through this entry-point. */
+ abstract DataFlow::SourceNode getASource();
+
+ /** Gets a data-flow node where a value leaves the current codebase through this entry-point. */
+ abstract DataFlow::Node getASink();
/** Gets an API-node for this entry point. */
API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) }
@@ -684,7 +690,7 @@ module API {
base = MkRoot() and
exists(EntryPoint e |
lbl = Label::entryPoint(e) and
- rhs = e.getARhs()
+ rhs = e.getASink()
)
or
exists(string m, string prop |
@@ -861,7 +867,7 @@ module API {
base = MkRoot() and
exists(EntryPoint e |
lbl = Label::entryPoint(e) and
- ref = e.getAUse()
+ ref = e.getASource()
)
or
// property reads
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index 7ec3f0d95fe..1c2e45f13af 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -9,9 +9,9 @@ module D3 {
private class D3GlobalEntry extends API::EntryPoint {
D3GlobalEntry() { this = "D3GlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("d3") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("d3") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/** Gets an API node referring to the `d3` module. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
index 3907b80af1d..acb465ac2fe 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
@@ -8,9 +8,9 @@ module History {
private class HistoryGlobalEntry extends API::EntryPoint {
HistoryGlobalEntry() { this = "HistoryLibrary" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("HistoryLibrary") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("HistoryLibrary") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
index 39b0ea201bb..4e6d9f5d894 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
@@ -16,9 +16,9 @@ private module Immutable {
private class ImmutableGlobalEntry extends API::EntryPoint {
ImmutableGlobalEntry() { this = "ImmutableGlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("Immutable") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Immutable") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
index 993df7ff10a..0d3a493d8e2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
@@ -35,9 +35,9 @@ private module Console {
private class ConsoleGlobalEntry extends API::EntryPoint {
ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("console") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("console") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index 0a8ba5ca632..89ec6334ba2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -140,11 +140,11 @@ module NestJS {
private class ValidationNodeEntry extends API::EntryPoint {
ValidationNodeEntry() { this = "ValidationNodeEntry" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
result.(DataFlow::ClassNode).getName() = "ValidationPipe"
}
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/** Gets an API node referring to the constructor of `ValidationPipe` */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index fe05080c25c..50cbd2cdf0e 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -1096,9 +1096,9 @@ module Redux {
private class HeuristicConnectEntryPoint extends API::EntryPoint {
HeuristicConnectEntryPoint() { this = "react-redux-connect" }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
exists(DataFlow::CallNode call |
call.getAnArgument().asExpr().(Identifier).getName() =
["mapStateToProps", "mapDispatchToProps"] and
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index 9e2315c13ee..9227fab3544 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -657,11 +657,11 @@ module Templating {
private class IncludeFunctionAsEntryPoint extends API::EntryPoint {
IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
result = any(TemplatePlaceholderTag tag).getInnerTopLevel().getAVariableUse("include")
}
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
index 222bcf0830c..d9394538d76 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
@@ -14,9 +14,9 @@ module TrustedTypes {
private class TrustedTypesEntry extends API::EntryPoint {
TrustedTypesEntry() { this = "TrustedTypesEntry" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("trustedTypes") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("trustedTypes") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getANode() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index cfabf6d291a..583e90635d1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -9,9 +9,9 @@ module Vue {
private class GlobalVueEntryPoint extends API::EntryPoint {
GlobalVueEntryPoint() { this = "VueEntryPoint" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("Vue") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Vue") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
@@ -22,9 +22,9 @@ module Vue {
private class VueExportEntryPoint extends API::EntryPoint {
VueExportEntryPoint() { this = "VueExportEntryPoint" }
- override DataFlow::SourceNode getAUse() { none() }
+ override DataFlow::SourceNode getASource() { none() }
- override DataFlow::Node getARhs() {
+ override DataFlow::Node getASink() {
result = any(SingleFileComponent c).getModule().getDefaultOrBulkExport()
}
}
@@ -484,14 +484,14 @@ module Vue {
private class VueFileImportEntryPoint extends API::EntryPoint {
VueFileImportEntryPoint() { this = "VueFileImportEntryPoint" }
- override DataFlow::SourceNode getAUse() {
+ override DataFlow::SourceNode getASource() {
exists(Import imprt |
imprt.getImportedPath().resolve() instanceof VueFile and
result = imprt.getImportedModuleNode()
)
}
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index 6cc06e97488..e70777fb83c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -61,9 +61,9 @@ private class GlobalApiEntryPoint extends API::EntryPoint {
this = "GlobalApiEntryPoint:" + global
}
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(global) }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(global) }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
/** Gets the name of the global variable. */
string getGlobal() { result = global }
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
index 5f5cf99bdd2..75a3b642eec 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
@@ -164,9 +164,9 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
string getName() { result = name }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(name) }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(name) }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
index fb8a943f2ca..233f44c34c3 100644
--- a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
+++ b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
@@ -1,9 +1,9 @@
class CustomEntryPoint extends API::EntryPoint {
CustomEntryPoint() { this = "CustomEntryPoint" }
- override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef("CustomEntryPoint") }
+ override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("CustomEntryPoint") }
- override DataFlow::Node getARhs() { none() }
+ override DataFlow::Node getASink() { none() }
}
import ApiGraphs.VerifyAssertions
From 76ba78294ffe0f492bb81dad43d30d8fc1e04e96 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:39:34 +0200
Subject: [PATCH 070/125] JS: Make API::EntryPoint overrides optional
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 ++--
javascript/ql/lib/semmle/javascript/frameworks/D3.qll | 2 --
javascript/ql/lib/semmle/javascript/frameworks/History.qll | 2 --
.../ql/lib/semmle/javascript/frameworks/Immutable.qll | 2 --
javascript/ql/lib/semmle/javascript/frameworks/Logging.qll | 2 --
javascript/ql/lib/semmle/javascript/frameworks/Nest.qll | 2 --
javascript/ql/lib/semmle/javascript/frameworks/Redux.qll | 2 --
.../ql/lib/semmle/javascript/frameworks/Templating.qll | 2 --
.../ql/lib/semmle/javascript/frameworks/TrustedTypes.qll | 2 --
javascript/ql/lib/semmle/javascript/frameworks/Vue.qll | 6 ------
.../frameworks/data/internal/ApiGraphModelsSpecific.qll | 2 --
.../javascript/security/dataflow/RemoteFlowSources.qll | 2 --
.../test/ApiGraphs/custom-entry-point/VerifyAssertions.ql | 2 --
13 files changed, 2 insertions(+), 30 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index d935819861a..a036ae56271 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -569,10 +569,10 @@ module API {
deprecated DataFlow::SourceNode getARhs() { none() }
/** Gets a data-flow node where a value enters the current codebase through this entry-point. */
- abstract DataFlow::SourceNode getASource();
+ DataFlow::SourceNode getASource() { none() }
/** Gets a data-flow node where a value leaves the current codebase through this entry-point. */
- abstract DataFlow::Node getASink();
+ DataFlow::Node getASink() { none() }
/** Gets an API-node for this entry point. */
API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index 1c2e45f13af..9bed73e0a22 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -10,8 +10,6 @@ module D3 {
D3GlobalEntry() { this = "D3GlobalEntry" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("d3") }
-
- override DataFlow::Node getASink() { none() }
}
/** Gets an API node referring to the `d3` module. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
index acb465ac2fe..7b7d3d6042e 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
@@ -9,8 +9,6 @@ module History {
HistoryGlobalEntry() { this = "HistoryLibrary" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("HistoryLibrary") }
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
index 4e6d9f5d894..3a5ef400801 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll
@@ -17,8 +17,6 @@ private module Immutable {
ImmutableGlobalEntry() { this = "ImmutableGlobalEntry" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Immutable") }
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
index 0d3a493d8e2..fb6f34f7d82 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
@@ -36,8 +36,6 @@ private module Console {
ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("console") }
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index 89ec6334ba2..07be0df2b28 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -143,8 +143,6 @@ module NestJS {
override DataFlow::SourceNode getASource() {
result.(DataFlow::ClassNode).getName() = "ValidationPipe"
}
-
- override DataFlow::Node getASink() { none() }
}
/** Gets an API node referring to the constructor of `ValidationPipe` */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index 50cbd2cdf0e..c6b83765d63 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -1096,8 +1096,6 @@ module Redux {
private class HeuristicConnectEntryPoint extends API::EntryPoint {
HeuristicConnectEntryPoint() { this = "react-redux-connect" }
- override DataFlow::Node getASink() { none() }
-
override DataFlow::SourceNode getASource() {
exists(DataFlow::CallNode call |
call.getAnArgument().asExpr().(Identifier).getName() =
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index 9227fab3544..b081ec9e782 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -660,8 +660,6 @@ module Templating {
override DataFlow::SourceNode getASource() {
result = any(TemplatePlaceholderTag tag).getInnerTopLevel().getAVariableUse("include")
}
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
index d9394538d76..3845a30e950 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
@@ -15,8 +15,6 @@ module TrustedTypes {
TrustedTypesEntry() { this = "TrustedTypesEntry" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("trustedTypes") }
-
- override DataFlow::Node getASink() { none() }
}
private API::Node trustedTypesObj() { result = any(TrustedTypesEntry entry).getANode() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index 583e90635d1..452c524b99b 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -10,8 +10,6 @@ module Vue {
GlobalVueEntryPoint() { this = "VueEntryPoint" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("Vue") }
-
- override DataFlow::Node getASink() { none() }
}
/**
@@ -22,8 +20,6 @@ module Vue {
private class VueExportEntryPoint extends API::EntryPoint {
VueExportEntryPoint() { this = "VueExportEntryPoint" }
- override DataFlow::SourceNode getASource() { none() }
-
override DataFlow::Node getASink() {
result = any(SingleFileComponent c).getModule().getDefaultOrBulkExport()
}
@@ -490,8 +486,6 @@ module Vue {
result = imprt.getImportedModuleNode()
)
}
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index e70777fb83c..5ab12d0aab2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -63,8 +63,6 @@ private class GlobalApiEntryPoint extends API::EntryPoint {
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(global) }
- override DataFlow::Node getASink() { none() }
-
/** Gets the name of the global variable. */
string getGlobal() { result = global }
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
index 75a3b642eec..294958504f7 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
@@ -165,8 +165,6 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
string getName() { result = name }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef(name) }
-
- override DataFlow::Node getASink() { none() }
}
/**
diff --git a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
index 233f44c34c3..3502c0ea556 100644
--- a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
+++ b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql
@@ -2,8 +2,6 @@ class CustomEntryPoint extends API::EntryPoint {
CustomEntryPoint() { this = "CustomEntryPoint" }
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("CustomEntryPoint") }
-
- override DataFlow::Node getASink() { none() }
}
import ApiGraphs.VerifyAssertions
From 9fad4b883bc9f30072fac6bb4ab8d59143363488 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:40:04 +0200
Subject: [PATCH 071/125] JS: Autoformat
---
.../ql/lib/semmle/javascript/frameworks/ClassValidator.qll | 3 ++-
javascript/ql/lib/semmle/javascript/frameworks/SQL.qll | 3 ++-
.../lib/semmle/javascript/frameworks/TorrentLibraries.qll | 4 +++-
javascript/ql/lib/semmle/javascript/frameworks/Vue.qll | 6 +-----
javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll | 7 +++----
.../ql/lib/semmle/javascript/frameworks/XmlParsers.qll | 6 +-----
.../javascript/security/dataflow/MissingRateLimiting.qll | 4 +---
.../security/dataflow/XssThroughDomCustomizations.qll | 3 +--
.../library-tests/frameworks/Express/MiddlewareFlow.qll | 4 +++-
9 files changed, 17 insertions(+), 23 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
index cff8da8aaf8..35f966217bd 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll
@@ -39,7 +39,8 @@ module ClassValidator {
/** Holds if the given field has a decorator that sanitizes its value for the purpose of taint tracking. */
predicate isFieldSanitizedByDecorator(FieldDefinition field) {
- field.getADecorator().getExpression().flow() = sanitizingDecorator().getReturn().getAValueReachableFromSource()
+ field.getADecorator().getExpression().flow() =
+ sanitizingDecorator().getReturn().getAValueReachableFromSource()
}
pragma[noinline]
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
index bd4e2b8c139..26833cb3019 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
@@ -440,7 +440,8 @@ private module MsSql {
override TaggedTemplateExpr astNode;
QueryTemplateExpr() {
- mssql().getMember("query").getAValueReachableFromSource() = DataFlow::valueNode(astNode.getTag())
+ mssql().getMember("query").getAValueReachableFromSource() =
+ DataFlow::valueNode(astNode.getTag())
}
override DataFlow::Node getAResult() {
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
index a9ab45ba821..384d6402244 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
@@ -29,7 +29,9 @@ module ParseTorrent {
}
/** Gets a data flow node referring to a parsed torrent. */
- DataFlow::SourceNode parsedTorrentRef() { result = any(ParsedTorrent t).asApiNode().getAValueReachableFromSource() }
+ DataFlow::SourceNode parsedTorrentRef() {
+ result = any(ParsedTorrent t).asApiNode().getAValueReachableFromSource()
+ }
/**
* An access to user-controlled torrent information.
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index 452c524b99b..e375bd091a1 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -700,11 +700,7 @@ module Vue {
.getASource()
or
result =
- router
- .getParameter(0)
- .getMember("scrollBehavior")
- .getParameter([0, 1])
- .getASource()
+ router.getParameter(0).getMember("scrollBehavior").getParameter([0, 1]).getASource()
)
or
result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getASource()
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
index ea6e64b4e79..c6d6be5f768 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
@@ -88,7 +88,8 @@ module Vuex {
pragma[noinline]
string getNamespace() {
getNumArgument() = 2 and
- result = appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
+ result =
+ appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
or
getNumArgument() = 1 and
result = namespace
@@ -303,9 +304,7 @@ module Vuex {
}
/** Gets a value that refers to the given access path of the state. */
- DataFlow::Node stateMutationSucc(string path) {
- result = stateRefByAccessPath(path).getASource()
- }
+ DataFlow::Node stateMutationSucc(string path) { result = stateRefByAccessPath(path).getASource() }
/** Holds if `pred -> succ` is a step from state mutation to state access. */
predicate stateMutationStep(DataFlow::Node pred, DataFlow::Node succ) {
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
index bd57a4ab1f8..665825c3cad 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
@@ -282,11 +282,7 @@ module XML {
override DataFlow::Node getAResult() {
result =
- parser
- .getReturn()
- .getMember(any(string s | s.matches("on%")))
- .getAParameter()
- .getASource()
+ parser.getReturn().getMember(any(string s | s.matches("on%"))).getAParameter().getASource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
index b762198a25f..4c3debcaeea 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
@@ -152,9 +152,7 @@ abstract class RateLimitingMiddleware extends DataFlow::SourceNode {
* A rate limiter constructed using the `express-rate-limit` package.
*/
class ExpressRateLimit extends RateLimitingMiddleware {
- ExpressRateLimit() {
- this = API::moduleImport("express-rate-limit").getReturn().getASource()
- }
+ ExpressRateLimit() { this = API::moduleImport("express-rate-limit").getReturn().getASource() }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index 924176d99c5..792311dd8a9 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -208,8 +208,7 @@ module XssThroughDom {
exists(API::Node useForm |
useForm = API::moduleImport("react-hook-form").getMember("useForm").getReturn()
|
- this =
- useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getASource()
+ this = useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getASource()
or
this = useForm.getMember("getValues").getACall()
)
diff --git a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
index e1a8e825099..9578d5139b5 100644
--- a/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
+++ b/javascript/ql/test/library-tests/frameworks/Express/MiddlewareFlow.qll
@@ -1,3 +1,5 @@
import javascript
-query DataFlow::Node dbUse() { result = API::moduleImport("@example/db").getInstance().getAValueReachableFromSource() }
+query DataFlow::Node dbUse() {
+ result = API::moduleImport("@example/db").getInstance().getAValueReachableFromSource()
+}
From 1ae97d9d54849dfb9c738ae885f84a48136fbd15 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 4 Apr 2022 12:50:23 +0200
Subject: [PATCH 072/125] Apply suggestions from code review
Co-authored-by: Nick Rolfe
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index a036ae56271..c40aa214903 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -56,7 +56,7 @@ module API {
*
* ### Access paths and edge labels
*
- * Nodes in the API graph nodes are associated with a set of access paths, describing a series of operations
+ * Nodes in the API graph are associated with a set of access paths, describing a series of operations
* that may be performed to obtain that value.
*
* For example, the access path `API::moduleImport("lodash").getMember("extend")` represents the action of
@@ -77,7 +77,7 @@ module API {
* Because the implementation of the external library is not visible, it is not known exactly what operations
* it will perform on values that flow there. Instead, the edges starting from a def-node are operations that would
* lead to an observable effect within the current codebase; without knowing for certain if the library will actually perform
- * those operations. (When constructing these edge, we assume the library is somewhat well-behaved).
+ * those operations. (When constructing these edges, we assume the library is somewhat well-behaved).
*
* For example, given this snippet:
* ```js
From 8da96ed40350e28ae1df820108d9874f9bf68562 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:43:50 +0200
Subject: [PATCH 073/125] JS: Update doc comment
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index c40aa214903..1a29265ecb2 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -28,11 +28,11 @@ module API {
* The most basic use of API graphs is typically as follows:
* 1. Start with `API::moduleImport` for the relevant library.
* 2. Follow up with a chain of accessors such as `getMember` describing how to get to the relevant API function.
- * 3. Map the resulting API graph nodes to data-flow nodes, using `getAnImmediateUse` or `getARhs`.
+ * 3. Map the resulting API graph nodes to data-flow nodes, using `getASource` or `getASink`.
*
* For example, a simplified way to get arguments to `underscore.extend` would be
* ```codeql
- * API::moduleImport("underscore").getMember("extend").getParameter(0).getARhs()
+ * API::moduleImport("underscore").getMember("extend").getParameter(0).getASink()
* ```
*
* The most commonly used accessors are `getMember`, `getParameter`, and `getReturn`.
From e2858b7b6435612ae35fe81279789d6e86ed7232 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:46:43 +0200
Subject: [PATCH 074/125] JS: Update ATM code
---
.../experimental/adaptivethreatmodeling/EndpointFeatures.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
index ca7f12b7a33..e2ce4753fb4 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
@@ -144,9 +144,9 @@ private module AccessPaths {
not param = base.getReceiver()
|
result = param and
- name = param.getAnImmediateUse().asExpr().(Parameter).getName()
+ name = param.getASource().asExpr().(Parameter).getName()
or
- param.getAnImmediateUse().asExpr() instanceof DestructuringPattern and
+ param.getASource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
From 777d344dde1f5102d7743982e97da0770c6ae219 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 09:56:34 +0200
Subject: [PATCH 075/125] JS: Fix up qldoc for getAValueReachingSink
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 1a29265ecb2..329840b0b30 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -207,8 +207,10 @@ module API {
DataFlow::Node getASink() { Impl::rhs(this, result) }
/**
- * Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition
- * of the API component represented by this node.
+ * Get a data-flow node that transitively flows to an external library (or in general, any external codebase).
+ *
+ * This is similar to `getASink()` but additionally includes nodes that transitively reach a sink by data flow.
+ * See `getASink()` for examples.
*/
DataFlow::Node getAValueReachingSink() { result = Impl::trackDefNode(this.getASink()) }
From 1e96b1e559607812aae7068cd114cff021f74059 Mon Sep 17 00:00:00 2001
From: Asger Feldthaus
Date: Tue, 5 Apr 2022 10:15:27 +0200
Subject: [PATCH 076/125] JS: Fix typo
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 329840b0b30..d1eee769738 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -191,7 +191,7 @@ module API {
* external library (or in general, any external codebase).
*
* Concretely, this is either an argument passed to a call to external code,
- * or the right-hand side of a property write on an object flows into such a call.
+ * or the right-hand side of a property write on an object flowing into such a call.
*
* For example:
* ```js
From 18dc39484d2ba1e81794ccdcc71fd4cb235ecfe5 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Thu, 7 Apr 2022 10:56:11 +0200
Subject: [PATCH 077/125] Update
javascript/ql/lib/semmle/javascript/ApiGraphs.qll
Co-authored-by: Erik Krogh Kristensen
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index d1eee769738..7bd2ae95d96 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -126,9 +126,7 @@ module API {
*/
pragma[inline]
DataFlow::Node getAValueReachableFromSource() {
- exists(DataFlow::SourceNode src | Impl::use(this, src) |
- Impl::trackUseNode(src).flowsTo(result)
- )
+ Impl::trackUseNode(this.getASource()).flowsTo(result)
}
/**
From f80f8b6630b79c3e3df1657bc6af8e3693c524e4 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 18 May 2022 15:00:04 +0200
Subject: [PATCH 078/125] JS: Update a comment mentioning getARhs
---
javascript/ql/lib/semmle/javascript/frameworks/Vue.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index e375bd091a1..e4d61ec8ed6 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -191,7 +191,7 @@ module Vue {
}
/**
- * DEPRECATED. Use `getOwnOptions().getARhs()`.
+ * DEPRECATED. Use `getOwnOptions().getASink()`.
*
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
* or the default export of a single-file component.
From bc601261ed65e11657c0d428d0bb6b4119218879 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Thu, 19 May 2022 08:47:31 +0200
Subject: [PATCH 079/125] JS: Use 'ql' language for markdown snippets
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 7bd2ae95d96..9a19cb38d10 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -31,7 +31,7 @@ module API {
* 3. Map the resulting API graph nodes to data-flow nodes, using `getASource` or `getASink`.
*
* For example, a simplified way to get arguments to `underscore.extend` would be
- * ```codeql
+ * ```ql
* API::moduleImport("underscore").getMember("extend").getParameter(0).getASink()
* ```
*
From 631527fe49c36514ad96d20d3dfa9598c84f4fee Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 23 May 2022 13:54:50 +0200
Subject: [PATCH 080/125] JS: Rename Node.{getASource -> asSource, getASink ->
asSink}
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 56 +++++++++---------
.../ql/lib/semmle/javascript/JsonParsers.qll | 2 +-
.../ql/lib/semmle/javascript/JsonSchema.qll | 4 +-
.../semmle/javascript/JsonStringifiers.qll | 2 +-
.../semmle/javascript/frameworks/Babel.qll | 2 +-
.../javascript/frameworks/ClientRequests.qll | 10 ++--
.../javascript/frameworks/Credentials.qll | 2 +-
.../lib/semmle/javascript/frameworks/D3.qll | 8 +--
.../semmle/javascript/frameworks/Electron.qll | 2 +-
.../semmle/javascript/frameworks/Files.qll | 12 ++--
.../javascript/frameworks/FormParsers.qll | 6 +-
.../semmle/javascript/frameworks/History.qll | 6 +-
.../javascript/frameworks/HttpProxy.qll | 12 ++--
.../semmle/javascript/frameworks/LdapJS.qll | 4 +-
.../javascript/frameworks/LiveServer.qll | 2 +-
.../semmle/javascript/frameworks/Logging.qll | 2 +-
.../semmle/javascript/frameworks/Markdown.qll | 2 +-
.../lib/semmle/javascript/frameworks/Nest.qll | 10 ++--
.../lib/semmle/javascript/frameworks/Next.qll | 2 +-
.../semmle/javascript/frameworks/NoSQL.qll | 12 ++--
.../javascript/frameworks/NodeJSLib.qll | 8 +--
.../semmle/javascript/frameworks/Prettier.qll | 2 +-
.../javascript/frameworks/Puppeteer.qll | 2 +-
.../semmle/javascript/frameworks/Redux.qll | 58 +++++++++----------
.../lib/semmle/javascript/frameworks/SQL.qll | 14 ++---
.../javascript/frameworks/Snapdragon.qll | 4 +-
.../semmle/javascript/frameworks/SocketIO.qll | 4 +-
.../javascript/frameworks/Templating.qll | 10 ++--
.../frameworks/TorrentLibraries.qll | 4 +-
.../javascript/frameworks/TrustedTypes.qll | 2 +-
.../javascript/frameworks/UriLibraries.qll | 2 +-
.../lib/semmle/javascript/frameworks/Vue.qll | 27 +++++----
.../lib/semmle/javascript/frameworks/Vuex.qll | 24 ++++----
.../javascript/frameworks/XmlParsers.qll | 4 +-
.../frameworks/data/ModelsAsData.qll | 6 +-
.../data/internal/ApiGraphModelsSpecific.qll | 2 +-
.../dataflow/DomBasedXssCustomizations.qll | 2 +-
.../dataflow/ExceptionXssCustomizations.qll | 2 +-
...APIUsedWithUntrustedDataCustomizations.qll | 6 +-
...IndirectCommandInjectionCustomizations.qll | 2 +-
.../security/dataflow/MissingRateLimiting.qll | 8 +--
.../security/dataflow/RemoteFlowSources.qll | 2 +-
.../dataflow/SqlInjectionCustomizations.qll | 2 +-
.../dataflow/TaintedPathCustomizations.qll | 10 ++--
.../dataflow/XssThroughDomCustomizations.qll | 2 +-
.../dataflow/ZipSlipCustomizations.qll | 4 +-
.../CWE-295/DisablingCertificateValidation.ql | 2 +-
.../Security/CWE-352/MissingCsrfMiddleware.ql | 2 +-
.../ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql | 2 +-
.../ql/test/ApiGraphs/VerifyAssertions.qll | 2 +-
.../ql/test/ApiGraphs/call-nodes/test.ql | 4 +-
.../ql/test/ApiGraphs/typed/NodeOfType.ql | 2 +-
.../ql/test/library-tests/Routing/test.ql | 4 +-
.../library-tests/frameworks/data/test.ql | 6 +-
54 files changed, 197 insertions(+), 198 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 9a19cb38d10..205ff21d1fd 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -28,11 +28,11 @@ module API {
* The most basic use of API graphs is typically as follows:
* 1. Start with `API::moduleImport` for the relevant library.
* 2. Follow up with a chain of accessors such as `getMember` describing how to get to the relevant API function.
- * 3. Map the resulting API graph nodes to data-flow nodes, using `getASource` or `getASink`.
+ * 3. Map the resulting API graph nodes to data-flow nodes, using `asSource` or `asSink`.
*
* For example, a simplified way to get arguments to `underscore.extend` would be
* ```ql
- * API::moduleImport("underscore").getMember("extend").getParameter(0).getASink()
+ * API::moduleImport("underscore").getMember("extend").getParameter(0).asSink()
* ```
*
* The most commonly used accessors are `getMember`, `getParameter`, and `getReturn`.
@@ -121,12 +121,12 @@ module API {
/**
* Get a data-flow node where this value may flow after entering the current codebase.
*
- * This is similar to `getASource()` but additionally includes nodes that are transitively reachable by data flow.
- * See `getASource()` for examples.
+ * This is similar to `asSource()` but additionally includes nodes that are transitively reachable by data flow.
+ * See `asSource()` for examples.
*/
pragma[inline]
DataFlow::Node getAValueReachableFromSource() {
- Impl::trackUseNode(this.getASource()).flowsTo(result)
+ Impl::trackUseNode(this.asSource()).flowsTo(result)
}
/**
@@ -134,27 +134,27 @@ module API {
*
* For example:
* ```js
- * // API::moduleImport("fs").getASource()
+ * // API::moduleImport("fs").asSource()
* require('fs');
*
- * // API::moduleImport("fs").getMember("readFile").getASource()
+ * // API::moduleImport("fs").getMember("readFile").asSource()
* require('fs').readFile;
*
- * // API::moduleImport("fs").getMember("readFile").getReturn().getASource()
+ * // API::moduleImport("fs").getMember("readFile").getReturn().asSource()
* require('fs').readFile();
*
* require('fs').readFile(
* filename,
- * // 'y' matched by API::moduleImport("fs").getMember("readFile").getParameter(1).getParameter(0).getASource()
+ * // 'y' matched by API::moduleImport("fs").getMember("readFile").getParameter(1).getParameter(0).asSource()
* y => {
* ...
* });
* ```
*/
- DataFlow::SourceNode getASource() { Impl::use(this, result) }
+ DataFlow::SourceNode asSource() { Impl::use(this, result) }
- /** DEPRECATED. This predicate has been renamed to `getASource`. */
- deprecated DataFlow::SourceNode getAnImmediateUse() { result = this.getASource() }
+ /** DEPRECATED. This predicate has been renamed to `asSource`. */
+ deprecated DataFlow::SourceNode getAnImmediateUse() { result = this.asSource() }
/** DEPRECATED. This predicate has been renamed to `getAValueReachableFromSource`. */
deprecated DataFlow::Node getAUse() { result = this.getAValueReachableFromSource() }
@@ -162,7 +162,7 @@ module API {
/**
* Gets a call to the function represented by this API component.
*/
- CallNode getACall() { result = this.getReturn().getASource() }
+ CallNode getACall() { result = this.getReturn().asSource() }
/**
* Gets a call to the function represented by this API component,
@@ -177,7 +177,7 @@ module API {
/**
* Gets a `new` call to the function represented by this API component.
*/
- NewNode getAnInstantiation() { result = this.getInstance().getASource() }
+ NewNode getAnInstantiation() { result = this.getInstance().asSource() }
/**
* Gets an invocation (with our without `new`) to the function represented by this API component.
@@ -193,27 +193,27 @@ module API {
*
* For example:
* ```js
- * // 'x' is matched by API::moduleImport("foo").getParameter(0).getASink()
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).asSink()
* require('foo')(x);
*
- * // 'x' is matched by API::moduleImport("foo").getParameter(0).getMember("prop").getASink()
+ * // 'x' is matched by API::moduleImport("foo").getParameter(0).getMember("prop").asSink()
* require('foo')({
* prop: x
* });
* ```
*/
- DataFlow::Node getASink() { Impl::rhs(this, result) }
+ DataFlow::Node asSink() { Impl::rhs(this, result) }
/**
* Get a data-flow node that transitively flows to an external library (or in general, any external codebase).
*
- * This is similar to `getASink()` but additionally includes nodes that transitively reach a sink by data flow.
- * See `getASink()` for examples.
+ * This is similar to `asSink()` but additionally includes nodes that transitively reach a sink by data flow.
+ * See `asSink()` for examples.
*/
- DataFlow::Node getAValueReachingSink() { result = Impl::trackDefNode(this.getASink()) }
+ DataFlow::Node getAValueReachingSink() { result = Impl::trackDefNode(this.asSink()) }
- /** DEPRECATED. This predicate has been renamed to `getASink`. */
- deprecated DataFlow::Node getARhs() { result = this.getASink() }
+ /** DEPRECATED. This predicate has been renamed to `asSink`. */
+ deprecated DataFlow::Node getARhs() { result = this.asSink() }
/** DEPRECATED. This predicate has been renamed to `getAValueReachingSink`. */
deprecated DataFlow::Node getAValueReachingRhs() { result = this.getAValueReachingSink() }
@@ -451,7 +451,7 @@ module API {
* In other words, the value of a use of `that` may flow into the right-hand side of a
* definition of this node.
*/
- predicate refersTo(Node that) { this.getASink() = that.getAValueReachableFromSource() }
+ predicate refersTo(Node that) { this.asSink() = that.getAValueReachableFromSource() }
/**
* Gets the data-flow node that gives rise to this node, if any.
@@ -1301,8 +1301,8 @@ module API {
API::Node callee;
InvokeNode() {
- this = callee.getReturn().getASource() or
- this = callee.getInstance().getASource() or
+ this = callee.getReturn().asSource() or
+ this = callee.getInstance().asSource() or
this = Impl::getAPromisifiedInvocation(callee, _, _)
}
@@ -1317,7 +1317,7 @@ module API {
* Gets an API node where a RHS of the node is the `i`th argument to this call.
*/
pragma[noinline]
- private Node getAParameterCandidate(int i) { result.getASink() = this.getArgument(i) }
+ private Node getAParameterCandidate(int i) { result.asSink() = this.getArgument(i) }
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = this.getParameter(_) }
@@ -1328,13 +1328,13 @@ module API {
/** Gets the API node for the return value of this call. */
Node getReturn() {
result = callee.getReturn() and
- result.getASource() = this
+ result.asSource() = this
}
/** Gets the API node for the object constructed by this invocation. */
Node getInstance() {
result = callee.getInstance() and
- result.getASource() = this
+ result.asSource() = this
}
}
diff --git a/javascript/ql/lib/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
index cd4a104679f..e3f1f285a21 100644
--- a/javascript/ql/lib/semmle/javascript/JsonParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonParsers.qll
@@ -29,7 +29,7 @@ private class PlainJsonParserCall extends JsonParserCall {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"parse") or
- callee = API::moduleImport("replicator").getInstance().getMember("decode").getASource() or
+ callee = API::moduleImport("replicator").getInstance().getMember("decode").asSource() or
callee = DataFlow::moduleImport("parse-json") or
callee = DataFlow::moduleImport("json-parse-better-errors") or
callee = DataFlow::moduleImport("json-safe-parse") or
diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
index 4c6540efc13..a298abfd2dd 100644
--- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll
@@ -134,7 +134,7 @@ module JsonSchema {
.ref()
.getMember(["addSchema", "validate", "compile", "compileAsync"])
.getParameter(0)
- .getASink()
+ .asSink()
}
}
}
@@ -184,7 +184,7 @@ module JsonSchema {
override boolean getPolarity() { none() }
override DataFlow::Node getAValidationResultAccess(boolean polarity) {
- result = this.getReturn().getMember("error").getASource() and
+ result = this.getReturn().getMember("error").asSource() and
polarity = false
}
}
diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
index fc6d1dfe1f5..f4cdda89e31 100644
--- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
+++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll
@@ -14,7 +14,7 @@ class JsonStringifyCall extends DataFlow::CallNode {
callee =
DataFlow::moduleMember(["json3", "json5", "flatted", "teleport-javascript", "json-cycle"],
"stringify") or
- callee = API::moduleImport("replicator").getInstance().getMember("encode").getASource() or
+ callee = API::moduleImport("replicator").getInstance().getMember("encode").asSource() or
callee =
DataFlow::moduleImport([
"json-stringify-safe", "json-stable-stringify", "stringify-object",
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
index 2134a84fb10..4280862c6e0 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll
@@ -198,7 +198,7 @@ module Babel {
.getMember(["transform", "transformSync", "transformAsync"])
.getACall() and
pred = call.getArgument(0) and
- succ = [call, call.getParameter(2).getParameter(0).getASource()]
+ succ = [call, call.getParameter(2).getParameter(0).asSource()]
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
index c14d4047602..8e56a36b9bf 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll
@@ -265,7 +265,7 @@ module ClientRequest {
or
responseType = this.getResponseType() and
promise = false and
- result = this.getReturn().getPromisedError().getMember("response").getASource()
+ result = this.getReturn().getPromisedError().getMember("response").asSource()
}
}
@@ -463,7 +463,7 @@ module ClientRequest {
*/
private API::Node netSocketInstantiation(DataFlow::NewNode socket) {
result = API::moduleImport("net").getMember("Socket").getInstance() and
- socket = result.getASource()
+ socket = result.asSource()
}
/**
@@ -827,7 +827,7 @@ module ClientRequest {
class ApolloClientRequest extends ClientRequest::Range, API::InvokeNode {
ApolloClientRequest() { this = apolloUriCallee().getAnInvocation() }
- override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").getASink() }
+ override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").asSink() }
override DataFlow::Node getHost() { none() }
@@ -848,10 +848,10 @@ module ClientRequest {
override DataFlow::Node getUrl() { result = this.getArgument(0) }
- override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").getASink() }
+ override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").asSink() }
override DataFlow::Node getADataNode() {
- result = form.getMember("append").getACall().getParameter(1).getASink()
+ result = form.getMember("append").getACall().getParameter(1).asSink()
}
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
index 925dba2305b..164bc6e8f88 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll
@@ -21,7 +21,7 @@ private class CredentialsFromModel extends CredentialsExpr {
string kind;
CredentialsFromModel() {
- this = ModelOutput::getASinkNode("credentials[" + kind + "]").getASink().asExpr()
+ this = ModelOutput::getASinkNode("credentials[" + kind + "]").asSink().asExpr()
}
override string getCredentialsKind() { result = kind }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
index 9bed73e0a22..76bdeb1324a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll
@@ -69,18 +69,18 @@ module D3 {
D3XssSink() {
exists(API::Node htmlArg |
htmlArg = d3Selection().getMember("html").getParameter(0) and
- this = [htmlArg, htmlArg.getReturn()].getASink()
+ this = [htmlArg, htmlArg.getReturn()].asSink()
)
}
}
private class D3DomValueSource extends DOM::DomValueSource::Range {
D3DomValueSource() {
- this = d3Selection().getMember("each").getReceiver().getASource()
+ this = d3Selection().getMember("each").getReceiver().asSource()
or
- this = d3Selection().getMember("node").getReturn().getASource()
+ this = d3Selection().getMember("node").getReturn().asSource()
or
- this = d3Selection().getMember("nodes").getReturn().getUnknownMember().getASource()
+ this = d3Selection().getMember("nodes").getReturn().getUnknownMember().asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
index f0ab6a75bc5..038f4b8afb3 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll
@@ -56,7 +56,7 @@ module Electron {
}
}
- private API::Node browserObject() { result.getASource() instanceof NewBrowserObject }
+ private API::Node browserObject() { result.asSource() instanceof NewBrowserObject }
/**
* A data flow node whose value may originate from a browser object instantiation.
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
index 8420ade8039..f03f5ee1458 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll
@@ -89,7 +89,7 @@ private API::Node globbyFileNameSource() {
* A file name or an array of file names from the `globby` library.
*/
private class GlobbyFileNameSource extends FileNameSource {
- GlobbyFileNameSource() { this = globbyFileNameSource().getASource() }
+ GlobbyFileNameSource() { this = globbyFileNameSource().asSource() }
}
/** Gets a file name or an array of file names from the `fast-glob` library. */
@@ -116,7 +116,7 @@ private API::Node fastGlobFileName() {
* A file name or an array of file names from the `fast-glob` library.
*/
private class FastGlobFileNameSource extends FileNameSource {
- FastGlobFileNameSource() { this = fastGlobFileName().getASource() }
+ FastGlobFileNameSource() { this = fastGlobFileName().asSource() }
}
/**
@@ -200,7 +200,7 @@ private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, API::
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getASource() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().asSource() }
private API::Node trackFileSource() {
result = this.getParameter([1 .. 2]).getParameter(1)
@@ -223,7 +223,7 @@ private module JsonFile {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getASource() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().asSource() }
private API::Node trackRead() {
this.getCalleeName() = "readFile" and
@@ -272,7 +272,7 @@ private class LoadJsonFile extends FileSystemReadAccess, API::CallNode {
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getADataNode() { result = this.trackRead().getASource() }
+ override DataFlow::Node getADataNode() { result = this.trackRead().asSource() }
private API::Node trackRead() {
this.getCalleeName() = "sync" and result = this.getReturn()
@@ -310,7 +310,7 @@ private class WalkDir extends FileNameProducer, FileSystemAccess, API::CallNode
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
- override DataFlow::Node getAFileName() { result = this.trackFileSource().getASource() }
+ override DataFlow::Node getAFileName() { result = this.trackFileSource().asSource() }
private API::Node trackFileSource() {
not this.getCalleeName() = ["sync", "async"] and
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
index 37d20219ab8..26e0d4fe94f 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll
@@ -15,7 +15,7 @@ private class BusBoyRemoteFlow extends RemoteFlowSource {
.getMember("on")
.getParameter(1)
.getAParameter()
- .getASource()
+ .asSource()
}
override string getSourceType() { result = "parsed user value from Busbuy" }
@@ -49,12 +49,12 @@ private class MultipartyRemoteFlow extends RemoteFlowSource {
MultipartyRemoteFlow() {
exists(API::Node form | form = API::moduleImport("multiparty").getMember("Form").getInstance() |
exists(API::CallNode parse | parse = form.getMember("parse").getACall() |
- this = parse.getParameter(1).getAParameter().getASource()
+ this = parse.getParameter(1).getAParameter().asSource()
)
or
exists(API::CallNode on | on = form.getMember("on").getACall() |
on.getArgument(0).mayHaveStringValue(["part", "file", "field"]) and
- this = on.getParameter(1).getAParameter().getASource()
+ this = on.getParameter(1).getAParameter().asSource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
index 7b7d3d6042e..e076bee9670 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll
@@ -38,11 +38,11 @@ module History {
HistoryLibaryRemoteFlow() {
exists(API::Node loc | loc = [getBrowserHistory(), getHashHistory()].getMember("location") |
- this = loc.getMember("hash").getASource() and kind.isFragment()
+ this = loc.getMember("hash").asSource() and kind.isFragment()
or
- this = loc.getMember("pathname").getASource() and kind.isPath()
+ this = loc.getMember("pathname").asSource() and kind.isPath()
or
- this = loc.getMember("search").getASource() and kind.isQuery()
+ this = loc.getMember("search").asSource() and kind.isQuery()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
index b879207c602..24e694ca8d9 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll
@@ -19,10 +19,10 @@ private module HttpProxy {
.getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").getASink() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").asSink() }
override DataFlow::Node getHost() {
- result = getParameter(0).getMember("target").getMember("host").getASink()
+ result = getParameter(0).getMember("target").getMember("host").asSink()
}
override DataFlow::Node getADataNode() { none() }
@@ -49,10 +49,10 @@ private module HttpProxy {
)
}
- override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").getASink() }
+ override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").asSink() }
override DataFlow::Node getHost() {
- result = getOptionsObject().getMember("target").getMember("host").getASink()
+ result = getOptionsObject().getMember("target").getMember("host").asSink()
}
override DataFlow::Node getADataNode() { none() }
@@ -78,8 +78,8 @@ private module HttpProxy {
ProxyListenerCallback() {
exists(API::CallNode call |
call = any(CreateServerCall server).getReturn().getMember(["on", "once"]).getACall() and
- call.getParameter(0).getASink().mayHaveStringValue(event) and
- this = call.getParameter(1).getASink().getAFunctionValue()
+ call.getParameter(0).asSink().mayHaveStringValue(event) and
+ this = call.getParameter(1).asSink().getAFunctionValue()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
index 9a50f2315fe..1118f05b506 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll
@@ -61,10 +61,10 @@ module LdapJS {
SearchFilter() {
options = ldapClient().getMember("search").getACall().getParameter(1) and
- this = options.getASink()
+ this = options.asSink()
}
- override DataFlow::Node getInput() { result = options.getMember("filter").getASink() }
+ override DataFlow::Node getInput() { result = options.getMember("filter").asSink() }
override DataFlow::Node getOutput() { result = this }
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
index 5272881c7d8..1d7604e0b0c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll
@@ -12,7 +12,7 @@ private module LiveServer {
class ServerDefinition extends HTTP::Servers::StandardServerDefinition {
ServerDefinition() { this = DataFlow::moduleImport("live-server").asExpr() }
- API::Node getImportNode() { result.getASource().asExpr() = this }
+ API::Node getImportNode() { result.asSource().asExpr() = this }
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
index fb6f34f7d82..8f5938f4865 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll
@@ -350,7 +350,7 @@ private module Pino {
// `pino` is installed as the "log" property on the request object in `Express` and similar libraries.
// in `Hapi` the property is "logger".
exists(HTTP::RequestExpr req, API::Node reqNode |
- reqNode.getASource() = req.flow().getALocalSource() and
+ reqNode.asSource() = req.flow().getALocalSource() and
result = reqNode.getMember(["log", "logger"])
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
index d22d64b1adc..492ab0cbcec 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll
@@ -163,7 +163,7 @@ module Markdown {
or
call = API::moduleImport("markdown-it").getMember("Markdown").getAnInvocation()
|
- call.getParameter(0).getMember("html").getASink().mayHaveBooleanValue(true) and
+ call.getParameter(0).getMember("html").asSink().mayHaveBooleanValue(true) and
result = call.getReturn()
)
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
index 07be0df2b28..1799f35beb8 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
@@ -191,7 +191,7 @@ module NestJS {
.getAMember()
.getMember("useFactory")
.getReturn()
- .getASink() = validationPipe().getInstance().getAValueReachableFromSource() and
+ .asSink() = validationPipe().getInstance().getAValueReachableFromSource() and
folder = decorator.getFile().getParentContainer()
)
or
@@ -397,7 +397,7 @@ module NestJS {
}
/** Gets a value returned by the decorator's callback, which becomes the value of the decorated parameter. */
- DataFlow::Node getResult() { result = getParameter(0).getReturn().getASink() }
+ DataFlow::Node getResult() { result = getParameter(0).getReturn().asSink() }
}
/**
@@ -425,7 +425,7 @@ module NestJS {
private class ExpressRequestSource extends Express::RequestSource {
ExpressRequestSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Req", "Request"]).getReturn().getASource()
+ nestjs().getMember(["Req", "Request"]).getReturn().asSource()
or
this =
executionContext()
@@ -433,7 +433,7 @@ module NestJS {
.getReturn()
.getMember("getRequest")
.getReturn()
- .getASource()
+ .asSource()
}
/**
@@ -450,7 +450,7 @@ module NestJS {
private class ExpressResponseSource extends Express::ResponseSource {
ExpressResponseSource() {
this.(DataFlow::ParameterNode).getADecorator() =
- nestjs().getMember(["Res", "Response"]).getReturn().getASource()
+ nestjs().getMember(["Res", "Response"]).getReturn().asSource()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
index d131e6b3674..091aa8ba1af 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll
@@ -252,6 +252,6 @@ module NextJS {
.getParameter(0)
.getParameter(0)
.getMember("router")
- .getASource()
+ .asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
index 122d3b994be..0d2da4b10bb 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll
@@ -20,7 +20,7 @@ deprecated module NoSQL = NoSql;
* Gets a value that has been assigned to the "$where" property of an object that flows to `queryArg`.
*/
private DataFlow::Node getADollarWhereProperty(API::Node queryArg) {
- result = queryArg.getMember("$where").getASink()
+ result = queryArg.getMember("$where").asSink()
}
/**
@@ -418,7 +418,7 @@ private module Mongoose {
param = f.getParameter(0).getParameter(1)
|
exists(DataFlow::MethodCallNode pred |
- // limitation: look at the previous method call
+ // limitation: look at the previous method call
Query::MethodSignatures::returnsDocumentQuery(pred.getMethodName(), asArray) and
pred.getAMethodCall() = f.getACall()
)
@@ -501,7 +501,7 @@ private module Mongoose {
Credentials() {
exists(string prop |
- this = createConnection().getParameter(3).getMember(prop).getASink().asExpr()
+ this = createConnection().getParameter(3).getMember(prop).asSink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -518,7 +518,7 @@ private module Mongoose {
class MongoDBQueryPart extends NoSql::Query {
MongooseFunction f;
- MongoDBQueryPart() { this = f.getQueryArgument().getASink().asExpr() }
+ MongoDBQueryPart() { this = f.getQueryArgument().asSink().asExpr() }
override DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(f.getQueryArgument())
@@ -540,7 +540,7 @@ private module Mongoose {
override DataFlow::Node getAQueryArgument() {
// NB: the complete information is not easily accessible for deeply chained calls
- f.getQueryArgument().getASink() = result
+ f.getQueryArgument().asSink() = result
}
override DataFlow::Node getAResult() {
@@ -770,7 +770,7 @@ private module Redis {
RedisKeyArgument() {
exists(string method, int argIndex |
QuerySignatures::argumentIsAmbiguousKey(method, argIndex) and
- this = redis().getMember(method).getParameter(argIndex).getASink().asExpr()
+ this = redis().getMember(method).getParameter(argIndex).asSink().asExpr()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
index 580109b6cc4..75e222730cc 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll
@@ -739,7 +739,7 @@ module NodeJSLib {
methodName = ["execFile", "execFileSync", "spawn", "spawnSync", "fork"]
) and
// all of the above methods take the command as their first argument
- result = this.getParameter(0).getASink()
+ result = this.getParameter(0).asSink()
}
override DataFlow::Node getACommandArgument() { result = this.getACommandArgument(_) }
@@ -751,7 +751,7 @@ module NodeJSLib {
override DataFlow::Node getArgumentList() {
methodName = ["execFile", "execFileSync", "fork", "spawn", "spawnSync"] and
// all of the above methods take the argument list as their second argument
- result = this.getParameter(1).getASink()
+ result = this.getParameter(1).asSink()
}
override predicate isSync() { methodName.matches("%Sync") }
@@ -759,7 +759,7 @@ module NodeJSLib {
override DataFlow::Node getOptionsArg() {
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode and // looks like argumentlist
- not result = this.getParameter(0).getASink() and
+ not result = this.getParameter(0).asSink() and
// fork/spawn and all sync methos always has options as the last argument
if
methodName.matches("fork%") or
@@ -768,7 +768,7 @@ module NodeJSLib {
then result = this.getLastArgument()
else
// the rest (exec/execFile) has the options argument as their second last.
- result = this.getParameter(this.getNumArgument() - 2).getASink()
+ result = this.getParameter(this.getNumArgument() - 2).asSink()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
index 3b7accdaa26..1277c1ee133 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll
@@ -22,7 +22,7 @@ private module Prettier {
call = API::moduleImport("prettier").getMember("formatWithCursor").getACall()
|
pred = call.getArgument(0) and
- succ = call.getReturn().getMember("formatted").getASource()
+ succ = call.getReturn().getMember("formatted").asSource()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
index 94e98a5bdee..0636b8603b9 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll
@@ -86,7 +86,7 @@ module Puppeteer {
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
}
- override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").getASink() }
+ override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").asSink() }
override DataFlow::Node getHost() { none() }
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
index c6b83765d63..67901528f2b 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
@@ -61,7 +61,7 @@ module Redux {
DataFlow::SourceNode ref() { result = asApiNode().getAValueReachableFromSource() }
/** Gets an API node that refers to this store creation. */
- API::Node asApiNode() { result.getASource() = this }
+ API::Node asApiNode() { result.asSource() = this }
/** Gets the data flow node holding the root reducer for this store. */
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
@@ -94,7 +94,7 @@ module Redux {
}
override DataFlow::Node getReducerArg() {
- result = getParameter(0).getMember("reducer").getASink()
+ result = getParameter(0).getMember("reducer").asSink()
}
}
}
@@ -106,7 +106,7 @@ module Redux {
private API::Node rootState() {
result instanceof RootStateSource
or
- stateStep(rootState().getAValueReachableFromSource(), result.getASource())
+ stateStep(rootState().getAValueReachableFromSource(), result.asSource())
}
/**
@@ -120,7 +120,7 @@ module Redux {
accessPath = joinAccessPaths(base, prop)
)
or
- stateStep(rootStateAccessPath(accessPath).getAValueReachableFromSource(), result.getASource())
+ stateStep(rootStateAccessPath(accessPath).getAValueReachableFromSource(), result.asSource())
}
/**
@@ -193,7 +193,7 @@ module Redux {
CombineReducers() { this = combineReducers().getACall() }
override DataFlow::Node getStateHandlerArg(string prop) {
- result = getParameter(0).getMember(prop).getASink()
+ result = getParameter(0).getMember(prop).asSink()
}
}
@@ -235,7 +235,7 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(DataFlow::PropWrite write |
- result = getParameter(0).getAMember().getASink() and
+ result = getParameter(0).getAMember().asSink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -374,7 +374,7 @@ module Redux {
CreateSliceReducer() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("reducer").getASource()
+ this = call.getReturn().getMember("reducer").asSource()
}
private API::Node getABuilderRef() {
@@ -385,14 +385,14 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(string name |
- result = call.getParameter(0).getMember("reducers").getMember(name).getASink() and
- actionType = call.getReturn().getMember("actions").getMember(name).getASource()
+ result = call.getParameter(0).getMember("reducers").getMember(name).asSink() and
+ actionType = call.getReturn().getMember("actions").getMember(name).asSource()
)
or
// Properties of 'extraReducers':
// { extraReducers: { [action]: reducer }}
exists(DataFlow::PropWrite write |
- result = call.getParameter(0).getMember("extraReducers").getAMember().getASink() and
+ result = call.getParameter(0).getMember("extraReducers").getAMember().asSink() and
write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow()
)
@@ -444,8 +444,8 @@ module Redux {
or
// x -> bindActionCreators({ x, ... })
exists(BindActionCreatorsCall bind, string prop |
- ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).getASink()) and
- result = bind.getReturn().getMember(prop).getASource()
+ ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and
+ result = bind.getReturn().getMember(prop).asSource()
)
or
// x -> combineActions(x, ...)
@@ -580,11 +580,11 @@ module Redux {
MultiAction() {
createActions = API::moduleImport("redux-actions").getMember("createActions").getACall() and
- this = createActions.getReturn().getMember(name).getASource()
+ this = createActions.getReturn().getMember(name).asSource()
}
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
- result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).getASink()) and
+ result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).asSink()) and
async = false
}
@@ -614,12 +614,12 @@ module Redux {
CreateSliceAction() {
call = API::moduleImport("@reduxjs/toolkit").getMember("createSlice").getACall() and
- this = call.getReturn().getMember("actions").getMember(actionName).getASource()
+ this = call.getReturn().getMember("actions").getMember(actionName).asSource()
}
override string getTypeTag() {
exists(string prefix |
- call.getParameter(0).getMember("name").getASink().mayHaveStringValue(prefix) and
+ call.getParameter(0).getMember("name").asSink().mayHaveStringValue(prefix) and
result = prefix + "/" + actionName
)
}
@@ -885,12 +885,12 @@ module Redux {
accessPath = getAffectedStateAccessPath(reducer)
|
pred = function.getReturnNode() and
- succ = rootStateAccessPath(accessPath).getASource()
+ succ = rootStateAccessPath(accessPath).asSource()
or
exists(string suffix, DataFlow::SourceNode base |
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(accessPath + "." + suffix).getASource()
+ succ = rootStateAccessPath(accessPath + "." + suffix).asSource()
)
)
or
@@ -901,7 +901,7 @@ module Redux {
reducer.isRootStateHandler() and
base = [function.getParameter(0), function.getReturnNode().getALocalSource()] and
pred = AccessPath::getAnAssignmentTo(base, suffix) and
- succ = rootStateAccessPath(suffix).getASource()
+ succ = rootStateAccessPath(suffix).asSource()
)
}
@@ -994,7 +994,7 @@ module Redux {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(API::CallNode call |
call = useSelector().getACall() and
- pred = call.getParameter(0).getReturn().getASink() and
+ pred = call.getParameter(0).getReturn().asSink() and
succ = call
)
}
@@ -1046,19 +1046,19 @@ module Redux {
//
// const mapDispatchToProps = { foo }
//
- result = getMapDispatchToProps().getMember(name).getASink()
+ result = getMapDispatchToProps().getMember(name).asSink()
or
//
// const mapDispatchToProps = dispatch => ( { foo } )
//
- result = getMapDispatchToProps().getReturn().getMember(name).getASink()
+ result = getMapDispatchToProps().getReturn().getMember(name).asSink()
or
// Explicitly bound by bindActionCreators:
//
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
//
exists(BindActionCreatorsCall bind |
- bind.flowsTo(getMapDispatchToProps().getReturn().getASink()) and
+ bind.flowsTo(getMapDispatchToProps().getReturn().asSink()) and
result = bind.getOptionArgument(0, name)
)
}
@@ -1113,12 +1113,12 @@ module Redux {
override API::Node getMapStateToProps() {
result = getAParameter() and
- result.getASink().asExpr().(Identifier).getName() = "mapStateToProps"
+ result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
}
override API::Node getMapDispatchToProps() {
result = getAParameter() and
- result.getASink().asExpr().(Identifier).getName() = "mapDispatchToProps"
+ result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps"
}
}
@@ -1128,7 +1128,7 @@ module Redux {
private class StateToPropsStep extends StateStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(ConnectCall call |
- pred = call.getMapStateToProps().getReturn().getASink() and
+ pred = call.getMapStateToProps().getReturn().asSink() and
succ = call.getReactComponent().getADirectPropsAccess()
)
}
@@ -1219,13 +1219,13 @@ module Redux {
// Return value of `i`th callback flows to the `i`th parameter of the last callback.
exists(CreateSelectorCall call, int index |
call.getNumArgument() > 1 and
- pred = call.getSelectorFunction(index).getReturn().getASink() and
- succ = call.getLastParameter().getParameter(index).getASource()
+ pred = call.getSelectorFunction(index).getReturn().asSink() and
+ succ = call.getLastParameter().getParameter(index).asSource()
)
or
// The result of the last callback is the final result
exists(CreateSelectorCall call |
- pred = call.getLastParameter().getReturn().getASink() and
+ pred = call.getLastParameter().getReturn().asSink() and
succ = call
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
index 26833cb3019..edd92614a2c 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll
@@ -9,7 +9,7 @@ module SQL {
abstract class SqlString extends Expr { }
private class SqlStringFromModel extends SqlString {
- SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").getASink().asExpr() }
+ SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").asSink().asExpr() }
}
/**
@@ -109,7 +109,7 @@ private module MySql {
Credentials() {
exists(API::Node callee, string prop |
callee in [createConnection(), createPool()] and
- this = callee.getParameter(0).getMember(prop).getASink().asExpr() and
+ this = callee.getParameter(0).getMember(prop).asSink().asExpr() and
(
prop = "user" and kind = "user name"
or
@@ -200,7 +200,7 @@ private module Postgres {
QueryString() {
this = any(QueryCall qc).getAQueryArgument().asExpr()
or
- this = API::moduleImport("pg-cursor").getParameter(0).getASink().asExpr()
+ this = API::moduleImport("pg-cursor").getParameter(0).asSink().asExpr()
}
}
@@ -210,9 +210,9 @@ private module Postgres {
Credentials() {
exists(string prop |
- this = [newClient(), newPool()].getParameter(0).getMember(prop).getASink().asExpr()
+ this = [newClient(), newPool()].getParameter(0).getMember(prop).asSink().asExpr()
or
- this = pgPromise().getParameter(0).getMember(prop).getASink().asExpr()
+ this = pgPromise().getParameter(0).getMember(prop).asSink().asExpr()
|
prop = "user" and kind = "user name"
or
@@ -383,7 +383,7 @@ private module Sqlite {
/** A call to a Sqlite query method. */
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
QueryCall() {
- this = getAChainingQueryCall().getASource()
+ this = getAChainingQueryCall().asSource()
or
this = database().getMember("prepare").getACall()
}
@@ -495,7 +495,7 @@ private module MsSql {
or
callee = mssql().getMember("ConnectionPool")
) and
- this = callee.getParameter(0).getMember(prop).getASink().asExpr() and
+ this = callee.getParameter(0).getMember(prop).asSink().asExpr() and
(
prop = "user" and kind = "user name"
or
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
index 2569d205473..6f460a842ff 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll
@@ -27,7 +27,7 @@ private module Snapdragon {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(string methodName, API::CallNode set, API::CallNode call, API::Node base |
// the handler, registered with a call to `.set`.
- set = getSetCall+(base.getMember(methodName + "r")).getASource() and
+ set = getSetCall+(base.getMember(methodName + "r")).asSource() and
// the snapdragon instance. The API is chaining, you can also use the instance directly.
base = API::moduleImport("snapdragon").getInstance() and
methodName = ["parse", "compile"] and
@@ -47,7 +47,7 @@ private module Snapdragon {
or
// for compiler handlers the input is the first parameter.
methodName = "compile" and
- succ = set.getParameter(1).getParameter(0).getASource()
+ succ = set.getParameter(1).getParameter(0).asSource()
)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
index 7e0cc61c3ca..e48d674fa74 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll
@@ -41,7 +41,7 @@ module SocketIO {
class ServerObject extends SocketIOObject {
API::Node node;
- ServerObject() { node = newServer() and this = node.getASource() }
+ ServerObject() { node = newServer() and this = node.asSource() }
/** Gets the Api node for this server. */
API::Node asApiNode() { result = node }
@@ -119,7 +119,7 @@ module SocketIO {
API::Node node;
NamespaceBase() {
- this = node.getASource() and
+ this = node.asSource() and
exists(ServerObject srv |
// namespace lookup on `srv`
node = srv.asApiNode().getMember("sockets") and
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
index b081ec9e782..90adf7d7de6 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll
@@ -233,7 +233,7 @@ module Templating {
/** Gets an API node that may flow to `succ` through a template instantiation. */
private API::Node getTemplateInput(DataFlow::SourceNode succ) {
exists(TemplateInstantiation inst, API::Node base, string name |
- base.getASink() = inst.getTemplateParamsNode() and
+ base.asSink() = inst.getTemplateParamsNode() and
result = base.getMember(name) and
succ =
inst.getTemplateFile()
@@ -244,7 +244,7 @@ module Templating {
)
or
exists(TemplateInstantiation inst, string accessPath |
- result.getASink() = inst.getTemplateParamForValue(accessPath) and
+ result.asSink() = inst.getTemplateParamForValue(accessPath) and
succ =
inst.getTemplateFile()
.getAnImportedFile*()
@@ -261,7 +261,7 @@ module Templating {
private class TemplateInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
- getTemplateInput(succ).getASink() = pred
+ getTemplateInput(succ).asSink() = pred
}
}
@@ -321,7 +321,7 @@ module Templating {
result = this.getStringValue()
or
exists(API::Node node |
- this = node.getASink() and
+ this = node.asSink() and
result = node.getAValueReachingSink().getStringValue()
)
}
@@ -716,7 +716,7 @@ module Templating {
override TemplateSyntax getTemplateSyntax() { result.getAPackageName() = engine }
override DataFlow::SourceNode getOutput() {
- result = this.getParameter([1, 2]).getParameter(1).getASource()
+ result = this.getParameter([1, 2]).getParameter(1).asSource()
or
not exists(this.getParameter([1, 2]).getParameter(1)) and
result = this
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
index 384d6402244..29c100234bf 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll
@@ -21,7 +21,7 @@ module ParseTorrent {
node = mod().getReturn() or
node = mod().getMember("remote").getParameter(1).getParameter(1)
) and
- this = node.getASource()
+ this = node.asSource()
}
/** Gets the API node for this torrent object. */
@@ -40,7 +40,7 @@ module ParseTorrent {
UserControlledTorrentInfo() {
exists(API::Node read |
read = any(ParsedTorrent t).asApiNode().getAMember() and
- this = read.getASource()
+ this = read.asSource()
|
exists(string prop |
not (
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
index 3845a30e950..b1b2cc6cf0a 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll
@@ -36,7 +36,7 @@ module TrustedTypes {
private class PolicyInputStep extends DataFlow::SharedFlowStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(PolicyCreation policy, string method |
- pred = policy.getReturn().getMember(method).getParameter(0).getASink() and
+ pred = policy.getReturn().getMember(method).getParameter(0).asSink() and
succ = policy.getPolicyCallback(method).getParameter(0)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
index 6e59884237d..26fff795250 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll
@@ -190,7 +190,7 @@ module Querystringify {
* Gets a data flow source node for member `name` of the querystringify library.
*/
DataFlow::SourceNode querystringifyMember(string name) {
- result = querystringify().getMember(name).getASource()
+ result = querystringify().getMember(name).asSource()
}
/** Gets an API node referring to the `querystringify` module. */
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
index e4d61ec8ed6..95a372025e2 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
@@ -37,7 +37,7 @@ module Vue {
/**
* Gets a reference to the 'Vue' object.
*/
- DataFlow::SourceNode vue() { result = vueLibrary().getASource() }
+ DataFlow::SourceNode vue() { result = vueLibrary().asSource() }
/** Gets an API node referring to a component or `Vue`. */
private API::Node component() {
@@ -173,7 +173,7 @@ module Vue {
/** Gets a component which is extended by this one. */
Component getABaseComponent() {
result.getComponentRef().getAValueReachableFromSource() =
- getOwnOptions().getMember(["extends", "mixins"]).getASink()
+ getOwnOptions().getMember(["extends", "mixins"]).asSink()
}
/**
@@ -196,7 +196,7 @@ module Vue {
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
* or the default export of a single-file component.
*/
- deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().getASink() }
+ deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().asSink() }
/**
* Gets the class implementing this Vue component, if any.
@@ -210,13 +210,13 @@ module Vue {
* Gets the node for option `name` for this component, not including
* those from extended objects and mixins.
*/
- DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).getASink() }
+ DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).asSink() }
/**
* Gets the node for option `name` for this component, including those from
* extended objects and mixins.
*/
- DataFlow::Node getOption(string name) { result = getOptions().getMember(name).getASink() }
+ DataFlow::Node getOption(string name) { result = getOptions().getMember(name).asSink() }
/**
* Gets a source node flowing into the option `name` of this component, including those from
@@ -324,10 +324,10 @@ module Vue {
}
/** Gets an API node referring to an instance of this component. */
- API::Node getInstance() { result.getASource() = getABoundFunction().getReceiver() }
+ API::Node getInstance() { result.asSource() = getABoundFunction().getReceiver() }
/** Gets a data flow node referring to an instance of this component. */
- DataFlow::SourceNode getAnInstanceRef() { result = getInstance().getASource() }
+ DataFlow::SourceNode getAnInstanceRef() { result = getInstance().asSource() }
pragma[noinline]
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
@@ -527,13 +527,13 @@ module Vue {
// of the .vue file.
exists(Import imprt |
imprt.getImportedPath().resolve() = file and
- result.getASource() = imprt.getImportedModuleNode()
+ result.asSource() = imprt.getImportedModuleNode()
)
}
override API::Node getOwnOptions() {
// Use the entry point generated by `VueExportEntryPoint`
- result.getASink() = getModule().getDefaultOrBulkExport()
+ result.asSink() = getModule().getDefaultOrBulkExport()
}
override string toString() { result = file.toString() }
@@ -689,7 +689,7 @@ module Vue {
t.start() and
(
exists(API::Node router | router = API::moduleImport("vue-router") |
- result = router.getInstance().getMember("currentRoute").getASource()
+ result = router.getInstance().getMember("currentRoute").asSource()
or
result =
router
@@ -697,13 +697,12 @@ module Vue {
.getMember(["beforeEach", "beforeResolve", "afterEach"])
.getParameter(0)
.getParameter([0, 1])
- .getASource()
+ .asSource()
or
- result =
- router.getParameter(0).getMember("scrollBehavior").getParameter([0, 1]).getASource()
+ result = router.getParameter(0).getMember("scrollBehavior").getParameter([0, 1]).asSource()
)
or
- result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).getASource()
+ result = routeConfig().getMember("beforeEnter").getParameter([0, 1]).asSource()
or
exists(Component c |
result = c.getABoundFunction().getAFunctionValue().getReceiver().getAPropertyRead("$route")
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
index c6d6be5f768..71132fb531d 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll
@@ -118,10 +118,10 @@ module Vuex {
Vue::Component getVueComponent() {
exists(DataFlow::ObjectLiteralNode obj |
obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
- result.getOwnOptions().getAMember().getASink() = obj
+ result.getOwnOptions().getAMember().asSink() = obj
)
or
- result.getOwnOptions().getAMember().getASink() = this
+ result.getOwnOptions().getAMember().asSink() = this
}
}
@@ -147,7 +147,7 @@ module Vuex {
/** Gets a value that is returned by a getter registered with the given name. */
private DataFlow::Node getterPred(string name) {
exists(string prefix, string prop |
- result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().getASink() and
+ result = storeConfigObject(prefix).getMember("getters").getMember(prop).getReturn().asSink() and
name = prefix + prop
)
}
@@ -155,12 +155,12 @@ module Vuex {
/** Gets a property access that may receive the produced by a getter of the given name. */
private DataFlow::Node getterSucc(string name) {
exists(string prefix, string prop |
- result = storeRef(prefix).getMember("getters").getMember(prop).getASource() and
+ result = storeRef(prefix).getMember("getters").getMember(prop).asSource() and
prop != "*" and
name = prefix + prop
)
or
- result = getAMappedAccess("mapGetters", name).getASource()
+ result = getAMappedAccess("mapGetters", name).asSource()
}
/** Holds if `pred -> succ` is a step from a getter function to a relevant property access. */
@@ -225,7 +225,7 @@ module Vuex {
or
// this.name(payload)
// methods: {...mapMutations(['name'])} }
- result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).getASink()
+ result = getAMappedAccess(getMapHelperForCommitKind(kind), name).getParameter(0).asSink()
}
/** Gets a node that refers the payload of a committed mutation with the given `name.` */
@@ -239,7 +239,7 @@ module Vuex {
.getMember(getStorePropForCommitKind(kind))
.getMember(prop)
.getParameter(1)
- .getASource() and
+ .asSource() and
prop != "*" and
name = prefix + prop
)
@@ -294,7 +294,7 @@ module Vuex {
/** Gets a value that flows into the given access path of the state. */
DataFlow::Node stateMutationPred(string path) {
- result = stateRefByAccessPath(path).getASink()
+ result = stateRefByAccessPath(path).asSink()
or
exists(ExtendCall call, string base, string prop |
call.getDestinationOperand() = stateRefByAccessPath(base).getAValueReachableFromSource() and
@@ -304,7 +304,7 @@ module Vuex {
}
/** Gets a value that refers to the given access path of the state. */
- DataFlow::Node stateMutationSucc(string path) { result = stateRefByAccessPath(path).getASource() }
+ DataFlow::Node stateMutationSucc(string path) { result = stateRefByAccessPath(path).asSource() }
/** Holds if `pred -> succ` is a step from state mutation to state access. */
predicate stateMutationStep(DataFlow::Node pred, DataFlow::Node succ) {
@@ -324,7 +324,7 @@ module Vuex {
exists(MapHelperCall call |
call.getHelperName() = "mapState" and
component = call.getVueComponent() and
- result = call.getLastParameter().getMember(name).getReturn().getASink()
+ result = call.getLastParameter().getMember(name).getReturn().asSink()
)
}
@@ -335,7 +335,7 @@ module Vuex {
predicate mapStateHelperStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(Vue::Component component, string name |
pred = mapStateHelperPred(component, name) and
- succ = pragma[only_bind_out](component).getInstance().getMember(name).getASource()
+ succ = pragma[only_bind_out](component).getInstance().getMember(name).asSource()
)
}
@@ -377,7 +377,7 @@ module Vuex {
/** Gets a package that can be considered an entry point for a Vuex app. */
private PackageJson entryPointPackage() {
- result = getPackageJson(storeRef().getASource().getFile())
+ result = getPackageJson(storeRef().asSource().getFile())
or
// Any package that imports a store-creating package is considered a potential entry point.
packageDependsOn(result, entryPointPackage())
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
index 665825c3cad..355ee485246 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll
@@ -100,7 +100,7 @@ module XML {
}
override DataFlow::Node getAResult() {
- result = [doc(), element(), attr()].getASource()
+ result = [doc(), element(), attr()].asSource()
or
result = element().getMember(["name", "text"]).getACall()
or
@@ -282,7 +282,7 @@ module XML {
override DataFlow::Node getAResult() {
result =
- parser.getReturn().getMember(any(string s | s.matches("on%"))).getAParameter().getASource()
+ parser.getReturn().getMember(any(string s | s.matches("on%"))).getAParameter().asSource()
}
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
index 3276a0feb30..bbed827c3e5 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll
@@ -26,7 +26,7 @@ import Shared::ModelOutput as ModelOutput
* A remote flow source originating from a CSV source row.
*/
private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
- RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").getASource() }
+ RemoteFlowSourceFromCsv() { this = ModelOutput::getASourceNode("remote").asSource() }
override string getSourceType() { result = "Remote flow" }
}
@@ -37,8 +37,8 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
exists(API::Node predNode, API::Node succNode |
Specific::summaryStep(predNode, succNode, kind) and
- pred = predNode.getASink() and
- succ = succNode.getASource()
+ pred = predNode.asSink() and
+ succ = succNode.asSource()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
index 5ab12d0aab2..861a44a2cfc 100644
--- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
+++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll
@@ -149,7 +149,7 @@ API::Node getExtraSuccessorFromInvoke(API::InvokeNode node, AccessPathToken toke
or
token.getName() = "Argument" and
token.getAnArgument() = "this" and
- result.getASink() = node.(DataFlow::CallNode).getReceiver()
+ result.asSink() = node.(DataFlow::CallNode).getReceiver()
}
/**
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
index 879a03ca029..b23f52d7c22 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll
@@ -49,7 +49,7 @@ module DomBasedXss {
or
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
exists(DataFlow::NewNode instance |
- instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getASource() and
+ instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().asSource() and
this = instance.getArgument(0) and
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
index 26c5ded744f..4605de869a0 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll
@@ -62,7 +62,7 @@ module ExceptionXss {
*/
private class JsonSchemaValidationError extends Source {
JsonSchemaValidationError() {
- this = any(JsonSchema::Ajv::Instance i).getAValidationError().getASource()
+ this = any(JsonSchema::Ajv::Instance i).getAValidationError().asSource()
or
this = any(JsonSchema::Joi::JoiValidationErrorRead r).getAValidationResultAccess(_)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
index b627f8fadac..fb663a755ed 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll
@@ -48,7 +48,7 @@ module ExternalApiUsedWithUntrustedData {
}
/** Holds if `node` corresponds to a deep object argument. */
- private predicate isDeepObjectSink(API::Node node) { node.getASink() instanceof DeepObjectSink }
+ private predicate isDeepObjectSink(API::Node node) { node.asSink() instanceof DeepObjectSink }
/**
* A sanitizer for data flowing to an external API.
@@ -165,9 +165,9 @@ module ExternalApiUsedWithUntrustedData {
not param = base.getReceiver()
|
result = param and
- name = param.getASource().asExpr().(Parameter).getName()
+ name = param.asSource().asExpr().(Parameter).getName()
or
- param.getASource().asExpr() instanceof DestructuringPattern and
+ param.asSource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
index 9a0fb9c4e2c..108ce5d8e62 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll
@@ -74,7 +74,7 @@ module IndirectCommandInjection {
].getMember("parse").getACall()
or
// `require('commander').myCmdArgumentName`
- this = commander().getAMember().getASource()
+ this = commander().getAMember().asSource()
or
// `require('commander').opt()` => `{a: ..., b: ...}`
this = commander().getMember("opts").getACall()
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
index 4c3debcaeea..f1a27697725 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll
@@ -152,7 +152,7 @@ abstract class RateLimitingMiddleware extends DataFlow::SourceNode {
* A rate limiter constructed using the `express-rate-limit` package.
*/
class ExpressRateLimit extends RateLimitingMiddleware {
- ExpressRateLimit() { this = API::moduleImport("express-rate-limit").getReturn().getASource() }
+ ExpressRateLimit() { this = API::moduleImport("express-rate-limit").getReturn().asSource() }
}
/**
@@ -160,7 +160,7 @@ class ExpressRateLimit extends RateLimitingMiddleware {
*/
class BruteForceRateLimit extends RateLimitingMiddleware {
BruteForceRateLimit() {
- this = API::moduleImport("express-brute").getInstance().getMember("prevent").getASource()
+ this = API::moduleImport("express-brute").getInstance().getMember("prevent").asSource()
}
}
@@ -172,7 +172,7 @@ class BruteForceRateLimit extends RateLimitingMiddleware {
*/
class RouteHandlerLimitedByExpressLimiter extends RateLimitingMiddleware {
RouteHandlerLimitedByExpressLimiter() {
- this = API::moduleImport("express-limiter").getReturn().getReturn().getASource()
+ this = API::moduleImport("express-limiter").getReturn().getReturn().asSource()
}
override Routing::Node getRoutingNode() {
@@ -209,7 +209,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
- request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().getASink())
+ request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().asSink())
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
index 294958504f7..bb60b5bc23e 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll
@@ -173,7 +173,7 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
private class ExternalRemoteFlowSource extends RemoteFlowSource {
RemoteFlowSourceAccessPath ap;
- ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().getASource() }
+ ExternalRemoteFlowSource() { Stages::Taint::ref() and this = ap.resolve().asSource() }
override string getSourceType() { result = ap.getSourceType() }
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
index dd634de28ea..42ffe2ea3c3 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll
@@ -51,7 +51,7 @@ module SqlInjection {
this = any(LdapJS::ClientCall call).getArgument(0)
or
// A search options object, which contains a filter and a baseDN.
- this = any(LdapJS::SearchOptions opt).getASink()
+ this = any(LdapJS::SearchOptions opt).asSink()
or
// A call to "parseDN", which parses a DN from a string.
this = LdapJS::ldapjs().getMember("parseDN").getACall().getArgument(0)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
index cb93bd39432..03b1211326a 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll
@@ -681,7 +681,7 @@ module TaintedPath {
.getMember(["pdf", "screenshot"])
.getParameter(0)
.getMember("path")
- .getASink()
+ .asSink()
}
}
@@ -702,7 +702,7 @@ module TaintedPath {
.getACall()
.getParameter(1)
.getMember("config")
- .getASink()
+ .asSink()
}
}
@@ -716,7 +716,7 @@ module TaintedPath {
.getMember(["readPackageAsync", "readPackageSync"])
.getParameter(0)
.getMember("cwd")
- .getASink()
+ .asSink()
}
}
@@ -726,8 +726,8 @@ module TaintedPath {
private class ShellCwdSink extends TaintedPath::Sink {
ShellCwdSink() {
exists(SystemCommandExecution sys, API::Node opts |
- opts.getASink() = sys.getOptionsArg() and // assuming that an API::Node exists here.
- this = opts.getMember("cwd").getASink()
+ opts.asSink() = sys.getOptionsArg() and // assuming that an API::Node exists here.
+ this = opts.getMember("cwd").asSink()
)
}
}
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
index 792311dd8a9..3f0f569eff6 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll
@@ -208,7 +208,7 @@ module XssThroughDom {
exists(API::Node useForm |
useForm = API::moduleImport("react-hook-form").getMember("useForm").getReturn()
|
- this = useForm.getMember("handleSubmit").getParameter(0).getParameter(0).getASource()
+ this = useForm.getMember("handleSubmit").getParameter(0).getParameter(0).asSource()
or
this = useForm.getMember("getValues").getACall()
)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
index 2e417d018db..1cb58609d13 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll
@@ -103,7 +103,7 @@ module ZipSlip {
class JSZipFilesSource extends Source instanceof DynamicPropertyAccess::EnumeratedPropName {
JSZipFilesSource() {
super.getSourceObject() =
- API::moduleImport("jszip").getInstance().getMember("files").getASource()
+ API::moduleImport("jszip").getInstance().getMember("files").asSource()
}
}
@@ -116,7 +116,7 @@ module ZipSlip {
.getMember(["forEach", "filter"])
.getParameter(0)
.getParameter(0)
- .getASource()
+ .asSource()
}
}
diff --git a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
index c8a36ed78f3..7fd76a635ec 100644
--- a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
+++ b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql
@@ -45,7 +45,7 @@ where
or
// the same thing, but with API-nodes if they happen to be available
exists(API::Node tlsInvk | tlsInvk.getAnInvocation() = tlsInvocation() |
- disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").getASink()
+ disable.getRhs() = tlsInvk.getAParameter().getMember("rejectUnauthorized").asSink()
)
) and
disable.getRhs().(AnalyzedNode).getTheBooleanValue() = false
diff --git a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
index 1a366c66710..6240615a6e7 100644
--- a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
+++ b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql
@@ -143,7 +143,7 @@ API::CallNode passportAuthenticateCall() {
*/
API::CallNode nonSessionBasedAuthMiddleware() {
result = passportAuthenticateCall() and
- result.getParameter(1).getMember("session").getASink().mayHaveBooleanValue(false)
+ result.getParameter(1).getMember("session").asSink().mayHaveBooleanValue(false)
}
/**
diff --git a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
index 0057d186e52..4f07f9be7fe 100644
--- a/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
+++ b/javascript/ql/src/meta/ApiGraphs/ApiGraphRhsNodes.ql
@@ -12,4 +12,4 @@
import javascript
import meta.MetaMetrics
-select projectRoot(), count(any(API::Node nd).getASink())
+select projectRoot(), count(any(API::Node nd).asSink())
diff --git a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
index 0a472c090a6..2f4b80ee1c6 100644
--- a/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
+++ b/javascript/ql/test/ApiGraphs/VerifyAssertions.qll
@@ -21,7 +21,7 @@ import javascript
private DataFlow::Node getNode(API::Node nd, string kind) {
kind = "def" and
- result = nd.getASink()
+ result = nd.asSink()
or
kind = "use" and
result = nd.getAValueReachableFromSource()
diff --git a/javascript/ql/test/ApiGraphs/call-nodes/test.ql b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
index d4f086923a3..8f0ea4bfc8b 100644
--- a/javascript/ql/test/ApiGraphs/call-nodes/test.ql
+++ b/javascript/ql/test/ApiGraphs/call-nodes/test.ql
@@ -3,9 +3,9 @@ import javascript
class FooCall extends API::CallNode {
FooCall() { this = API::moduleImport("mylibrary").getMember("foo").getACall() }
- DataFlow::Node getFirst() { result = getParameter(0).getMember("value").getASink() }
+ DataFlow::Node getFirst() { result = getParameter(0).getMember("value").asSink() }
- DataFlow::Node getSecond() { result = getParameter(1).getMember("value").getASink() }
+ DataFlow::Node getSecond() { result = getParameter(1).getMember("value").asSink() }
}
query predicate values(FooCall call, int first, int second) {
diff --git a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
index b703739ff04..10c5133f9a8 100644
--- a/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
+++ b/javascript/ql/test/ApiGraphs/typed/NodeOfType.ql
@@ -1,4 +1,4 @@
import javascript
from string mod, string tp
-select mod, tp, API::Node::ofType(mod, tp).getASource()
+select mod, tp, API::Node::ofType(mod, tp).asSource()
diff --git a/javascript/ql/test/library-tests/Routing/test.ql b/javascript/ql/test/library-tests/Routing/test.ql
index ea546c0722d..b427f710894 100644
--- a/javascript/ql/test/library-tests/Routing/test.ql
+++ b/javascript/ql/test/library-tests/Routing/test.ql
@@ -9,12 +9,12 @@ class Taint extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node node) {
node.(DataFlow::CallNode).getCalleeName() = "source"
or
- node = testInstance().getMember("getSource").getReturn().getASource()
+ node = testInstance().getMember("getSource").getReturn().asSource()
}
override predicate isSink(DataFlow::Node node) {
node = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- node = testInstance().getMember("getSink").getAParameter().getASink()
+ node = testInstance().getMember("getSink").getAParameter().asSink()
}
}
diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql
index ee889cb9161..ff385f3afff 100644
--- a/javascript/ql/test/library-tests/frameworks/data/test.ql
+++ b/javascript/ql/test/library-tests/frameworks/data/test.ql
@@ -62,13 +62,13 @@ class BasicTaintTracking extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) {
source.(DataFlow::CallNode).getCalleeName() = "source"
or
- source = ModelOutput::getASourceNode("test-source").getASource()
+ source = ModelOutput::getASourceNode("test-source").asSource()
}
override predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()
or
- sink = ModelOutput::getASinkNode("test-sink").getASink()
+ sink = ModelOutput::getASinkNode("test-sink").asSink()
}
}
@@ -77,7 +77,7 @@ query predicate taintFlow(DataFlow::Node source, DataFlow::Node sink) {
}
query predicate isSink(DataFlow::Node node, string kind) {
- node = ModelOutput::getASinkNode(kind).getASink()
+ node = ModelOutput::getASinkNode(kind).asSink()
}
class SyntaxErrorTest extends ModelInput::SinkModelCsv {
From 87cbf7b2162d1d7cafeb2049e7072c218a5e54a2 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Tue, 24 May 2022 11:38:19 +0200
Subject: [PATCH 081/125] JS: Update ATM code
---
.../experimental/adaptivethreatmodeling/EndpointFeatures.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
index e2ce4753fb4..f146f569684 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/experimental/adaptivethreatmodeling/EndpointFeatures.qll
@@ -144,9 +144,9 @@ private module AccessPaths {
not param = base.getReceiver()
|
result = param and
- name = param.getASource().asExpr().(Parameter).getName()
+ name = param.asSource().asExpr().(Parameter).getName()
or
- param.getASource().asExpr() instanceof DestructuringPattern and
+ param.asSource().asExpr() instanceof DestructuringPattern and
result = param.getMember(name)
)
}
From 572f247fd9b20d6740485aa0c09469ac9ff5eb48 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 12:34:29 +0200
Subject: [PATCH 082/125] bump the supported ECMAScript version to 2022
---
docs/codeql/support/reusables/versions-compilers.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst
index a5f68cb64e1..b1e0350aa49 100644
--- a/docs/codeql/support/reusables/versions-compilers.rst
+++ b/docs/codeql/support/reusables/versions-compilers.rst
@@ -20,7 +20,7 @@
Java,"Java 7 to 18 [4]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [5]_",``.java``
- JavaScript,ECMAScript 2021 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
+ JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py``
Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
TypeScript [8]_,"2.6-4.6",Standard TypeScript compiler,"``.ts``, ``.tsx``"
From fc25d14af7aaebff28c0c1a80f4e8c0a6839ae37 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 12:37:28 +0200
Subject: [PATCH 083/125] add change note
---
javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md
diff --git a/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md b/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md
new file mode 100644
index 00000000000..389b7c9044b
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2022-05-24-ecmascript-2022.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* All new ECMAScript 2022 features are now supported.
From 1717d17fb3cb236d650bbca7d8643073901dee9e Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 12:41:27 +0200
Subject: [PATCH 084/125] add flow step for Array.prototype.at
---
.../ql/lib/semmle/javascript/Arrays.qll | 6 +-
.../library-tests/Arrays/DataFlow.expected | 1 +
.../ql/test/library-tests/Arrays/arrays.js | 2 +
.../library-tests/Arrays/printAst.expected | 207 ++++++++++--------
.../TaintTracking/BasicTaintTracking.expected | 1 +
.../library-tests/TaintTracking/arrays.js | 2 +
6 files changed, 129 insertions(+), 90 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll
index 0433b1b5681..c129e9a31b2 100644
--- a/javascript/ql/lib/semmle/javascript/Arrays.qll
+++ b/javascript/ql/lib/semmle/javascript/Arrays.qll
@@ -75,7 +75,7 @@ module ArrayTaintTracking {
succ.(DataFlow::SourceNode).getAMethodCall("splice") = call
or
// `e = array.pop()`, `e = array.shift()`, or similar: if `array` is tainted, then so is `e`.
- call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice"]) and
+ call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice", "at"]) and
succ = call
or
// `e = Array.from(x)`: if `x` is tainted, then so is `e`.
@@ -199,13 +199,13 @@ private module ArrayDataFlow {
}
/**
- * A step for retrieving an element from an array using `.pop()` or `.shift()`.
+ * A step for retrieving an element from an array using `.pop()`, `.shift()`, or `.at()`.
* E.g. `array.pop()`.
*/
private class ArrayPopStep extends DataFlow::SharedFlowStep {
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
exists(DataFlow::MethodCallNode call |
- call.getMethodName() = ["pop", "shift"] and
+ call.getMethodName() = ["pop", "shift", "at"] and
prop = arrayElement() and
obj = call.getReceiver() and
element = call
diff --git a/javascript/ql/test/library-tests/Arrays/DataFlow.expected b/javascript/ql/test/library-tests/Arrays/DataFlow.expected
index fd98b66d4db..2f5179075cf 100644
--- a/javascript/ql/test/library-tests/Arrays/DataFlow.expected
+++ b/javascript/ql/test/library-tests/Arrays/DataFlow.expected
@@ -11,6 +11,7 @@
| arrays.js:2:16:2:23 | "source" | arrays.js:74:8:74:29 | arr.fin ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:77:8:77:35 | arrayFi ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:81:10:81:10 | x |
+| arrays.js:2:16:2:23 | "source" | arrays.js:84:8:84:17 | arr.at(-1) |
| arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e |
| arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() |
| arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() |
diff --git a/javascript/ql/test/library-tests/Arrays/arrays.js b/javascript/ql/test/library-tests/Arrays/arrays.js
index 9b445760f47..2dfb203cd54 100644
--- a/javascript/ql/test/library-tests/Arrays/arrays.js
+++ b/javascript/ql/test/library-tests/Arrays/arrays.js
@@ -80,4 +80,6 @@
for (const x of uniq(arr)) {
sink(x); // NOT OK
}
+
+ sink(arr.at(-1)); // NOT OK
});
diff --git a/javascript/ql/test/library-tests/Arrays/printAst.expected b/javascript/ql/test/library-tests/Arrays/printAst.expected
index 8364838f8bd..c6e097c770e 100644
--- a/javascript/ql/test/library-tests/Arrays/printAst.expected
+++ b/javascript/ql/test/library-tests/Arrays/printAst.expected
@@ -1,9 +1,9 @@
nodes
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | [ParExpr] (functi ... } }) |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.label | [ExprStmt] (functi ... } }); |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.order | 1 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | [FunctionExpr] functio ... K } } |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | [BlockStmt] { let ... K } } |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | [ParExpr] (functi ... T OK }) |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.label | [ExprStmt] (functi ... OK }); |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.order | 1 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | [FunctionExpr] functio ... OT OK } |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | [BlockStmt] { let ... OT OK } |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | [DeclStmt] let source = ... |
| arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | [VarDecl] source |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | [VariableDeclarator] source = "source" |
@@ -339,6 +339,17 @@ nodes
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | [CallExpr] sink(x) |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | semmle.label | [ExprStmt] sink(x); |
| arrays.js:81:10:81:10 | [VarRef] x | semmle.label | [VarRef] x |
+| arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | [VarRef] sink |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | [CallExpr] sink(arr.at(-1)) |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | [ExprStmt] sink(arr.at(-1)); |
+| arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | [VarRef] arr |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | [DotExpr] arr.at |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | [MethodCallExpr] arr.at(-1) |
+| arrays.js:84:12:84:13 | [Label] at | semmle.label | [Label] at |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | [UnaryExpr] -1 |
+| arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | [Literal] 1 |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
@@ -386,88 +397,90 @@ nodes
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
edges
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | 1 |
-| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.order | 1 |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | 1 |
-| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.order | 1 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | 5 |
-| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.order | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
-| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | 1 |
+| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.order | 1 |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | 1 |
+| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.order | 1 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | 5 |
+| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.order | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | 39 |
+| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.order | 39 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | 1 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.order | 1 |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | 1 |
@@ -1052,6 +1065,22 @@ edges
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.order | 1 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | 0 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.order | 0 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | 1 |
+| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.order | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.order | 1 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.label | 2 |
+| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.order | 2 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | 0 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.order | 0 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
+| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | 1 |
+| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.order | 1 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:8:12:8:17 | [VarRef] source | semmle.label | 0 |
@@ -1140,6 +1169,10 @@ edges
| file://:0:0:0:0 | (Arguments) | arrays.js:80:24:80:26 | [VarRef] arr | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.order | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | 0 |
+| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:16:12:16:12 | [SimpleParameter] e | semmle.label | 0 |
diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
index 12fdd69e80f..cd41461e4a8 100644
--- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
+++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected
@@ -17,6 +17,7 @@ typeInferenceMismatch
| arrays.js:2:15:2:22 | source() | arrays.js:11:10:11:28 | union(["bla"], foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:14:10:14:18 | flat(foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:19:10:19:12 | res |
+| arrays.js:2:15:2:22 | source() | arrays.js:21:10:21:19 | foo.at(-1) |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:4:8:4:8 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:13:10:13:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:19:10:19:10 | x |
diff --git a/javascript/ql/test/library-tests/TaintTracking/arrays.js b/javascript/ql/test/library-tests/TaintTracking/arrays.js
index b99e2058d80..b9daf4943b3 100644
--- a/javascript/ql/test/library-tests/TaintTracking/arrays.js
+++ b/javascript/ql/test/library-tests/TaintTracking/arrays.js
@@ -17,4 +17,6 @@ function test() {
return prev + '' + current + '';
}, '');
sink(res); // NOT OK
+
+ sink(foo.at(-1)); // NOT OK
}
From 2a97dd9f6f36ab50dc8224f56a618810b6eade74 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 13:47:41 +0200
Subject: [PATCH 085/125] add support for Object.hasOwn(obj, key)
---
.../javascript/MembershipCandidates.qll | 8 +++
.../javascript/dataflow/TaintTracking.qll | 16 +++---
.../ql/src/Declarations/UnusedProperty.ql | 2 +
.../CWE-915/PrototypePollutingFunction.ql | 14 +++++
.../TaintBarriers/tests.expected | 14 +++++
.../test/library-tests/TaintBarriers/tst.js | 19 +++++++
.../Declarations/UnusedProperty/tst.js | 8 +++
.../ServerSideUrlRedirect.expected | 15 +++++
.../CWE-601/ServerSideUrlRedirect/express.js | 16 +++++-
.../PrototypePollutingFunction.expected | 57 +++++++++++++++++++
.../PrototypePollutingFunction/tests.js | 12 ++++
11 files changed, 171 insertions(+), 10 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
index 6c51b487f43..57d477c182b 100644
--- a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
+++ b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
@@ -234,6 +234,14 @@ module MembershipCandidate {
test = hasOwn and
hasOwn.calls(membersNode, "hasOwnProperty")
)
+ or
+ exists(DataFlow::CallNode hasOwn |
+ hasOwn = DataFlow::globalVarRef("Object").getAMemberCall("hasOwn")
+ |
+ hasOwn.getArgument(0).asExpr() = membersNode and
+ this = hasOwn.getArgument(1) and
+ test = hasOwn.asExpr()
+ )
}
override DataFlow::Node getTest() { result = test.flow() }
diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
index dde1c004946..0f82ec2e8e6 100644
--- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
+++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll
@@ -1027,18 +1027,16 @@ module TaintTracking {
class WhitelistContainmentCallSanitizer extends AdditionalSanitizerGuardNode,
DataFlow::MethodCallNode {
WhitelistContainmentCallSanitizer() {
- exists(string name |
- name = "contains" or
- name = "has" or
- name = "hasOwnProperty"
- |
- this.getMethodName() = name
- )
+ this.getMethodName() = ["contains", "has", "hasOwnProperty", "hasOwn"]
}
override predicate sanitizes(boolean outcome, Expr e) {
- outcome = true and
- e = this.getArgument(0).asExpr()
+ exists(int propertyIndex |
+ if this.getMethodName() = "hasOwn" then propertyIndex = 1 else propertyIndex = 0
+ |
+ outcome = true and
+ e = this.getArgument(propertyIndex).asExpr()
+ )
}
override predicate appliesTo(Configuration cfg) { any() }
diff --git a/javascript/ql/src/Declarations/UnusedProperty.ql b/javascript/ql/src/Declarations/UnusedProperty.ql
index 19d43a09db2..1a8f9ee291f 100644
--- a/javascript/ql/src/Declarations/UnusedProperty.ql
+++ b/javascript/ql/src/Declarations/UnusedProperty.ql
@@ -27,6 +27,8 @@ predicate hasUnknownPropertyRead(LocalObject obj) {
or
exists(obj.getAPropertyRead("hasOwnProperty"))
or
+ obj.flowsTo(DataFlow::globalVarRef("Object").getAMemberCall("hasOwn").getArgument(0))
+ or
exists(obj.getAPropertyRead("propertyIsEnumerable"))
}
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
index 2fb9cece66d..61483e4a9cb 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
@@ -286,6 +286,7 @@ class PropNameTracking extends DataFlow::Configuration {
node instanceof DenyListEqualityGuard or
node instanceof AllowListEqualityGuard or
node instanceof HasOwnPropertyGuard or
+ node instanceof HasOwnGuard or
node instanceof InExprGuard or
node instanceof InstanceOfGuard or
node instanceof TypeofGuard or
@@ -355,6 +356,19 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode {
}
}
+/** Sanitizer guard for calls to `Object.hasOwn(obj, prop)`. */
+class HasOwnGuard extends DataFlow::BarrierGuardNode, CallNode {
+ HasOwnGuard() {
+ this = DataFlow::globalVarRef("Object").getAMemberCall("hasOwn") and
+ // same check as in HasOwnPropertyGuard
+ not arePropertiesEnumerated(getArgument(0).getALocalSource())
+ }
+
+ override predicate blocks(boolean outcome, Expr e) {
+ e = getArgument(1).asExpr() and outcome = true
+ }
+}
+
/**
* A sanitizer guard for `key in dst`.
*
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tests.expected b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
index 33f06a2ff23..d8cca36c7ca 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tests.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
@@ -43,6 +43,10 @@ isLabeledBarrier
| ExampleConfiguration | tst.js:361:14:361:14 | v | taint |
| ExampleConfiguration | tst.js:371:14:371:16 | o.p | taint |
| ExampleConfiguration | tst.js:378:14:378:17 | o[p] | taint |
+| ExampleConfiguration | tst.js:392:14:392:14 | v | taint |
+| ExampleConfiguration | tst.js:394:14:394:16 | v.p | taint |
+| ExampleConfiguration | tst.js:396:14:396:18 | v.p.q | taint |
+| ExampleConfiguration | tst.js:402:14:402:14 | v | taint |
isSanitizer
| ExampleConfiguration | tst.js:176:18:176:18 | v |
sanitizingGuard
@@ -122,6 +126,13 @@ sanitizingGuard
| tst.js:370:9:370:29 | o.p == ... listed" | tst.js:370:16:370:29 | "white-listed" | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:11:377:14 | o[p] | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:19:377:32 | "white-listed" | true |
+| tst.js:391:9:391:27 | o.hasOwnProperty(v) | tst.js:391:26:391:26 | v | true |
+| tst.js:393:16:393:36 | o.hasOw ... ty(v.p) | tst.js:393:33:393:35 | v.p | true |
+| tst.js:395:16:395:38 | o.hasOw ... (v.p.q) | tst.js:395:33:395:37 | v.p.q | true |
+| tst.js:397:16:397:36 | o.hasOw ... ty(v.p) | tst.js:397:33:397:35 | v.p | true |
+| tst.js:399:16:399:41 | o.hasOw ... "p.q"]) | tst.js:399:33:399:40 | v["p.q"] | true |
+| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:30:401:30 | o | true |
+| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:33:401:33 | v | true |
taintedSink
| tst.js:2:13:2:20 | SOURCE() | tst.js:3:10:3:10 | v |
| tst.js:2:13:2:20 | SOURCE() | tst.js:8:14:8:14 | v |
@@ -186,3 +197,6 @@ taintedSink
| tst.js:367:13:367:20 | SOURCE() | tst.js:373:14:373:16 | o.p |
| tst.js:367:13:367:20 | SOURCE() | tst.js:380:14:380:17 | o[p] |
| tst.js:367:13:367:20 | SOURCE() | tst.js:382:14:382:17 | o[p] |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:389:10:389:14 | v.p.q |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:398:14:398:14 | v |
+| tst.js:388:13:388:20 | SOURCE() | tst.js:400:14:400:18 | v.p.q |
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js
index 265c5ac6210..20102605af1 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tst.js
+++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js
@@ -383,3 +383,22 @@ function constantComparisonSanitizer2() {
}
}
}
+
+function propertySanitization(o) {
+ var v = SOURCE();
+ SINK(v.p.q); // NOT OK
+
+ if (o.hasOwnProperty(v)) {
+ SINK(v); // OK
+ } else if (o.hasOwnProperty(v.p)) {
+ SINK(v.p); // OK
+ } else if (o.hasOwnProperty(v.p.q)) {
+ SINK(v.p.q); // OK
+ } else if (o.hasOwnProperty(v.p)) {
+ SINK(v); // NOT OK
+ } else if (o.hasOwnProperty(v["p.q"])) {
+ SINK(v.p.q); // NOT OK
+ } else if (Object.hasOwn(o, v)) {
+ SINK(v); // OK
+ }
+}
diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
index 26cd1a110bb..847f30bd944 100644
--- a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
+++ b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.js
@@ -81,3 +81,11 @@
(function(){
({ unusedProp: 42 }, 42);
});
+
+(function(){
+ var foo = {
+ unused: 42
+ };
+ foo.unused = 42;
+ Object.hasOwn(foo, blab);
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
index a4654b29c27..5fa8a043558 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
@@ -50,6 +50,13 @@ nodes
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
+| express.js:150:7:150:34 | target |
+| express.js:150:16:150:34 | req.param("target") |
+| express.js:150:16:150:34 | req.param("target") |
+| express.js:155:18:155:23 | target |
+| express.js:155:18:155:23 | target |
+| express.js:160:18:160:23 | target |
+| express.js:160:18:160:23 | target |
| koa.js:6:6:6:27 | url |
| koa.js:6:12:6:27 | ctx.query.target |
| koa.js:6:12:6:27 | ctx.query.target |
@@ -140,6 +147,12 @@ edges
| express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo |
+| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
+| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
+| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
+| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
+| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
+| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:8:18:8:20 | url |
@@ -199,6 +212,8 @@ edges
| express.js:136:16:136:36 | 'u' + r ... ms.user | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | Untrusted URL redirection due to $@. | express.js:136:22:136:36 | req.params.user | user-provided value |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | Untrusted URL redirection due to $@. | express.js:143:16:143:28 | req.query.foo | user-provided value |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | Untrusted URL redirection due to $@. | express.js:146:16:146:24 | query.foo | user-provided value |
+| express.js:155:18:155:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:155:18:155:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
+| express.js:160:18:160:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:160:18:160:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
| koa.js:7:15:7:17 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:7:15:7:17 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:8:15:8:26 | `${url}${x}` | koa.js:6:12:6:27 | ctx.query.target | koa.js:8:15:8:26 | `${url}${x}` | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:14:16:14:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:14:16:14:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
index b319315b985..667d6f89f05 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/express.js
@@ -144,4 +144,18 @@ app.get("foo", (req, res) => {
});
app.get("bar", ({query}, res) => {
res.redirect(query.foo); // NOT OK
-})
\ No newline at end of file
+})
+
+app.get('/some/path', function(req, res) {
+ let target = req.param("target");
+
+ if (SAFE_TARGETS.hasOwnProperty(target))
+ res.redirect(target); // OK: request parameter is checked against whitelist
+ else
+ res.redirect(target); // NOT OK
+
+ if (Object.hasOwn(SAFE_TARGETS, target))
+ res.redirect(target); // OK: request parameter is checked against whitelist
+ else
+ res.redirect(target); // NOT OK
+});
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
index 23b21f12460..65161e5df90 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
@@ -1478,6 +1478,31 @@ nodes
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
+| tests.js:552:35:552:37 | src |
+| tests.js:552:35:552:37 | src |
+| tests.js:553:14:553:16 | key |
+| tests.js:553:14:553:16 | key |
+| tests.js:553:14:553:16 | key |
+| tests.js:557:43:557:45 | src |
+| tests.js:557:43:557:45 | src |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:17:559:19 | key |
+| tests.js:559:24:559:26 | src |
+| tests.js:559:24:559:26 | src |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key |
+| tests.js:559:28:559:30 | key |
edges
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
@@ -3347,6 +3372,38 @@ edges
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
+| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
+| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
+| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
+| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
+| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:24:559:31 | src[key] | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
#select
| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst |
| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target |
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
index d54081d6e7d..7059e613801 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
@@ -548,3 +548,15 @@ function mergeUsingCallback3(dst, src) {
}
});
}
+
+function copyHasOwnProperty2(dst, src) {
+ for (let key in src) {
+ // Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
+ // since '__proto__' and 'constructor' are not own properties of the destination object.
+ if (Object.hasOwn(dst, key)) {
+ copyHasOwnProperty2(dst[key], src[key]);
+ } else {
+ dst[key] = src[key]; // OK
+ }
+ }
+}
From 82c6c22d50a60f50ae470768c2658c3bf790e221 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 14:13:53 +0200
Subject: [PATCH 086/125] make a model for hasOwnProperty calls and similar
---
.../javascript/MembershipCandidates.qll | 16 ++----
.../lib/semmle/javascript/StandardLibrary.qll | 32 +++++++++++
.../CWE-915/PrototypePollutingFunction.ql | 23 +-------
.../TaintBarriers/tests.expected | 1 -
.../PrototypePollutingFunction.expected | 57 +++++++++++++++++++
.../PrototypePollutingFunction/tests.js | 12 ++++
6 files changed, 108 insertions(+), 33 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
index 57d477c182b..607c55c9d02 100644
--- a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
+++ b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll
@@ -229,18 +229,10 @@ module MembershipCandidate {
membersNode = inExpr.getRightOperand()
)
or
- exists(MethodCallExpr hasOwn |
- this = hasOwn.getArgument(0).flow() and
- test = hasOwn and
- hasOwn.calls(membersNode, "hasOwnProperty")
- )
- or
- exists(DataFlow::CallNode hasOwn |
- hasOwn = DataFlow::globalVarRef("Object").getAMemberCall("hasOwn")
- |
- hasOwn.getArgument(0).asExpr() = membersNode and
- this = hasOwn.getArgument(1) and
- test = hasOwn.asExpr()
+ exists(HasOwnPropertyCall hasOwn |
+ this = hasOwn.getProperty() and
+ test = hasOwn.asExpr() and
+ membersNode = hasOwn.getObject().asExpr()
)
}
diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
index d99cd0e7e0d..9366c76d9cc 100644
--- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
+++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll
@@ -192,3 +192,35 @@ class StringSplitCall extends DataFlow::MethodCallNode {
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = this.getAPropertyRead(i.toString()) }
}
+
+/**
+ * A call to `Object.prototype.hasOwnProperty`, `Object.hasOwn`, or a library that implements
+ * the same functionality.
+ */
+class HasOwnPropertyCall extends DataFlow::Node instanceof DataFlow::CallNode {
+ DataFlow::Node object;
+ DataFlow::Node property;
+
+ HasOwnPropertyCall() {
+ // Make sure we handle reflective calls since libraries love to do that.
+ super.getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() =
+ "hasOwnProperty" and
+ object = super.getReceiver() and
+ property = super.getArgument(0)
+ or
+ this =
+ [
+ DataFlow::globalVarRef("Object").getAMemberCall("hasOwn"), //
+ DataFlow::moduleImport("has").getACall(), //
+ LodashUnderscore::member("has").getACall()
+ ] and
+ object = super.getArgument(0) and
+ property = super.getArgument(1)
+ }
+
+ /** Gets the object whose property is being checked. */
+ DataFlow::Node getObject() { result = object }
+
+ /** Gets the property being checked. */
+ DataFlow::Node getProperty() { result = property }
+}
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
index 61483e4a9cb..9e5b873f663 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
@@ -286,7 +286,6 @@ class PropNameTracking extends DataFlow::Configuration {
node instanceof DenyListEqualityGuard or
node instanceof AllowListEqualityGuard or
node instanceof HasOwnPropertyGuard or
- node instanceof HasOwnGuard or
node instanceof InExprGuard or
node instanceof InstanceOfGuard or
node instanceof TypeofGuard or
@@ -340,32 +339,16 @@ class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod
* but the destination object generally doesn't. It is therefore only a sanitizer when
* used on the destination object.
*/
-class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode {
+class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPropertyCall {
HasOwnPropertyGuard() {
- // Make sure we handle reflective calls since libraries love to do that.
- getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() = "hasOwnProperty" and
- exists(getReceiver()) and
// Try to avoid `src.hasOwnProperty` by requiring that the receiver
// does not locally have its properties enumerated. Typically there is no
// reason to enumerate the properties of the destination object.
- not arePropertiesEnumerated(getReceiver().getALocalSource())
+ not arePropertiesEnumerated(super.getObject().getALocalSource())
}
override predicate blocks(boolean outcome, Expr e) {
- e = getArgument(0).asExpr() and outcome = true
- }
-}
-
-/** Sanitizer guard for calls to `Object.hasOwn(obj, prop)`. */
-class HasOwnGuard extends DataFlow::BarrierGuardNode, CallNode {
- HasOwnGuard() {
- this = DataFlow::globalVarRef("Object").getAMemberCall("hasOwn") and
- // same check as in HasOwnPropertyGuard
- not arePropertiesEnumerated(getArgument(0).getALocalSource())
- }
-
- override predicate blocks(boolean outcome, Expr e) {
- e = getArgument(1).asExpr() and outcome = true
+ e = super.getProperty().asExpr() and outcome = true
}
}
diff --git a/javascript/ql/test/library-tests/TaintBarriers/tests.expected b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
index d8cca36c7ca..3ee1223b87d 100644
--- a/javascript/ql/test/library-tests/TaintBarriers/tests.expected
+++ b/javascript/ql/test/library-tests/TaintBarriers/tests.expected
@@ -131,7 +131,6 @@ sanitizingGuard
| tst.js:395:16:395:38 | o.hasOw ... (v.p.q) | tst.js:395:33:395:37 | v.p.q | true |
| tst.js:397:16:397:36 | o.hasOw ... ty(v.p) | tst.js:397:33:397:35 | v.p | true |
| tst.js:399:16:399:41 | o.hasOw ... "p.q"]) | tst.js:399:33:399:40 | v["p.q"] | true |
-| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:30:401:30 | o | true |
| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:33:401:33 | v | true |
taintedSink
| tst.js:2:13:2:20 | SOURCE() | tst.js:3:10:3:10 | v |
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
index 65161e5df90..f16f3e4ef55 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/PrototypePollutingFunction.expected
@@ -1503,6 +1503,31 @@ nodes
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key |
| tests.js:559:28:559:30 | key |
+| tests.js:564:35:564:37 | src |
+| tests.js:564:35:564:37 | src |
+| tests.js:565:14:565:16 | key |
+| tests.js:565:14:565:16 | key |
+| tests.js:565:14:565:16 | key |
+| tests.js:569:43:569:45 | src |
+| tests.js:569:43:569:45 | src |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:17:571:19 | key |
+| tests.js:571:24:571:26 | src |
+| tests.js:571:24:571:26 | src |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key |
+| tests.js:571:28:571:30 | key |
edges
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
@@ -3404,6 +3429,38 @@ edges
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
+| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
+| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
+| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
+| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
+| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:24:571:31 | src[key] | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
+| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
#select
| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst |
| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target |
diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
index 7059e613801..a1fc92a5776 100644
--- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
+++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingFunction/tests.js
@@ -560,3 +560,15 @@ function copyHasOwnProperty2(dst, src) {
}
}
}
+
+function copyHasOwnProperty3(dst, src) {
+ for (let key in src) {
+ // Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
+ // since '__proto__' and 'constructor' are not own properties of the destination object.
+ if (_.has(dst, key)) {
+ copyHasOwnProperty3(dst[key], src[key]);
+ } else {
+ dst[key] = src[key]; // OK
+ }
+ }
+}
From 2da001ebd759a54d7b52d88d03df265281d27bac Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 24 May 2022 22:55:59 +0200
Subject: [PATCH 087/125] bump TypeScript version to stable release
---
javascript/extractor/lib/typescript/package.json | 2 +-
javascript/extractor/lib/typescript/yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json
index 858719325db..6898986e749 100644
--- a/javascript/extractor/lib/typescript/package.json
+++ b/javascript/extractor/lib/typescript/package.json
@@ -2,7 +2,7 @@
"name": "typescript-parser-wrapper",
"private": true,
"dependencies": {
- "typescript": "4.7.1-rc"
+ "typescript": "4.7.2"
},
"scripts": {
"build": "tsc --project tsconfig.json",
diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock
index 4fbd1283dda..3a10c8452f0 100644
--- a/javascript/extractor/lib/typescript/yarn.lock
+++ b/javascript/extractor/lib/typescript/yarn.lock
@@ -6,7 +6,7 @@
version "12.7.11"
resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446
-typescript@4.7.1-rc:
- version "4.7.1-rc"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.1-rc.tgz#23a0517d36c56de887b4457f29e2d265647bbd7c"
- integrity sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==
+typescript@4.7.2:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
+ integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
From 877a9d8bcc8cbc903b34933e7be0a590496dcc3e Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 25 May 2022 09:41:17 +0200
Subject: [PATCH 088/125] JS: Fix FP in
js/type-confusion-through-parameter-tampering
---
...onfusionThroughParameterTamperingQuery.qll | 28 +++++++++++++
...onfusionThroughParameterTampering.expected | 20 +++++++++
.../test/query-tests/Security/CWE-843/tst.js | 41 +++++++++++++++----
3 files changed, 80 insertions(+), 9 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
index da6b698d97f..1b6cc31f653 100644
--- a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
+++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingQuery.qll
@@ -27,4 +27,32 @@ class Configuration extends DataFlow::Configuration {
}
override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier }
+
+ override predicate isBarrierGuard(DataFlow::BarrierGuardNode guard) {
+ guard instanceof TypeOfTestBarrier or
+ guard instanceof IsArrayBarrier
+ }
+}
+
+private class TypeOfTestBarrier extends DataFlow::BarrierGuardNode, DataFlow::ValueNode {
+ override EqualityTest astNode;
+ private Expr operand;
+
+ TypeOfTestBarrier() { astNode.getAnOperand().(TypeofExpr).getOperand() = operand }
+
+ override predicate blocks(boolean outcome, Expr e) {
+ e = operand and
+ if astNode.getAnOperand().getStringValue() = ["string", "object"]
+ then outcome = [true, false] // separation between string/array removes type confusion in both branches
+ else outcome = astNode.getPolarity() // block flow to branch where value is neither string nor array
+ }
+}
+
+private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallNode {
+ IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray").getACall() }
+
+ override predicate blocks(boolean outcome, Expr e) {
+ e = getArgument(0).asExpr() and
+ outcome = [true, false] // separation between string/array removes type confusion in both branches
+ }
}
diff --git a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
index 5c560d8c4ca..997d8968fcc 100644
--- a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
@@ -32,6 +32,18 @@ nodes
| tst.js:81:9:81:9 | p |
| tst.js:82:9:82:9 | p |
| tst.js:82:9:82:9 | p |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:90:5:90:12 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:92:9:92:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo |
edges
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
@@ -63,6 +75,10 @@ edges
| tst.js:80:23:80:23 | p | tst.js:81:9:81:9 | p |
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
| tst.js:80:23:80:23 | p | tst.js:82:9:82:9 | p |
+| tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo |
+| tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo |
+| tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo |
+| tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo |
#select
| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |
| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:5:15:5:27 | req.query.foo | this HTTP request parameter |
@@ -75,3 +91,7 @@ edges
| tst.js:46:5:46:7 | foo | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:46:5:46:7 | foo | Potential type confusion as $@ may be either an array or a string. | tst.js:45:15:45:35 | ctx.req ... ery.foo | this HTTP request parameter |
| tst.js:81:9:81:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:81:9:81:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter |
| tst.js:82:9:82:9 | p | tst.js:77:25:77:38 | req.query.path | tst.js:82:9:82:9 | p | Potential type confusion as $@ may be either an array or a string. | tst.js:77:25:77:38 | req.query.path | this HTTP request parameter |
+| tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo | tst.js:90:5:90:12 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:90:5:90:12 | data.foo | this HTTP request parameter |
+| tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo | tst.js:92:9:92:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:92:9:92:16 | data.foo | this HTTP request parameter |
+| tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo | tst.js:95:9:95:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:95:9:95:16 | data.foo | this HTTP request parameter |
+| tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo | tst.js:98:9:98:16 | data.foo | Potential type confusion as $@ may be either an array or a string. | tst.js:98:9:98:16 | data.foo | this HTTP request parameter |
diff --git a/javascript/ql/test/query-tests/Security/CWE-843/tst.js b/javascript/ql/test/query-tests/Security/CWE-843/tst.js
index 82650bcf054..d49f7ce53d2 100644
--- a/javascript/ql/test/query-tests/Security/CWE-843/tst.js
+++ b/javascript/ql/test/query-tests/Security/CWE-843/tst.js
@@ -1,7 +1,7 @@
var express = require('express');
var Koa = require('koa');
-express().get('/some/path', function(req, res) {
+express().get('/some/path', function (req, res) {
var foo = req.query.foo;
foo.indexOf(); // NOT OK
@@ -41,38 +41,38 @@ express().get('/some/path', function(req, res) {
foo.length; // NOT OK
});
-new Koa().use(function handler(ctx){
+new Koa().use(function handler(ctx) {
var foo = ctx.request.query.foo;
foo.indexOf(); // NOT OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
var foo = req.params.foo;
foo.indexOf(); // OK
});
-express().get('/some/path/:foo', function(req, res) {
- if (req.query.path.length) {} // OK
+express().get('/some/path/:foo', function (req, res) {
+ if (req.query.path.length) { } // OK
req.query.path.length == 0; // OK
!req.query.path.length; // OK
req.query.path.length > 0; // OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
let p = req.query.path;
if (typeof p !== 'string') {
- return;
+ return;
}
while (p.length) { // OK
- p = p.substr(1);
+ p = p.substr(1);
}
p.length < 1; // OK
});
-express().get('/some/path/:foo', function(req, res) {
+express().get('/some/path/:foo', function (req, res) {
let someObject = {};
safeGet(someObject, req.query.path).bar = 'baz'; // prototype pollution here - but flagged in `safeGet`
});
@@ -84,3 +84,26 @@ function safeGet(obj, p) {
}
return obj[p];
}
+
+express().get('/foo', function (req, res) {
+ let data = req.query;
+ data.foo.indexOf(); // NOT OK
+ if (typeof data.foo !== 'undefined') {
+ data.foo.indexOf(); // NOT OK
+ }
+ if (typeof data.foo !== 'string') {
+ data.foo.indexOf(); // OK
+ }
+ if (typeof data.foo !== 'undefined') {
+ data.foo.indexOf(); // NOT OK
+ }
+});
+
+express().get('/foo', function (req, res) {
+ let data = req.query;
+ if (Array.isArray(data)) {
+ data.indexOf(); // OK
+ } else {
+ data.indexOf(); // OK
+ }
+});
From efa895e91279d87b0c5f6108ea7ca8e40671c359 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 25 May 2022 10:33:39 +0000
Subject: [PATCH 089/125] update expected output
---
.../TypeScript/Types/printAst.expected | 1392 ++++++++++-------
.../TypeScript/Types/tests.expected | 63 +-
2 files changed, 886 insertions(+), 569 deletions(-)
diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
index 8ebfa8473ec..bbe3148efb3 100644
--- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
+++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected
@@ -95,6 +95,10 @@ nodes
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
+| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
@@ -1140,186 +1144,314 @@ nodes
| tst.ts:293:7:293:23 | [MethodCallExpr] payload.toFixed() | semmle.label | [MethodCallExpr] payload.toFixed() |
| tst.ts:293:7:293:24 | [ExprStmt] payload.toFixed(); | semmle.label | [ExprStmt] payload.toFixed(); |
| tst.ts:293:15:293:21 | [Label] toFixed | semmle.label | [Label] toFixed |
-| tst.ts:298:1:376:1 | [FunctionDeclStmt] functio ... ring } | semmle.label | [FunctionDeclStmt] functio ... ring } |
-| tst.ts:298:1:376:1 | [FunctionDeclStmt] functio ... ring } | semmle.order | 61 |
-| tst.ts:298:10:298:15 | [VarDecl] foo_47 | semmle.label | [VarDecl] foo_47 |
-| tst.ts:298:19:376:1 | [BlockStmt] { con ... ring } | semmle.label | [BlockStmt] { con ... ring } |
-| tst.ts:299:3:299:23 | [DeclStmt] const key = ... | semmle.label | [DeclStmt] const key = ... |
-| tst.ts:299:9:299:11 | [VarDecl] key | semmle.label | [VarDecl] key |
-| tst.ts:299:9:299:22 | [VariableDeclarator] key = Symbol() | semmle.label | [VariableDeclarator] key = Symbol() |
-| tst.ts:299:15:299:20 | [VarRef] Symbol | semmle.label | [VarRef] Symbol |
-| tst.ts:299:15:299:22 | [CallExpr] Symbol() | semmle.label | [CallExpr] Symbol() |
-| tst.ts:301:3:301:60 | [DeclStmt] const numberOrString = ... | semmle.label | [DeclStmt] const numberOrString = ... |
-| tst.ts:301:9:301:22 | [VarDecl] numberOrString | semmle.label | [VarDecl] numberOrString |
-| tst.ts:301:9:301:59 | [VariableDeclarator] numberO ... "hello" | semmle.label | [VariableDeclarator] numberO ... "hello" |
-| tst.ts:301:26:301:29 | [VarRef] Math | semmle.label | [VarRef] Math |
-| tst.ts:301:26:301:36 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
-| tst.ts:301:26:301:38 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
-| tst.ts:301:26:301:44 | [BinaryExpr] Math.random() < 0.5 | semmle.label | [BinaryExpr] Math.random() < 0.5 |
-| tst.ts:301:26:301:59 | [ConditionalExpr] Math.ra ... "hello" | semmle.label | [ConditionalExpr] Math.ra ... "hello" |
-| tst.ts:301:31:301:36 | [Label] random | semmle.label | [Label] random |
-| tst.ts:301:42:301:44 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
-| tst.ts:301:48:301:49 | [Literal] 42 | semmle.label | [Literal] 42 |
-| tst.ts:301:53:301:59 | [Literal] "hello" | semmle.label | [Literal] "hello" |
-| tst.ts:303:3:305:4 | [DeclStmt] let obj = ... | semmle.label | [DeclStmt] let obj = ... |
-| tst.ts:303:7:303:9 | [VarDecl] obj | semmle.label | [VarDecl] obj |
-| tst.ts:303:7:305:3 | [VariableDeclarator] obj = { ... ng, } | semmle.label | [VariableDeclarator] obj = { ... ng, } |
-| tst.ts:303:13:305:3 | [ObjectExpr] { [ ... ng, } | semmle.label | [ObjectExpr] { [ ... ng, } |
-| tst.ts:304:5:304:25 | [Property] [key]: ... rString | semmle.label | [Property] [key]: ... rString |
-| tst.ts:304:6:304:8 | [VarRef] key | semmle.label | [VarRef] key |
-| tst.ts:304:12:304:25 | [VarRef] numberOrString | semmle.label | [VarRef] numberOrString |
-| tst.ts:307:3:310:3 | [IfStmt] if (typ ... (); } | semmle.label | [IfStmt] if (typ ... (); } |
-| tst.ts:307:7:307:21 | [UnaryExpr] typeof obj[key] | semmle.label | [UnaryExpr] typeof obj[key] |
-| tst.ts:307:7:307:34 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" |
-| tst.ts:307:14:307:16 | [VarRef] obj | semmle.label | [VarRef] obj |
-| tst.ts:307:14:307:21 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
-| tst.ts:307:18:307:20 | [VarRef] key | semmle.label | [VarRef] key |
-| tst.ts:307:27:307:34 | [Literal] "string" | semmle.label | [Literal] "string" |
-| tst.ts:307:37:310:3 | [BlockStmt] { l ... (); } | semmle.label | [BlockStmt] { l ... (); } |
-| tst.ts:308:5:308:23 | [DeclStmt] let str = ... | semmle.label | [DeclStmt] let str = ... |
-| tst.ts:308:9:308:11 | [VarDecl] str | semmle.label | [VarDecl] str |
-| tst.ts:308:9:308:22 | [VariableDeclarator] str = obj[key] | semmle.label | [VariableDeclarator] str = obj[key] |
-| tst.ts:308:15:308:17 | [VarRef] obj | semmle.label | [VarRef] obj |
-| tst.ts:308:15:308:22 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
-| tst.ts:308:19:308:21 | [VarRef] key | semmle.label | [VarRef] key |
-| tst.ts:309:5:309:7 | [VarRef] str | semmle.label | [VarRef] str |
-| tst.ts:309:5:309:19 | [DotExpr] str.toUpperCase | semmle.label | [DotExpr] str.toUpperCase |
-| tst.ts:309:5:309:21 | [MethodCallExpr] str.toUpperCase() | semmle.label | [MethodCallExpr] str.toUpperCase() |
-| tst.ts:309:5:309:22 | [ExprStmt] str.toUpperCase(); | semmle.label | [ExprStmt] str.toUpperCase(); |
-| tst.ts:309:9:309:19 | [Label] toUpperCase | semmle.label | [Label] toUpperCase |
-| tst.ts:314:3:317:12 | [FunctionDeclStmt] functio ... void {} | semmle.label | [FunctionDeclStmt] functio ... void {} |
-| tst.ts:314:12:314:12 | [VarDecl] f | semmle.label | [VarDecl] f |
-| tst.ts:314:14:314:14 | [Identifier] T | semmle.label | [Identifier] T |
-| tst.ts:314:14:314:14 | [TypeParameter] T | semmle.label | [TypeParameter] T |
-| tst.ts:314:17:314:19 | [SimpleParameter] arg | semmle.label | [SimpleParameter] arg |
-| tst.ts:314:22:316:29 | [InterfaceTypeExpr] { p ... void } | semmle.label | [InterfaceTypeExpr] { p ... void } |
-| tst.ts:315:5:315:11 | [Label] produce | semmle.label | [Label] produce |
-| tst.ts:315:5:315:30 | [FieldDeclaration] produce ... ) => T, | semmle.label | [FieldDeclaration] produce ... ) => T, |
-| tst.ts:315:14:315:29 | [FunctionExpr] (n: string) => T | semmle.label | [FunctionExpr] (n: string) => T |
-| tst.ts:315:14:315:29 | [FunctionTypeExpr] (n: string) => T | semmle.label | [FunctionTypeExpr] (n: string) => T |
-| tst.ts:315:15:315:15 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
-| tst.ts:315:18:315:23 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
-| tst.ts:315:29:315:29 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
-| tst.ts:316:5:316:11 | [Label] consume | semmle.label | [Label] consume |
-| tst.ts:316:5:316:27 | [FieldDeclaration] consume ... => void | semmle.label | [FieldDeclaration] consume ... => void |
-| tst.ts:316:14:316:27 | [FunctionExpr] (x: T) => void | semmle.label | [FunctionExpr] (x: T) => void |
-| tst.ts:316:14:316:27 | [FunctionTypeExpr] (x: T) => void | semmle.label | [FunctionTypeExpr] (x: T) => void |
-| tst.ts:316:15:316:15 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
-| tst.ts:316:18:316:18 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
-| tst.ts:316:24:316:27 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
-| tst.ts:317:6:317:9 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
-| tst.ts:317:11:317:12 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
-| tst.ts:317:13:317:13 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
-| tst.ts:319:3:319:3 | [VarRef] f | semmle.label | [VarRef] f |
-| tst.ts:319:3:322:4 | [CallExpr] f({ ... () }) | semmle.label | [CallExpr] f({ ... () }) |
-| tst.ts:319:3:322:5 | [ExprStmt] f({ ... ) }); | semmle.label | [ExprStmt] f({ ... ) }); |
-| tst.ts:319:5:322:3 | [ObjectExpr] {produce: ...} | semmle.label | [ObjectExpr] {produce: ...} |
-| tst.ts:320:5:320:11 | [Label] produce | semmle.label | [Label] produce |
-| tst.ts:320:5:320:19 | [Property] produce: n => n | semmle.label | [Property] produce: n => n |
-| tst.ts:320:14:320:14 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
-| tst.ts:320:14:320:19 | [ArrowFunctionExpr] n => n | semmle.label | [ArrowFunctionExpr] n => n |
-| tst.ts:320:19:320:19 | [VarRef] n | semmle.label | [VarRef] n |
-| tst.ts:321:5:321:11 | [Label] consume | semmle.label | [Label] consume |
-| tst.ts:321:5:321:33 | [Property] consume ... rCase() | semmle.label | [Property] consume ... rCase() |
-| tst.ts:321:14:321:14 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
-| tst.ts:321:14:321:33 | [ArrowFunctionExpr] x => x.toLowerCase() | semmle.label | [ArrowFunctionExpr] x => x.toLowerCase() |
-| tst.ts:321:19:321:19 | [VarRef] x | semmle.label | [VarRef] x |
-| tst.ts:321:19:321:31 | [DotExpr] x.toLowerCase | semmle.label | [DotExpr] x.toLowerCase |
-| tst.ts:321:19:321:33 | [MethodCallExpr] x.toLowerCase() | semmle.label | [MethodCallExpr] x.toLowerCase() |
-| tst.ts:321:21:321:31 | [Label] toLowerCase | semmle.label | [Label] toLowerCase |
-| tst.ts:326:3:326:38 | [DeclStmt] const ErrorMap = ... | semmle.label | [DeclStmt] const ErrorMap = ... |
-| tst.ts:326:9:326:16 | [VarDecl] ErrorMap | semmle.label | [VarDecl] ErrorMap |
-| tst.ts:326:9:326:37 | [VariableDeclarator] ErrorMa ... Error> | semmle.label | [VariableDeclarator] ErrorMa ... Error> |
-| tst.ts:326:20:326:22 | [VarRef] Map | semmle.label | [VarRef] Map |
-| tst.ts:326:20:326:37 | [???] Map | semmle.label | [???] Map |
-| tst.ts:326:24:326:29 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
-| tst.ts:326:32:326:36 | [LocalTypeAccess] Error | semmle.label | [LocalTypeAccess] Error |
-| tst.ts:328:3:328:34 | [DeclStmt] const errorMap = ... | semmle.label | [DeclStmt] const errorMap = ... |
-| tst.ts:328:9:328:16 | [VarDecl] errorMap | semmle.label | [VarDecl] errorMap |
-| tst.ts:328:9:328:33 | [VariableDeclarator] errorMa ... orMap() | semmle.label | [VariableDeclarator] errorMa ... orMap() |
-| tst.ts:328:20:328:33 | [NewExpr] new ErrorMap() | semmle.label | [NewExpr] new ErrorMap() |
-| tst.ts:328:24:328:31 | [VarRef] ErrorMap | semmle.label | [VarRef] ErrorMap |
-| tst.ts:332:3:335:16 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; |
-| tst.ts:332:8:332:18 | [Identifier] FirstString | semmle.label | [Identifier] FirstString |
-| tst.ts:332:20:332:20 | [Identifier] T | semmle.label | [Identifier] T |
-| tst.ts:332:20:332:20 | [TypeParameter] T | semmle.label | [TypeParameter] T |
-| tst.ts:333:5:333:5 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
-| tst.ts:333:5:335:15 | [ConditionalTypeExpr] T exten ... : never | semmle.label | [ConditionalTypeExpr] T exten ... : never |
-| tst.ts:333:15:333:52 | [TupleTypeExpr] [infer ... nown[]] | semmle.label | [TupleTypeExpr] [infer ... nown[]] |
-| tst.ts:333:16:333:37 | [InferTypeExpr] infer S ... string | semmle.label | [InferTypeExpr] infer S ... string |
-| tst.ts:333:22:333:22 | [Identifier] S | semmle.label | [Identifier] S |
-| tst.ts:333:22:333:37 | [TypeParameter] S extends string | semmle.label | [TypeParameter] S extends string |
-| tst.ts:333:32:333:37 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
-| tst.ts:333:40:333:51 | [RestTypeExpr] ...unknown[] | semmle.label | [RestTypeExpr] ...unknown[] |
-| tst.ts:333:43:333:49 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown |
-| tst.ts:333:43:333:51 | [ArrayTypeExpr] unknown[] | semmle.label | [ArrayTypeExpr] unknown[] |
-| tst.ts:334:11:334:11 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
-| tst.ts:335:11:335:15 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never |
-| tst.ts:337:3:337:53 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; |
-| tst.ts:337:8:337:8 | [Identifier] F | semmle.label | [Identifier] F |
-| tst.ts:337:12:337:22 | [LocalTypeAccess] FirstString | semmle.label | [LocalTypeAccess] FirstString |
-| tst.ts:337:12:337:52 | [GenericTypeExpr] FirstSt ... olean]> | semmle.label | [GenericTypeExpr] FirstSt ... olean]> |
-| tst.ts:337:24:337:51 | [TupleTypeExpr] ['a' \| ... oolean] | semmle.label | [TupleTypeExpr] ['a' \| ... oolean] |
-| tst.ts:337:25:337:27 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
-| tst.ts:337:25:337:33 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
-| tst.ts:337:31:337:33 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
-| tst.ts:337:36:337:41 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
-| tst.ts:337:44:337:50 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
-| tst.ts:339:3:339:19 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... |
-| tst.ts:339:9:339:9 | [VarDecl] a | semmle.label | [VarDecl] a |
-| tst.ts:339:9:339:18 | [VariableDeclarator] a: F = 'a' | semmle.label | [VariableDeclarator] a: F = 'a' |
-| tst.ts:339:12:339:12 | [LocalTypeAccess] F | semmle.label | [LocalTypeAccess] F |
-| tst.ts:339:16:339:18 | [Literal] 'a' | semmle.label | [Literal] 'a' |
-| tst.ts:343:3:346:3 | [InterfaceDeclaration,TypeDefinition] interfa ... id; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... id; } |
-| tst.ts:343:13:343:17 | [Identifier] State | semmle.label | [Identifier] State |
-| tst.ts:343:19:343:26 | [TypeParameter] in out T | semmle.label | [TypeParameter] in out T |
-| tst.ts:343:26:343:26 | [Identifier] T | semmle.label | [Identifier] T |
-| tst.ts:344:5:344:7 | [Label] get | semmle.label | [Label] get |
-| tst.ts:344:5:344:17 | [FieldDeclaration] get: () => T; | semmle.label | [FieldDeclaration] get: () => T; |
-| tst.ts:344:10:344:16 | [FunctionExpr] () => T | semmle.label | [FunctionExpr] () => T |
-| tst.ts:344:10:344:16 | [FunctionTypeExpr] () => T | semmle.label | [FunctionTypeExpr] () => T |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.label | [DeclStmt] const key = ... |
+| tst.ts:298:1:298:21 | [DeclStmt] const key = ... | semmle.order | 61 |
+| tst.ts:298:7:298:9 | [VarDecl] key | semmle.label | [VarDecl] key |
+| tst.ts:298:7:298:20 | [VariableDeclarator] key = Symbol() | semmle.label | [VariableDeclarator] key = Symbol() |
+| tst.ts:298:13:298:18 | [VarRef] Symbol | semmle.label | [VarRef] Symbol |
+| tst.ts:298:13:298:20 | [CallExpr] Symbol() | semmle.label | [CallExpr] Symbol() |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.label | [DeclStmt] const numberOrString = ... |
+| tst.ts:300:1:300:58 | [DeclStmt] const numberOrString = ... | semmle.order | 62 |
+| tst.ts:300:7:300:20 | [VarDecl] numberOrString | semmle.label | [VarDecl] numberOrString |
+| tst.ts:300:7:300:57 | [VariableDeclarator] numberO ... "hello" | semmle.label | [VariableDeclarator] numberO ... "hello" |
+| tst.ts:300:24:300:27 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tst.ts:300:24:300:34 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tst.ts:300:24:300:36 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tst.ts:300:24:300:42 | [BinaryExpr] Math.random() < 0.5 | semmle.label | [BinaryExpr] Math.random() < 0.5 |
+| tst.ts:300:24:300:57 | [ConditionalExpr] Math.ra ... "hello" | semmle.label | [ConditionalExpr] Math.ra ... "hello" |
+| tst.ts:300:29:300:34 | [Label] random | semmle.label | [Label] random |
+| tst.ts:300:40:300:42 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tst.ts:300:46:300:47 | [Literal] 42 | semmle.label | [Literal] 42 |
+| tst.ts:300:51:300:57 | [Literal] "hello" | semmle.label | [Literal] "hello" |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.label | [DeclStmt] let obj = ... |
+| tst.ts:302:1:304:2 | [DeclStmt] let obj = ... | semmle.order | 63 |
+| tst.ts:302:5:302:7 | [VarDecl] obj | semmle.label | [VarDecl] obj |
+| tst.ts:302:5:304:1 | [VariableDeclarator] obj = { ... ring, } | semmle.label | [VariableDeclarator] obj = { ... ring, } |
+| tst.ts:302:11:304:1 | [ObjectExpr] { [ke ... ring, } | semmle.label | [ObjectExpr] { [ke ... ring, } |
+| tst.ts:303:3:303:23 | [Property] [key]: ... rString | semmle.label | [Property] [key]: ... rString |
+| tst.ts:303:4:303:6 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:303:10:303:23 | [VarRef] numberOrString | semmle.label | [VarRef] numberOrString |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.label | [IfStmt] if (typ ... se(); } |
+| tst.ts:306:1:309:1 | [IfStmt] if (typ ... se(); } | semmle.order | 64 |
+| tst.ts:306:5:306:19 | [UnaryExpr] typeof obj[key] | semmle.label | [UnaryExpr] typeof obj[key] |
+| tst.ts:306:5:306:32 | [BinaryExpr] typeof ... string" | semmle.label | [BinaryExpr] typeof ... string" |
+| tst.ts:306:12:306:14 | [VarRef] obj | semmle.label | [VarRef] obj |
+| tst.ts:306:12:306:19 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
+| tst.ts:306:16:306:18 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:306:25:306:32 | [Literal] "string" | semmle.label | [Literal] "string" |
+| tst.ts:306:35:309:1 | [BlockStmt] { let ... se(); } | semmle.label | [BlockStmt] { let ... se(); } |
+| tst.ts:307:3:307:21 | [DeclStmt] let str = ... | semmle.label | [DeclStmt] let str = ... |
+| tst.ts:307:7:307:9 | [VarDecl] str | semmle.label | [VarDecl] str |
+| tst.ts:307:7:307:20 | [VariableDeclarator] str = obj[key] | semmle.label | [VariableDeclarator] str = obj[key] |
+| tst.ts:307:13:307:15 | [VarRef] obj | semmle.label | [VarRef] obj |
+| tst.ts:307:13:307:20 | [IndexExpr] obj[key] | semmle.label | [IndexExpr] obj[key] |
+| tst.ts:307:17:307:19 | [VarRef] key | semmle.label | [VarRef] key |
+| tst.ts:308:3:308:5 | [VarRef] str | semmle.label | [VarRef] str |
+| tst.ts:308:3:308:17 | [DotExpr] str.toUpperCase | semmle.label | [DotExpr] str.toUpperCase |
+| tst.ts:308:3:308:19 | [MethodCallExpr] str.toUpperCase() | semmle.label | [MethodCallExpr] str.toUpperCase() |
+| tst.ts:308:3:308:20 | [ExprStmt] str.toUpperCase(); | semmle.label | [ExprStmt] str.toUpperCase(); |
+| tst.ts:308:7:308:17 | [Label] toUpperCase | semmle.label | [Label] toUpperCase |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.label | [FunctionDeclStmt] functio ... void {} |
+| tst.ts:313:1:316:10 | [FunctionDeclStmt] functio ... void {} | semmle.order | 65 |
+| tst.ts:313:10:313:10 | [VarDecl] f | semmle.label | [VarDecl] f |
+| tst.ts:313:12:313:12 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:313:12:313:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
+| tst.ts:313:15:313:17 | [SimpleParameter] arg | semmle.label | [SimpleParameter] arg |
+| tst.ts:313:20:315:27 | [InterfaceTypeExpr] { pro ... void } | semmle.label | [InterfaceTypeExpr] { pro ... void } |
+| tst.ts:314:3:314:9 | [Label] produce | semmle.label | [Label] produce |
+| tst.ts:314:3:314:28 | [FieldDeclaration] produce ... ) => T, | semmle.label | [FieldDeclaration] produce ... ) => T, |
+| tst.ts:314:12:314:27 | [FunctionExpr] (n: string) => T | semmle.label | [FunctionExpr] (n: string) => T |
+| tst.ts:314:12:314:27 | [FunctionTypeExpr] (n: string) => T | semmle.label | [FunctionTypeExpr] (n: string) => T |
+| tst.ts:314:13:314:13 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
+| tst.ts:314:16:314:21 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:314:27:314:27 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:315:3:315:9 | [Label] consume | semmle.label | [Label] consume |
+| tst.ts:315:3:315:25 | [FieldDeclaration] consume ... => void | semmle.label | [FieldDeclaration] consume ... => void |
+| tst.ts:315:12:315:25 | [FunctionExpr] (x: T) => void | semmle.label | [FunctionExpr] (x: T) => void |
+| tst.ts:315:12:315:25 | [FunctionTypeExpr] (x: T) => void | semmle.label | [FunctionTypeExpr] (x: T) => void |
+| tst.ts:315:13:315:13 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
+| tst.ts:315:16:315:16 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:315:22:315:25 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:316:4:316:7 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:316:9:316:10 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
+| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
+| tst.ts:316:11:316:11 | [EmptyStmt] ; | semmle.order | 66 |
+| tst.ts:318:1:318:1 | [VarRef] f | semmle.label | [VarRef] f |
+| tst.ts:318:1:321:2 | [CallExpr] f({ p ... se() }) | semmle.label | [CallExpr] f({ p ... se() }) |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.label | [ExprStmt] f({ p ... e() }); |
+| tst.ts:318:1:321:3 | [ExprStmt] f({ p ... e() }); | semmle.order | 67 |
+| tst.ts:318:3:321:1 | [ObjectExpr] {produce: ...} | semmle.label | [ObjectExpr] {produce: ...} |
+| tst.ts:319:3:319:9 | [Label] produce | semmle.label | [Label] produce |
+| tst.ts:319:3:319:17 | [Property] produce: n => n | semmle.label | [Property] produce: n => n |
+| tst.ts:319:12:319:12 | [SimpleParameter] n | semmle.label | [SimpleParameter] n |
+| tst.ts:319:12:319:17 | [ArrowFunctionExpr] n => n | semmle.label | [ArrowFunctionExpr] n => n |
+| tst.ts:319:17:319:17 | [VarRef] n | semmle.label | [VarRef] n |
+| tst.ts:320:3:320:9 | [Label] consume | semmle.label | [Label] consume |
+| tst.ts:320:3:320:31 | [Property] consume ... rCase() | semmle.label | [Property] consume ... rCase() |
+| tst.ts:320:12:320:12 | [SimpleParameter] x | semmle.label | [SimpleParameter] x |
+| tst.ts:320:12:320:31 | [ArrowFunctionExpr] x => x.toLowerCase() | semmle.label | [ArrowFunctionExpr] x => x.toLowerCase() |
+| tst.ts:320:17:320:17 | [VarRef] x | semmle.label | [VarRef] x |
+| tst.ts:320:17:320:29 | [DotExpr] x.toLowerCase | semmle.label | [DotExpr] x.toLowerCase |
+| tst.ts:320:17:320:31 | [MethodCallExpr] x.toLowerCase() | semmle.label | [MethodCallExpr] x.toLowerCase() |
+| tst.ts:320:19:320:29 | [Label] toLowerCase | semmle.label | [Label] toLowerCase |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.label | [DeclStmt] const ErrorMap = ... |
+| tst.ts:325:1:325:36 | [DeclStmt] const ErrorMap = ... | semmle.order | 68 |
+| tst.ts:325:7:325:14 | [VarDecl] ErrorMap | semmle.label | [VarDecl] ErrorMap |
+| tst.ts:325:7:325:35 | [VariableDeclarator] ErrorMa ... Error> | semmle.label | [VariableDeclarator] ErrorMa ... Error> |
+| tst.ts:325:18:325:20 | [VarRef] Map | semmle.label | [VarRef] Map |
+| tst.ts:325:18:325:35 | [???] Map | semmle.label | [???] Map |
+| tst.ts:325:22:325:27 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:325:30:325:34 | [LocalTypeAccess] Error | semmle.label | [LocalTypeAccess] Error |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.label | [DeclStmt] const errorMap = ... |
+| tst.ts:327:1:327:32 | [DeclStmt] const errorMap = ... | semmle.order | 69 |
+| tst.ts:327:7:327:14 | [VarDecl] errorMap | semmle.label | [VarDecl] errorMap |
+| tst.ts:327:7:327:31 | [VariableDeclarator] errorMa ... orMap() | semmle.label | [VariableDeclarator] errorMa ... orMap() |
+| tst.ts:327:18:327:31 | [NewExpr] new ErrorMap() | semmle.label | [NewExpr] new ErrorMap() |
+| tst.ts:327:22:327:29 | [VarRef] ErrorMap | semmle.label | [VarRef] ErrorMap |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; |
+| tst.ts:331:1:334:14 | [TypeAliasDeclaration,TypeDefinition] type Fi ... never; | semmle.order | 70 |
+| tst.ts:331:6:331:16 | [Identifier] FirstString | semmle.label | [Identifier] FirstString |
+| tst.ts:331:18:331:18 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:331:18:331:18 | [TypeParameter] T | semmle.label | [TypeParameter] T |
+| tst.ts:332:3:332:3 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:332:3:334:13 | [ConditionalTypeExpr] T exten ... : never | semmle.label | [ConditionalTypeExpr] T exten ... : never |
+| tst.ts:332:13:332:50 | [TupleTypeExpr] [infer ... nown[]] | semmle.label | [TupleTypeExpr] [infer ... nown[]] |
+| tst.ts:332:14:332:35 | [InferTypeExpr] infer S ... string | semmle.label | [InferTypeExpr] infer S ... string |
+| tst.ts:332:20:332:20 | [Identifier] S | semmle.label | [Identifier] S |
+| tst.ts:332:20:332:35 | [TypeParameter] S extends string | semmle.label | [TypeParameter] S extends string |
+| tst.ts:332:30:332:35 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
+| tst.ts:332:38:332:49 | [RestTypeExpr] ...unknown[] | semmle.label | [RestTypeExpr] ...unknown[] |
+| tst.ts:332:41:332:47 | [KeywordTypeExpr] unknown | semmle.label | [KeywordTypeExpr] unknown |
+| tst.ts:332:41:332:49 | [ArrayTypeExpr] unknown[] | semmle.label | [ArrayTypeExpr] unknown[] |
+| tst.ts:333:9:333:9 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
+| tst.ts:334:9:334:13 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; |
+| tst.ts:336:1:336:51 | [TypeAliasDeclaration,TypeDefinition] type F ... lean]>; | semmle.order | 71 |
+| tst.ts:336:6:336:6 | [Identifier] F | semmle.label | [Identifier] F |
+| tst.ts:336:10:336:20 | [LocalTypeAccess] FirstString | semmle.label | [LocalTypeAccess] FirstString |
+| tst.ts:336:10:336:50 | [GenericTypeExpr] FirstSt ... olean]> | semmle.label | [GenericTypeExpr] FirstSt ... olean]> |
+| tst.ts:336:22:336:49 | [TupleTypeExpr] ['a' \| ... oolean] | semmle.label | [TupleTypeExpr] ['a' \| ... oolean] |
+| tst.ts:336:23:336:25 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tst.ts:336:23:336:31 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tst.ts:336:29:336:31 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tst.ts:336:34:336:39 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
+| tst.ts:336:42:336:48 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... |
+| tst.ts:338:1:338:17 | [DeclStmt] const a = ... | semmle.order | 72 |
+| tst.ts:338:7:338:7 | [VarDecl] a | semmle.label | [VarDecl] a |
+| tst.ts:338:7:338:16 | [VariableDeclarator] a: F = 'a' | semmle.label | [VariableDeclarator] a: F = 'a' |
+| tst.ts:338:10:338:10 | [LocalTypeAccess] F | semmle.label | [LocalTypeAccess] F |
+| tst.ts:338:14:338:16 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... void; } |
+| tst.ts:342:1:345:1 | [InterfaceDeclaration,TypeDefinition] interfa ... void; } | semmle.order | 73 |
+| tst.ts:342:11:342:15 | [Identifier] State | semmle.label | [Identifier] State |
+| tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.label | [TypeParameter] in out T |
+| tst.ts:342:24:342:24 | [Identifier] T | semmle.label | [Identifier] T |
+| tst.ts:343:3:343:5 | [Label] get | semmle.label | [Label] get |
+| tst.ts:343:3:343:15 | [FieldDeclaration] get: () => T; | semmle.label | [FieldDeclaration] get: () => T; |
+| tst.ts:343:8:343:14 | [FunctionExpr] () => T | semmle.label | [FunctionExpr] () => T |
+| tst.ts:343:8:343:14 | [FunctionTypeExpr] () => T | semmle.label | [FunctionTypeExpr] () => T |
+| tst.ts:343:14:343:14 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
+| tst.ts:344:3:344:5 | [Label] set | semmle.label | [Label] set |
+| tst.ts:344:3:344:26 | [FieldDeclaration] set: (v ... > void; | semmle.label | [FieldDeclaration] set: (v ... > void; |
+| tst.ts:344:8:344:25 | [FunctionExpr] (value: T) => void | semmle.label | [FunctionExpr] (value: T) => void |
+| tst.ts:344:8:344:25 | [FunctionTypeExpr] (value: T) => void | semmle.label | [FunctionTypeExpr] (value: T) => void |
+| tst.ts:344:9:344:13 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
| tst.ts:344:16:344:16 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
-| tst.ts:345:5:345:7 | [Label] set | semmle.label | [Label] set |
-| tst.ts:345:5:345:28 | [FieldDeclaration] set: (v ... > void; | semmle.label | [FieldDeclaration] set: (v ... > void; |
-| tst.ts:345:10:345:27 | [FunctionExpr] (value: T) => void | semmle.label | [FunctionExpr] (value: T) => void |
-| tst.ts:345:10:345:27 | [FunctionTypeExpr] (value: T) => void | semmle.label | [FunctionTypeExpr] (value: T) => void |
-| tst.ts:345:11:345:15 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
-| tst.ts:345:18:345:18 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
-| tst.ts:345:24:345:27 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
-| tst.ts:348:3:351:3 | [DeclStmt] const state = ... | semmle.label | [DeclStmt] const state = ... |
-| tst.ts:348:9:348:13 | [VarDecl] state | semmle.label | [VarDecl] state |
-| tst.ts:348:9:351:3 | [VariableDeclarator] state: ... { } } | semmle.label | [VariableDeclarator] state: ... { } } |
-| tst.ts:348:16:348:20 | [LocalTypeAccess] State | semmle.label | [LocalTypeAccess] State |
-| tst.ts:348:16:348:28 | [GenericTypeExpr] State | semmle.label | [GenericTypeExpr] State |
-| tst.ts:348:22:348:27 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
-| tst.ts:348:32:351:3 | [ObjectExpr] {get: ...} | semmle.label | [ObjectExpr] {get: ...} |
-| tst.ts:349:5:349:7 | [Label] get | semmle.label | [Label] get |
-| tst.ts:349:5:349:17 | [Property] get: () => 42 | semmle.label | [Property] get: () => 42 |
-| tst.ts:349:10:349:17 | [ArrowFunctionExpr] () => 42 | semmle.label | [ArrowFunctionExpr] () => 42 |
-| tst.ts:349:16:349:17 | [Literal] 42 | semmle.label | [Literal] 42 |
-| tst.ts:350:5:350:7 | [Label] set | semmle.label | [Label] set |
-| tst.ts:350:5:350:23 | [Property] set: (value) => { } | semmle.label | [Property] set: (value) => { } |
-| tst.ts:350:10:350:23 | [ArrowFunctionExpr] (value) => { } | semmle.label | [ArrowFunctionExpr] (value) => { } |
-| tst.ts:350:11:350:15 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
-| tst.ts:350:21:350:23 | [BlockStmt] { } | semmle.label | [BlockStmt] { } |
-| tst.ts:353:3:353:31 | [DeclStmt] const fortyTwo = ... | semmle.label | [DeclStmt] const fortyTwo = ... |
-| tst.ts:353:9:353:16 | [VarDecl] fortyTwo | semmle.label | [VarDecl] fortyTwo |
-| tst.ts:353:9:353:30 | [VariableDeclarator] fortyTw ... e.get() | semmle.label | [VariableDeclarator] fortyTw ... e.get() |
-| tst.ts:353:20:353:24 | [VarRef] state | semmle.label | [VarRef] state |
-| tst.ts:353:20:353:28 | [DotExpr] state.get | semmle.label | [DotExpr] state.get |
-| tst.ts:353:20:353:30 | [MethodCallExpr] state.get() | semmle.label | [MethodCallExpr] state.get() |
-| tst.ts:353:26:353:28 | [Label] get | semmle.label | [Label] get |
+| tst.ts:344:22:344:25 | [KeywordTypeExpr] void | semmle.label | [KeywordTypeExpr] void |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.label | [DeclStmt] const state = ... |
+| tst.ts:347:1:350:1 | [DeclStmt] const state = ... | semmle.order | 74 |
+| tst.ts:347:7:347:11 | [VarDecl] state | semmle.label | [VarDecl] state |
+| tst.ts:347:7:350:1 | [VariableDeclarator] state: ... > { } } | semmle.label | [VariableDeclarator] state: ... > { } } |
+| tst.ts:347:14:347:18 | [LocalTypeAccess] State | semmle.label | [LocalTypeAccess] State |
+| tst.ts:347:14:347:26 | [GenericTypeExpr] State | semmle.label | [GenericTypeExpr] State |
+| tst.ts:347:20:347:25 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
+| tst.ts:347:30:350:1 | [ObjectExpr] {get: ...} | semmle.label | [ObjectExpr] {get: ...} |
+| tst.ts:348:3:348:5 | [Label] get | semmle.label | [Label] get |
+| tst.ts:348:3:348:15 | [Property] get: () => 42 | semmle.label | [Property] get: () => 42 |
+| tst.ts:348:8:348:15 | [ArrowFunctionExpr] () => 42 | semmle.label | [ArrowFunctionExpr] () => 42 |
+| tst.ts:348:14:348:15 | [Literal] 42 | semmle.label | [Literal] 42 |
+| tst.ts:349:3:349:5 | [Label] set | semmle.label | [Label] set |
+| tst.ts:349:3:349:21 | [Property] set: (value) => { } | semmle.label | [Property] set: (value) => { } |
+| tst.ts:349:8:349:21 | [ArrowFunctionExpr] (value) => { } | semmle.label | [ArrowFunctionExpr] (value) => { } |
+| tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.label | [SimpleParameter] value |
+| tst.ts:349:19:349:21 | [BlockStmt] { } | semmle.label | [BlockStmt] { } |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.label | [DeclStmt] const fortyTwo = ... |
+| tst.ts:352:1:352:29 | [DeclStmt] const fortyTwo = ... | semmle.order | 75 |
+| tst.ts:352:7:352:14 | [VarDecl] fortyTwo | semmle.label | [VarDecl] fortyTwo |
+| tst.ts:352:7:352:28 | [VariableDeclarator] fortyTw ... e.get() | semmle.label | [VariableDeclarator] fortyTw ... e.get() |
+| tst.ts:352:18:352:22 | [VarRef] state | semmle.label | [VarRef] state |
+| tst.ts:352:18:352:26 | [DotExpr] state.get | semmle.label | [DotExpr] state.get |
+| tst.ts:352:18:352:28 | [MethodCallExpr] state.get() | semmle.label | [MethodCallExpr] state.get() |
+| tst.ts:352:24:352:26 | [Label] get | semmle.label | [Label] get |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.label | [ImportDeclaration] import ... S.mjs'; |
+| tst.ts:356:1:356:44 | [ImportDeclaration] import ... S.mjs'; | semmle.order | 76 |
+| tst.ts:356:8:356:18 | [ImportSpecifier] tstModuleES | semmle.label | [ImportSpecifier] tstModuleES |
+| tst.ts:356:8:356:18 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
+| tst.ts:356:25:356:43 | [Literal] './tstModuleES.mjs' | semmle.label | [Literal] './tstModuleES.mjs' |
+| tst.ts:358:1:358:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:358:1:358:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:358:1:358:26 | [MethodCallExpr] console ... leES()) | semmle.label | [MethodCallExpr] console ... leES()) |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.label | [ExprStmt] console ... eES()); |
+| tst.ts:358:1:358:27 | [ExprStmt] console ... eES()); | semmle.order | 77 |
+| tst.ts:358:9:358:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:358:13:358:23 | [VarRef] tstModuleES | semmle.label | [VarRef] tstModuleES |
+| tst.ts:358:13:358:25 | [CallExpr] tstModuleES() | semmle.label | [CallExpr] tstModuleES() |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.label | [ImportDeclaration] import ... S.cjs'; |
+| tst.ts:360:1:360:50 | [ImportDeclaration] import ... S.cjs'; | semmle.order | 78 |
+| tst.ts:360:10:360:21 | [ImportSpecifier] tstModuleCJS | semmle.label | [ImportSpecifier] tstModuleCJS |
+| tst.ts:360:10:360:21 | [Label] tstModuleCJS | semmle.label | [Label] tstModuleCJS |
+| tst.ts:360:10:360:21 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
+| tst.ts:360:30:360:49 | [Literal] './tstModuleCJS.cjs' | semmle.label | [Literal] './tstModuleCJS.cjs' |
+| tst.ts:362:1:362:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:362:1:362:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:362:1:362:27 | [MethodCallExpr] console ... eCJS()) | semmle.label | [MethodCallExpr] console ... eCJS()) |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.label | [ExprStmt] console ... CJS()); |
+| tst.ts:362:1:362:28 | [ExprStmt] console ... CJS()); | semmle.order | 79 |
+| tst.ts:362:9:362:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:362:13:362:24 | [VarRef] tstModuleCJS | semmle.label | [VarRef] tstModuleCJS |
+| tst.ts:362:13:362:26 | [CallExpr] tstModuleCJS() | semmle.label | [CallExpr] tstModuleCJS() |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.label | [ImportDeclaration] import ... ffixA'; |
+| tst.ts:368:1:368:34 | [ImportDeclaration] import ... ffixA'; | semmle.order | 80 |
+| tst.ts:368:8:368:13 | [ImportSpecifier] * as A | semmle.label | [ImportSpecifier] * as A |
+| tst.ts:368:13:368:13 | [VarDecl] A | semmle.label | [VarDecl] A |
+| tst.ts:368:20:368:33 | [Literal] './tstSuffixA' | semmle.label | [Literal] './tstSuffixA' |
+| tst.ts:370:1:370:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:370:1:370:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:370:1:370:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); |
+| tst.ts:370:1:370:30 | [ExprStmt] console ... ile()); | semmle.order | 81 |
+| tst.ts:370:9:370:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:370:13:370:13 | [VarRef] A | semmle.label | [VarRef] A |
+| tst.ts:370:13:370:26 | [DotExpr] A.resolvedFile | semmle.label | [DotExpr] A.resolvedFile |
+| tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.label | [MethodCallExpr] A.resolvedFile() |
+| tst.ts:370:15:370:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.label | [ImportDeclaration] import ... ffixB'; |
+| tst.ts:372:1:372:34 | [ImportDeclaration] import ... ffixB'; | semmle.order | 82 |
+| tst.ts:372:8:372:13 | [ImportSpecifier] * as B | semmle.label | [ImportSpecifier] * as B |
+| tst.ts:372:13:372:13 | [VarDecl] B | semmle.label | [VarDecl] B |
+| tst.ts:372:20:372:33 | [Literal] './tstSuffixB' | semmle.label | [Literal] './tstSuffixB' |
+| tst.ts:374:1:374:7 | [VarRef] console | semmle.label | [VarRef] console |
+| tst.ts:374:1:374:11 | [DotExpr] console.log | semmle.label | [DotExpr] console.log |
+| tst.ts:374:1:374:29 | [MethodCallExpr] console ... File()) | semmle.label | [MethodCallExpr] console ... File()) |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.label | [ExprStmt] console ... ile()); |
+| tst.ts:374:1:374:30 | [ExprStmt] console ... ile()); | semmle.order | 83 |
+| tst.ts:374:9:374:11 | [Label] log | semmle.label | [Label] log |
+| tst.ts:374:13:374:13 | [VarRef] B | semmle.label | [VarRef] B |
+| tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | [DotExpr] B.resolvedFile |
+| tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | [MethodCallExpr] B.resolvedFile() |
+| tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
+| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 84 |
+| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
+| tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
+| tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tstModuleCJS.cts:1:33:1:41 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tstModuleCJS.cts:1:39:1:41 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tstModuleCJS.cts:1:43:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | [BlockStmt] { r ... 'b'; } |
+| tstModuleCJS.cts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | [ReturnStmt] return ... : 'b'; |
+| tstModuleCJS.cts:2:12:2:15 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tstModuleCJS.cts:2:12:2:22 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tstModuleCJS.cts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tstModuleCJS.cts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | [BinaryExpr] Math.random() > 0.5 |
+| tstModuleCJS.cts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | [ConditionalExpr] Math.ra ... ' : 'b' |
+| tstModuleCJS.cts:2:17:2:22 | [Label] random | semmle.label | [Label] random |
+| tstModuleCJS.cts:2:28:2:30 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
+| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 85 |
+| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
+| tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
+| tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
+| tstModuleES.mts:1:40:1:48 | [UnionTypeExpr] 'a' \| 'b' | semmle.label | [UnionTypeExpr] 'a' \| 'b' |
+| tstModuleES.mts:1:46:1:48 | [LiteralTypeExpr] 'b' | semmle.label | [LiteralTypeExpr] 'b' |
+| tstModuleES.mts:1:50:3:1 | [BlockStmt] { r ... 'b'; } | semmle.label | [BlockStmt] { r ... 'b'; } |
+| tstModuleES.mts:2:5:2:43 | [ReturnStmt] return ... : 'b'; | semmle.label | [ReturnStmt] return ... : 'b'; |
+| tstModuleES.mts:2:12:2:15 | [VarRef] Math | semmle.label | [VarRef] Math |
+| tstModuleES.mts:2:12:2:22 | [DotExpr] Math.random | semmle.label | [DotExpr] Math.random |
+| tstModuleES.mts:2:12:2:24 | [MethodCallExpr] Math.random() | semmle.label | [MethodCallExpr] Math.random() |
+| tstModuleES.mts:2:12:2:30 | [BinaryExpr] Math.random() > 0.5 | semmle.label | [BinaryExpr] Math.random() > 0.5 |
+| tstModuleES.mts:2:12:2:42 | [ConditionalExpr] Math.ra ... ' : 'b' | semmle.label | [ConditionalExpr] Math.ra ... ' : 'b' |
+| tstModuleES.mts:2:17:2:22 | [Label] random | semmle.label | [Label] random |
+| tstModuleES.mts:2:28:2:30 | [Literal] 0.5 | semmle.label | [Literal] 0.5 |
+| tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
+| tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 86 |
+| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' |
+| tstSuffixA.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; |
+| tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 87 |
+| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' |
+| tstSuffixB.ios.ts:1:53:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; |
+| tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
+| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 88 |
+| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
+| tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
+| tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' |
+| tstSuffixB.ts:1:49:3:1 | [BlockStmt] { r ... .ts'; } | semmle.label | [BlockStmt] { r ... .ts'; } |
+| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; |
+| tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; |
-| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 62 |
+| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 89 |
| type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B |
| type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... |
-| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 63 |
+| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 90 |
| type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b |
| type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B |
| type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; |
-| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 64 |
+| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 91 |
| type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray |
| type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T |
| type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T |
@@ -1331,14 +1463,14 @@ nodes
| type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... |
-| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 65 |
+| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 92 |
| type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> |
| type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray |
| type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray |
| type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; |
-| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 66 |
+| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 93 |
| type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json |
| type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] |
| type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -1354,12 +1486,12 @@ nodes
| type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... |
-| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 67 |
+| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 94 |
| type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json |
| type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json |
| type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; |
-| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 68 |
+| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 95 |
| type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode |
| type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] |
| type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -1375,7 +1507,7 @@ nodes
| type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
| type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... |
-| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 69 |
+| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 96 |
| type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode |
| type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] |
| type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
@@ -1400,12 +1532,12 @@ nodes
| type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" |
| type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 70 |
+| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 97 |
| type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} |
-| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 71 |
+| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 98 |
| type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} |
| type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
@@ -1413,36 +1545,36 @@ nodes
| type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
| type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... |
-| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 72 |
+| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 99 |
| type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj |
| type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C |
| type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} |
-| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 73 |
+| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 100 |
| type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} |
| type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... |
-| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 74 |
+| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 101 |
| type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj |
| type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E |
| type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} |
-| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 75 |
+| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 102 |
| type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} |
| type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N |
| type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... |
-| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 76 |
+| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 103 |
| type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj |
| type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N |
| type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
-| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 77 |
+| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 104 |
| type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } |
-| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 78 |
+| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 105 |
| type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I |
| type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S |
| type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S |
@@ -1450,14 +1582,14 @@ nodes
| type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; |
| type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... |
-| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 79 |
+| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 106 |
| type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i |
| type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I |
| type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I |
| type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I