From 178da21fb8868280826e3d1dbec5a1e43f673717 Mon Sep 17 00:00:00 2001 From: Napalys Date: Mon, 25 Nov 2024 11:53:00 +0100 Subject: [PATCH 01/56] JS: Added test case for CWE-178 RegExp with unknown flags --- .../CWE-178/CaseSensitiveMiddlewarePath.expected | 1 + .../ql/test/query-tests/Security/CWE-178/tst.js | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected index 2195bbf0029..2be1780188a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected @@ -2,6 +2,7 @@ | tst.js:14:5:14:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:14:5:14:28 | new Reg ... (.*)?') | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | case-insensitive path | | tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | case-insensitive path | | tst.js:64:5:64:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:64:5:64:28 | new Reg ... (.*)?') | pattern | tst.js:73:1:74:2 | app.get ... ware\\n}) | case-insensitive path | +| tst.js:64:5:64:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:64:5:64:28 | new Reg ... (.*)?') | pattern | tst.js:107:1:108:2 | app.get ... ware\\n}) | case-insensitive path | | tst.js:76:9:76:20 | /\\/baz\\/bla/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ/BLA' will bypass the middleware. | tst.js:76:9:76:20 | /\\/baz\\/bla/ | pattern | tst.js:77:1:79:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ3/A' will bypass the middleware. | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | pattern | tst.js:87:1:89:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/CURRENTGAME' will bypass the middleware. | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | pattern | tst.js:93:1:95:2 | app.get ... O");\\n}) | case-insensitive path | diff --git a/javascript/ql/test/query-tests/Security/CWE-178/tst.js b/javascript/ql/test/query-tests/Security/CWE-178/tst.js index 5fcc3cc94a0..3dd24029ebe 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-178/tst.js @@ -93,3 +93,16 @@ app.use(/\/summonerByName|\/currentGame/,apiLimit1, apiLimit2); app.get('/currentGame', function (req, res) { res.send("FOO"); }); + +app.get( + new RegExp('^/bar(.*)?', unknownFlag()), // NOT OK - Currently not flagged. + unknown(), + function(req, res, next) { + if (req.params.blah) { + next(); + } + } +); + +app.get('/bar/*', (req, res) => { // OK - not a middleware +}); From e38b63ebcda88f698ab728c8d2aabd12cef06c51 Mon Sep 17 00:00:00 2001 From: Napalys Date: Mon, 25 Nov 2024 11:56:06 +0100 Subject: [PATCH 02/56] JS: previously js/case-sensitive-middleware-path was not taking into consideration unknown flags --- .../ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql | 2 +- .../Security/CWE-178/CaseSensitiveMiddlewarePath.expected | 1 + javascript/ql/test/query-tests/Security/CWE-178/tst.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql index d16f72d4172..2045d801c70 100644 --- a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql +++ b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql @@ -65,7 +65,7 @@ predicate isCaseSensitiveMiddleware( arg = call.getArgument(0) and regexp.getAReference().flowsTo(arg) and exists(string flags | - flags = regexp.getFlags() and + flags = regexp.tryGetFlags() and not RegExp::isIgnoreCase(flags) ) ) diff --git a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected index 2be1780188a..cb1720260ef 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected @@ -6,3 +6,4 @@ | tst.js:76:9:76:20 | /\\/baz\\/bla/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ/BLA' will bypass the middleware. | tst.js:76:9:76:20 | /\\/baz\\/bla/ | pattern | tst.js:77:1:79:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ3/A' will bypass the middleware. | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | pattern | tst.js:87:1:89:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/CURRENTGAME' will bypass the middleware. | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | pattern | tst.js:93:1:95:2 | app.get ... O");\\n}) | case-insensitive path | +| tst.js:98:5:98:43 | new Reg ... Flag()) | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:98:5:98:43 | new Reg ... Flag()) | pattern | tst.js:107:1:108:2 | app.get ... ware\\n}) | case-insensitive path | diff --git a/javascript/ql/test/query-tests/Security/CWE-178/tst.js b/javascript/ql/test/query-tests/Security/CWE-178/tst.js index 3dd24029ebe..69a203cb8df 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-178/tst.js @@ -95,7 +95,7 @@ app.get('/currentGame', function (req, res) { }); app.get( - new RegExp('^/bar(.*)?', unknownFlag()), // NOT OK - Currently not flagged. + new RegExp('^/bar(.*)?', unknownFlag()), // NOT OK - Might be OK if the unknown flag evaluates to case insensitive one unknown(), function(req, res, next) { if (req.params.blah) { From d6372aebc76cb196665f34e05671b0006bc6445c Mon Sep 17 00:00:00 2001 From: Napalys Klicius Date: Mon, 25 Nov 2024 12:11:07 +0100 Subject: [PATCH 03/56] Update javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql Co-authored-by: Erik Krogh Kristensen --- .../ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql | 2 +- .../Security/CWE-178/CaseSensitiveMiddlewarePath.expected | 1 - javascript/ql/test/query-tests/Security/CWE-178/tst.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql index 2045d801c70..997ee8971a5 100644 --- a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql +++ b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql @@ -66,7 +66,7 @@ predicate isCaseSensitiveMiddleware( regexp.getAReference().flowsTo(arg) and exists(string flags | flags = regexp.tryGetFlags() and - not RegExp::isIgnoreCase(flags) + not RegExp::maybeIgnoreCase(flags) ) ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected index cb1720260ef..2be1780188a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected @@ -6,4 +6,3 @@ | tst.js:76:9:76:20 | /\\/baz\\/bla/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ/BLA' will bypass the middleware. | tst.js:76:9:76:20 | /\\/baz\\/bla/ | pattern | tst.js:77:1:79:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ3/A' will bypass the middleware. | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | pattern | tst.js:87:1:89:2 | app.get ... });\\n}) | case-insensitive path | | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/CURRENTGAME' will bypass the middleware. | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | pattern | tst.js:93:1:95:2 | app.get ... O");\\n}) | case-insensitive path | -| tst.js:98:5:98:43 | new Reg ... Flag()) | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:98:5:98:43 | new Reg ... Flag()) | pattern | tst.js:107:1:108:2 | app.get ... ware\\n}) | case-insensitive path | diff --git a/javascript/ql/test/query-tests/Security/CWE-178/tst.js b/javascript/ql/test/query-tests/Security/CWE-178/tst.js index 69a203cb8df..81bbe993291 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-178/tst.js @@ -95,7 +95,7 @@ app.get('/currentGame', function (req, res) { }); app.get( - new RegExp('^/bar(.*)?', unknownFlag()), // NOT OK - Might be OK if the unknown flag evaluates to case insensitive one + new RegExp('^/bar(.*)?', unknownFlag()), // OK - Might be OK if the unknown flag evaluates to case insensitive one unknown(), function(req, res, next) { if (req.params.blah) { From 593896b40e06f09d883347c6e8c9dd4bd0000f4d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 8 Nov 2024 12:32:00 +0000 Subject: [PATCH 04/56] Add test showing promoted field bug NCField should be promoted to EmbedsNameClash. Currently it isn't because its embedded parent pkg2.NameClash is not a promoted field in EmbedsNameClash (because of a name clash with pkg1.NameClash), but this should not make a difference. --- .../semmle/go/Types/Field_getPackage.expected | 27 +++++++------ .../go/Types/Field_hasQualifiedName2.expected | 38 ++++++++++--------- .../go/Types/Field_hasQualifiedName3.expected | 38 ++++++++++--------- .../semmle/go/Types/MethodCount.expected | 4 ++ .../semmle/go/Types/MethodTypes.expected | 7 ++-- .../Types/Method_hasQualifiedName2.expected | 11 ++++-- .../Types/Method_hasQualifiedName3.expected | 11 ++++-- .../semmle/go/Types/Methods.expected | 20 ++++++---- .../semmle/go/Types/QualifiedNames.expected | 15 +++++--- .../SignatureType_getNumParameter.expected | 13 ++++--- .../Types/SignatureType_getNumResult.expected | 13 ++++--- .../semmle/go/Types/StructFields.expected | 38 ++++++++++--------- .../semmle/go/Types/Types.expected | 15 +++++--- .../library-tests/semmle/go/Types/main.go | 10 ++++- .../library-tests/semmle/go/Types/pkg1/tst.go | 6 +++ .../library-tests/semmle/go/Types/pkg2/tst.go | 6 +++ 16 files changed, 165 insertions(+), 107 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected b/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected index 485a42b185e..432eaf7997a 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected @@ -26,6 +26,7 @@ | generic.go:21:2:21:9 | mapField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | generic.go:25:2:25:12 | structField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | generic.go:29:2:29:13 | pointerField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | +| main.go:18:7:18:15 | NameClash | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | pkg1/embedding.go:19:23:19:26 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/embedding.go:22:27:22:30 | base | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/embedding.go:25:24:25:31 | embedder | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | @@ -36,20 +37,22 @@ | pkg1/promotedStructs.go:14:2:14:7 | PField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/promotedStructs.go:22:22:22:22 | S | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg1/promotedStructs.go:25:22:25:22 | P | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:4:2:4:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:5:2:5:4 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:6:2:6:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:10:2:10:4 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:11:2:11:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:15:3:15:5 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:16:3:16:5 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:20:3:20:5 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:21:2:21:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:25:2:25:4 | val | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:26:2:26:5 | flag | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | -| pkg1/tst.go:30:2:30:5 | flag | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:6:2:6:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:7:2:7:4 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:8:2:8:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:12:2:12:4 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:13:2:13:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:17:3:17:5 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:18:3:18:5 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:22:3:22:5 | Foo | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:23:2:23:4 | Bar | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:27:2:27:4 | val | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:28:2:28:5 | flag | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:32:2:32:5 | flag | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | +| pkg1/tst.go:62:7:62:15 | NameClash | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | | pkg2/tst.go:4:2:4:2 | g | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | | pkg2/tst.go:8:2:8:2 | g | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | +| pkg2/tst.go:17:2:17:8 | NCField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | | struct_tags.go:4:2:4:7 | field1 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | struct_tags.go:5:2:5:7 | field2 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | struct_tags.go:9:2:9:7 | field1 | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected index c8575332f6f..6d14516813d 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected @@ -33,6 +33,7 @@ | generic.go:21:2:21:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2 | mapField | | generic.go:25:2:25:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct2b | structField | | generic.go:29:2:29:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct2 | pointerField | +| main.go:18:7:18:15 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsNameClash | NameClash | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder2 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder3 | base | @@ -49,27 +50,30 @@ | pkg1/promotedStructs.go:14:2:14:7 | PField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedP | PField | | pkg1/promotedStructs.go:22:22:22:22 | S | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedS | S | | pkg1/promotedStructs.go:25:22:25:22 | P | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedP | P | -| pkg1/tst.go:4:2:4:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | f | -| pkg1/tst.go:5:2:5:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Foo | -| pkg1/tst.go:6:2:6:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Bar | -| pkg1/tst.go:10:2:10:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | Foo | -| pkg1/tst.go:11:2:11:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | Bar | -| pkg1/tst.go:15:3:15:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | Foo | -| pkg1/tst.go:16:3:16:5 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | Bar | -| pkg1/tst.go:20:3:20:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | Foo | -| pkg1/tst.go:21:2:21:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | Bar | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | val | -| pkg1/tst.go:26:2:26:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | flag | -| pkg1/tst.go:26:2:26:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | flag | -| pkg1/tst.go:30:2:30:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar | flag | -| pkg1/tst.go:30:2:30:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | flag | +| pkg1/tst.go:6:2:6:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | f | +| pkg1/tst.go:7:2:7:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Foo | +| pkg1/tst.go:8:2:8:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | Bar | +| pkg1/tst.go:12:2:12:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | Foo | +| pkg1/tst.go:13:2:13:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | Bar | +| pkg1/tst.go:17:3:17:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | Foo | +| pkg1/tst.go:18:3:18:5 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | Bar | +| pkg1/tst.go:22:3:22:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | Foo | +| pkg1/tst.go:23:2:23:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | Bar | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | val | +| pkg1/tst.go:28:2:28:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | flag | +| pkg1/tst.go:28:2:28:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | flag | +| pkg1/tst.go:32:2:32:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar | flag | +| pkg1/tst.go:32:2:32:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | flag | +| pkg1/tst.go:62:7:62:15 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.NameClash | NameClash | | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G | g | | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | g | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.NameClash | NCField | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.NameClash | NCField | | struct_tags.go:4:2:4:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S1 | field1 | | struct_tags.go:5:2:5:7 | field2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S1 | field2 | | struct_tags.go:9:2:9:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S2 | field1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected index 56176082d9a..7a97a6d8405 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected @@ -33,6 +33,7 @@ | generic.go:21:2:21:9 | mapField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct2 | mapField | | generic.go:25:2:25:12 | structField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct2b | structField | | generic.go:29:2:29:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | CircularGenericStruct2 | pointerField | +| main.go:18:7:18:15 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsNameClash | NameClash | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder2 | base | | pkg1/embedding.go:19:23:19:26 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | embedder3 | base | @@ -49,27 +50,30 @@ | pkg1/promotedStructs.go:14:2:14:7 | PField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | SEmbedP | PField | | pkg1/promotedStructs.go:22:22:22:22 | S | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | SEmbedS | S | | pkg1/promotedStructs.go:25:22:25:22 | P | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | SEmbedP | P | -| pkg1/tst.go:4:2:4:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | f | -| pkg1/tst.go:5:2:5:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Foo | -| pkg1/tst.go:6:2:6:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Bar | -| pkg1/tst.go:10:2:10:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | Foo | -| pkg1/tst.go:11:2:11:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | Bar | -| pkg1/tst.go:15:3:15:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | Foo | -| pkg1/tst.go:16:3:16:5 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | Bar | -| pkg1/tst.go:20:3:20:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | Foo | -| pkg1/tst.go:21:2:21:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | Bar | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | val | -| pkg1/tst.go:25:2:25:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | val | -| pkg1/tst.go:26:2:26:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | flag | -| pkg1/tst.go:26:2:26:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | flag | -| pkg1/tst.go:30:2:30:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Bar | flag | -| pkg1/tst.go:30:2:30:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | flag | +| pkg1/tst.go:6:2:6:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | f | +| pkg1/tst.go:7:2:7:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Foo | +| pkg1/tst.go:8:2:8:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | Bar | +| pkg1/tst.go:12:2:12:4 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | Foo | +| pkg1/tst.go:13:2:13:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | Bar | +| pkg1/tst.go:17:3:17:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | Foo | +| pkg1/tst.go:18:3:18:5 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | Bar | +| pkg1/tst.go:22:3:22:5 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | Foo | +| pkg1/tst.go:23:2:23:4 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | Bar | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | val | +| pkg1/tst.go:27:2:27:4 | val | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | val | +| pkg1/tst.go:28:2:28:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | flag | +| pkg1/tst.go:28:2:28:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | flag | +| pkg1/tst.go:32:2:32:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Bar | flag | +| pkg1/tst.go:32:2:32:5 | flag | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T2 | flag | +| pkg1/tst.go:62:7:62:15 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | NameClash | NameClash | | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | G | g | | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | T | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | G | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | T | g | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | NameClash | NCField | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | NameClash | NCField | | struct_tags.go:4:2:4:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S1 | field1 | | struct_tags.go:5:2:5:7 | field2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S1 | field2 | | struct_tags.go:9:2:9:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S2 | field1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/MethodCount.expected b/go/ql/test/library-tests/semmle/go/Types/MethodCount.expected index 9d576b0f4f6..351b29c6222 100644 --- a/go/ql/test/library-tests/semmle/go/Types/MethodCount.expected +++ b/go/ql/test/library-tests/semmle/go/Types/MethodCount.expected @@ -1,4 +1,6 @@ +| * EmbedsNameClash | 1 | | * Foo | 1 | +| * NameClash | 1 | | * P | 1 | | * S | 1 | | * SEmbedP | 1 | @@ -19,10 +21,12 @@ | AExtended | 2 | | B | 2 | | C | 2 | +| EmbedsNameClash | 1 | | Foo | 1 | | GenericInterface | 1 | | MixedExportedAndNot | 2 | | MyInterface | 17 | +| NameClash | 1 | | S | 1 | | SEmbedS | 1 | | T | 1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected b/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected index 326debd2f80..e02208761bf 100644 --- a/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected +++ b/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected @@ -51,8 +51,9 @@ | pkg1/interfaces.go:35:6:35:24 | MixedExportedAndNot | Exported | func() | | pkg1/interfaces.go:35:6:35:24 | MixedExportedAndNot | notExported | func() | | pkg1/promotedStructs.go:22:6:22:12 | SEmbedS | SMethod | func() interface { } | -| pkg1/tst.go:3:6:3:6 | T | half | func() Foo | -| pkg1/tst.go:14:6:14:7 | T3 | half | func() Foo | -| pkg1/tst.go:19:6:19:7 | T4 | half | func() Foo | +| pkg1/tst.go:5:6:5:6 | T | half | func() Foo | +| pkg1/tst.go:16:6:16:7 | T3 | half | func() Foo | +| pkg1/tst.go:21:6:21:7 | T4 | half | func() Foo | +| pkg1/tst.go:61:6:61:14 | NameClash | NCMethod | func() | | pkg2/tst.go:11:6:11:24 | MixedExportedAndNot | Exported | func() | | pkg2/tst.go:11:6:11:24 | MixedExportedAndNot | notExported | func() | diff --git a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected index 1f893728e30..3929e1d98d5 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName2.expected @@ -59,9 +59,12 @@ | pkg1/promotedStructs.go:8:12:8:18 | SMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedS | SMethod | | pkg1/promotedStructs.go:17:13:17:19 | PMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.P | PMethod | | pkg1/promotedStructs.go:17:13:17:19 | PMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedP | PMethod | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | half | | pkg2/tst.go:12:2:12:9 | Exported | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.MixedExportedAndNot | Exported | | pkg2/tst.go:13:2:13:12 | notExported | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.MixedExportedAndNot | notExported | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsNameClash | NCMethod | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.NameClash | NCMethod | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.NameClash | NCMethod | diff --git a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName3.expected b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName3.expected index 59a298e4b5f..9699ba3f382 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName3.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Method_hasQualifiedName3.expected @@ -59,9 +59,12 @@ | pkg1/promotedStructs.go:8:12:8:18 | SMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | SEmbedS | SMethod | | pkg1/promotedStructs.go:17:13:17:19 | PMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | P | PMethod | | pkg1/promotedStructs.go:17:13:17:19 | PMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | SEmbedP | PMethod | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | half | -| pkg1/tst.go:33:16:33:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | Foo | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T3 | half | +| pkg1/tst.go:35:16:35:19 | half | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | T4 | half | | pkg2/tst.go:12:2:12:9 | Exported | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | MixedExportedAndNot | Exported | | pkg2/tst.go:13:2:13:12 | notExported | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | MixedExportedAndNot | notExported | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsNameClash | NCMethod | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | NameClash | NCMethod | +| pkg2/tst.go:20:20:20:27 | NCMethod | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | NameClash | NCMethod | diff --git a/go/ql/test/library-tests/semmle/go/Types/Methods.expected b/go/ql/test/library-tests/semmle/go/Types/Methods.expected index 2c17013c186..c75b336543a 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Methods.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Methods.expected @@ -1,11 +1,13 @@ -| * Foo | half | pkg1/tst.go:33:16:33:19 | half | +| * EmbedsNameClash | NCMethod | pkg2/tst.go:20:20:20:27 | NCMethod | +| * Foo | half | pkg1/tst.go:35:16:35:19 | half | +| * NameClash | NCMethod | pkg2/tst.go:20:20:20:27 | NCMethod | | * P | PMethod | pkg1/promotedStructs.go:17:13:17:19 | PMethod | | * S | SMethod | pkg1/promotedStructs.go:8:12:8:18 | SMethod | | * SEmbedP | PMethod | pkg1/promotedStructs.go:17:13:17:19 | PMethod | | * SEmbedS | SMethod | pkg1/promotedStructs.go:8:12:8:18 | SMethod | -| * T | half | pkg1/tst.go:33:16:33:19 | half | -| * T3 | half | pkg1/tst.go:33:16:33:19 | half | -| * T4 | half | pkg1/tst.go:33:16:33:19 | half | +| * T | half | pkg1/tst.go:35:16:35:19 | half | +| * T3 | half | pkg1/tst.go:35:16:35:19 | half | +| * T4 | half | pkg1/tst.go:35:16:35:19 | half | | * base | f | pkg1/embedding.go:10:13:10:13 | f | | * base | g | pkg1/embedding.go:14:14:14:14 | g | | * embedder | f | pkg1/embedding.go:10:13:10:13 | f | @@ -29,7 +31,8 @@ | B | n | pkg1/interfaces.go:9:2:9:2 | n | | C | n | pkg1/interfaces.go:13:2:13:2 | n | | C | o | pkg1/interfaces.go:14:2:14:2 | o | -| Foo | half | pkg1/tst.go:33:16:33:19 | half | +| EmbedsNameClash | NCMethod | pkg2/tst.go:20:20:20:27 | NCMethod | +| Foo | half | pkg1/tst.go:35:16:35:19 | half | | GenericInterface | GetT | generic.go:33:2:33:5 | GetT | | MixedExportedAndNot | Exported | pkg1/interfaces.go:36:2:36:9 | Exported | | MixedExportedAndNot | Exported | pkg2/tst.go:12:2:12:9 | Exported | @@ -52,11 +55,12 @@ | MyInterface | dummy18 | generic.go:62:2:62:8 | dummy18 | | MyInterface | dummy19 | generic.go:63:2:63:8 | dummy19 | | MyInterface | dummy20 | generic.go:64:2:64:8 | dummy20 | +| NameClash | NCMethod | pkg2/tst.go:20:20:20:27 | NCMethod | | S | SMethod | pkg1/promotedStructs.go:8:12:8:18 | SMethod | | SEmbedS | SMethod | pkg1/promotedStructs.go:8:12:8:18 | SMethod | -| T | half | pkg1/tst.go:33:16:33:19 | half | -| T3 | half | pkg1/tst.go:33:16:33:19 | half | -| T4 | half | pkg1/tst.go:33:16:33:19 | half | +| T | half | pkg1/tst.go:35:16:35:19 | half | +| T3 | half | pkg1/tst.go:35:16:35:19 | half | +| T4 | half | pkg1/tst.go:35:16:35:19 | half | | base | f | pkg1/embedding.go:10:13:10:13 | f | | embedder | f | pkg1/embedding.go:10:13:10:13 | f | | embedder2 | f | pkg1/embedding.go:10:13:10:13 | f | diff --git a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected index 660209effbb..53e16bdef63 100644 --- a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected +++ b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected @@ -77,6 +77,7 @@ | interface.go:136:6:136:21 | testComparable21 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable21 | | interface.go:137:6:137:21 | testComparable22 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable22 | | interface.go:138:6:138:21 | testComparable23 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.testComparable23 | +| main.go:17:6:17:20 | EmbedsNameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsNameClash | | pkg1/embedding.go:8:6:8:9 | base | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.base | | pkg1/embedding.go:19:6:19:13 | embedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.embedder | | pkg1/embedding.go:22:6:22:16 | ptrembedder | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.ptrembedder | @@ -95,14 +96,16 @@ | pkg1/promotedStructs.go:13:6:13:6 | P | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.P | | pkg1/promotedStructs.go:22:6:22:12 | SEmbedS | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedS | | pkg1/promotedStructs.go:25:6:25:12 | SEmbedP | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.SEmbedP | -| pkg1/tst.go:3:6:3:6 | T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | -| pkg1/tst.go:9:6:9:7 | T2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | -| pkg1/tst.go:14:6:14:7 | T3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | -| pkg1/tst.go:19:6:19:7 | T4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | -| pkg1/tst.go:24:6:24:8 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | -| pkg1/tst.go:29:6:29:8 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar | +| pkg1/tst.go:5:6:5:6 | T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T | +| pkg1/tst.go:11:6:11:7 | T2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T2 | +| pkg1/tst.go:16:6:16:7 | T3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T3 | +| pkg1/tst.go:21:6:21:7 | T4 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.T4 | +| pkg1/tst.go:26:6:26:8 | Foo | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Foo | +| pkg1/tst.go:31:6:31:8 | Bar | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.Bar | +| pkg1/tst.go:61:6:61:14 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.NameClash | | pkg2/tst.go:3:6:3:6 | T | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | | pkg2/tst.go:7:6:7:6 | G | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G | | pkg2/tst.go:11:6:11:24 | MixedExportedAndNot | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.MixedExportedAndNot | +| pkg2/tst.go:16:6:16:14 | NameClash | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.NameClash | | struct_tags.go:3:6:3:7 | S1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S1 | | struct_tags.go:8:6:8:7 | S2 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S2 | diff --git a/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumParameter.expected b/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumParameter.expected index faedd5aa0de..5831152884b 100644 --- a/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumParameter.expected +++ b/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumParameter.expected @@ -4,18 +4,19 @@ | depth.go:22:1:25:1 | function declaration | 0 | | generic.go:70:1:72:1 | function declaration | 1 | | generic.go:74:1:80:1 | function declaration | 1 | -| main.go:5:1:5:30 | function declaration | 1 | -| main.go:7:1:9:1 | function declaration | 2 | -| main.go:11:1:11:14 | function declaration | 0 | +| main.go:9:1:9:30 | function declaration | 1 | +| main.go:11:1:13:1 | function declaration | 2 | +| main.go:15:1:15:14 | function declaration | 0 | | pkg1/embedding.go:10:1:12:1 | function declaration | 0 | | pkg1/embedding.go:14:1:16:1 | function declaration | 0 | | pkg1/embedding.go:30:1:32:1 | function declaration | 0 | | pkg1/embedding.go:40:1:61:1 | function declaration | 0 | | pkg1/promotedStructs.go:8:1:10:1 | function declaration | 0 | | pkg1/promotedStructs.go:17:1:19:1 | function declaration | 0 | -| pkg1/tst.go:33:1:35:1 | function declaration | 0 | -| pkg1/tst.go:37:1:37:26 | function declaration | 1 | -| pkg1/tst.go:39:1:57:1 | function declaration | 2 | +| pkg1/tst.go:35:1:37:1 | function declaration | 0 | +| pkg1/tst.go:39:1:39:26 | function declaration | 1 | +| pkg1/tst.go:41:1:59:1 | function declaration | 2 | +| pkg2/tst.go:20:1:20:32 | function declaration | 0 | | promoted.go:7:1:10:1 | function declaration | 1 | | promoted.go:12:1:15:1 | function declaration | 1 | | promoted.go:17:1:20:1 | function declaration | 1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumResult.expected b/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumResult.expected index 513ad56bd3c..960a272f73c 100644 --- a/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumResult.expected +++ b/go/ql/test/library-tests/semmle/go/Types/SignatureType_getNumResult.expected @@ -4,18 +4,19 @@ | depth.go:22:1:25:1 | function declaration | 0 | | generic.go:70:1:72:1 | function declaration | 1 | | generic.go:74:1:80:1 | function declaration | 0 | -| main.go:5:1:5:30 | function declaration | 0 | -| main.go:7:1:9:1 | function declaration | 2 | -| main.go:11:1:11:14 | function declaration | 0 | +| main.go:9:1:9:30 | function declaration | 0 | +| main.go:11:1:13:1 | function declaration | 2 | +| main.go:15:1:15:14 | function declaration | 0 | | pkg1/embedding.go:10:1:12:1 | function declaration | 1 | | pkg1/embedding.go:14:1:16:1 | function declaration | 1 | | pkg1/embedding.go:30:1:32:1 | function declaration | 1 | | pkg1/embedding.go:40:1:61:1 | function declaration | 0 | | pkg1/promotedStructs.go:8:1:10:1 | function declaration | 1 | | pkg1/promotedStructs.go:17:1:19:1 | function declaration | 1 | -| pkg1/tst.go:33:1:35:1 | function declaration | 1 | -| pkg1/tst.go:37:1:37:26 | function declaration | 0 | -| pkg1/tst.go:39:1:57:1 | function declaration | 0 | +| pkg1/tst.go:35:1:37:1 | function declaration | 1 | +| pkg1/tst.go:39:1:39:26 | function declaration | 0 | +| pkg1/tst.go:41:1:59:1 | function declaration | 0 | +| pkg2/tst.go:20:1:20:32 | function declaration | 0 | | promoted.go:7:1:10:1 | function declaration | 0 | | promoted.go:12:1:15:1 | function declaration | 0 | | promoted.go:17:1:20:1 | function declaration | 0 | diff --git a/go/ql/test/library-tests/semmle/go/Types/StructFields.expected b/go/ql/test/library-tests/semmle/go/Types/StructFields.expected index 502b4fa07ad..bafbc2afd09 100644 --- a/go/ql/test/library-tests/semmle/go/Types/StructFields.expected +++ b/go/ql/test/library-tests/semmle/go/Types/StructFields.expected @@ -33,6 +33,7 @@ | generic.go:19:6:19:19 | GenericStruct2 | generic.go:19:42:22:1 | struct type | structField | GenericStruct1 | | generic.go:24:6:24:20 | GenericStruct2b | generic.go:24:39:26:1 | struct type | structField | GenericStruct2 | | generic.go:28:6:28:27 | CircularGenericStruct2 | generic.go:28:39:30:1 | struct type | pointerField | * CircularGenericStruct2 | +| main.go:17:6:17:20 | EmbedsNameClash | main.go:17:22:19:1 | struct type | NameClash | NameClash | | pkg1/embedding.go:19:6:19:13 | embedder | pkg1/embedding.go:19:15:19:28 | struct type | base | base | | pkg1/embedding.go:22:6:22:16 | ptrembedder | pkg1/embedding.go:22:18:22:32 | struct type | base | * base | | pkg1/embedding.go:25:6:25:14 | embedder2 | pkg1/embedding.go:25:16:25:33 | struct type | base | base | @@ -51,27 +52,30 @@ | pkg1/promotedStructs.go:22:6:22:12 | SEmbedS | pkg1/promotedStructs.go:22:14:22:24 | struct type | SField | string | | pkg1/promotedStructs.go:25:6:25:12 | SEmbedP | pkg1/promotedStructs.go:25:14:25:24 | struct type | P | P | | pkg1/promotedStructs.go:25:6:25:12 | SEmbedP | pkg1/promotedStructs.go:25:14:25:24 | struct type | PField | string | -| pkg1/tst.go:3:6:3:6 | T | pkg1/tst.go:3:8:7:1 | struct type | Bar | Bar | -| pkg1/tst.go:3:6:3:6 | T | pkg1/tst.go:3:8:7:1 | struct type | Foo | Foo | -| pkg1/tst.go:3:6:3:6 | T | pkg1/tst.go:3:8:7:1 | struct type | f | int | -| pkg1/tst.go:3:6:3:6 | T | pkg1/tst.go:3:8:7:1 | struct type | val | int | -| pkg1/tst.go:9:6:9:7 | T2 | pkg1/tst.go:9:9:12:1 | struct type | Bar | Bar | -| pkg1/tst.go:9:6:9:7 | T2 | pkg1/tst.go:9:9:12:1 | struct type | Foo | Foo | -| pkg1/tst.go:9:6:9:7 | T2 | pkg1/tst.go:9:9:12:1 | struct type | flag | bool | -| pkg1/tst.go:14:6:14:7 | T3 | pkg1/tst.go:14:9:17:1 | struct type | Bar | * Bar | -| pkg1/tst.go:14:6:14:7 | T3 | pkg1/tst.go:14:9:17:1 | struct type | Foo | * Foo | -| pkg1/tst.go:14:6:14:7 | T3 | pkg1/tst.go:14:9:17:1 | struct type | val | int | -| pkg1/tst.go:19:6:19:7 | T4 | pkg1/tst.go:19:9:22:1 | struct type | Bar | Bar | -| pkg1/tst.go:19:6:19:7 | T4 | pkg1/tst.go:19:9:22:1 | struct type | Foo | * Foo | -| pkg1/tst.go:19:6:19:7 | T4 | pkg1/tst.go:19:9:22:1 | struct type | flag | bool | -| pkg1/tst.go:19:6:19:7 | T4 | pkg1/tst.go:19:9:22:1 | struct type | val | int | -| pkg1/tst.go:24:6:24:8 | Foo | pkg1/tst.go:24:10:27:1 | struct type | flag | bool | -| pkg1/tst.go:24:6:24:8 | Foo | pkg1/tst.go:24:10:27:1 | struct type | val | int | -| pkg1/tst.go:29:6:29:8 | Bar | pkg1/tst.go:29:10:31:1 | struct type | flag | bool | +| pkg1/tst.go:5:6:5:6 | T | pkg1/tst.go:5:8:9:1 | struct type | Bar | Bar | +| pkg1/tst.go:5:6:5:6 | T | pkg1/tst.go:5:8:9:1 | struct type | Foo | Foo | +| pkg1/tst.go:5:6:5:6 | T | pkg1/tst.go:5:8:9:1 | struct type | f | int | +| pkg1/tst.go:5:6:5:6 | T | pkg1/tst.go:5:8:9:1 | struct type | val | int | +| pkg1/tst.go:11:6:11:7 | T2 | pkg1/tst.go:11:9:14:1 | struct type | Bar | Bar | +| pkg1/tst.go:11:6:11:7 | T2 | pkg1/tst.go:11:9:14:1 | struct type | Foo | Foo | +| pkg1/tst.go:11:6:11:7 | T2 | pkg1/tst.go:11:9:14:1 | struct type | flag | bool | +| pkg1/tst.go:16:6:16:7 | T3 | pkg1/tst.go:16:9:19:1 | struct type | Bar | * Bar | +| pkg1/tst.go:16:6:16:7 | T3 | pkg1/tst.go:16:9:19:1 | struct type | Foo | * Foo | +| pkg1/tst.go:16:6:16:7 | T3 | pkg1/tst.go:16:9:19:1 | struct type | val | int | +| pkg1/tst.go:21:6:21:7 | T4 | pkg1/tst.go:21:9:24:1 | struct type | Bar | Bar | +| pkg1/tst.go:21:6:21:7 | T4 | pkg1/tst.go:21:9:24:1 | struct type | Foo | * Foo | +| pkg1/tst.go:21:6:21:7 | T4 | pkg1/tst.go:21:9:24:1 | struct type | flag | bool | +| pkg1/tst.go:21:6:21:7 | T4 | pkg1/tst.go:21:9:24:1 | struct type | val | int | +| pkg1/tst.go:26:6:26:8 | Foo | pkg1/tst.go:26:10:29:1 | struct type | flag | bool | +| pkg1/tst.go:26:6:26:8 | Foo | pkg1/tst.go:26:10:29:1 | struct type | val | int | +| pkg1/tst.go:31:6:31:8 | Bar | pkg1/tst.go:31:10:33:1 | struct type | flag | bool | +| pkg1/tst.go:61:6:61:14 | NameClash | pkg1/tst.go:61:16:63:1 | struct type | NCField | string | +| pkg1/tst.go:61:6:61:14 | NameClash | pkg1/tst.go:61:16:63:1 | struct type | NameClash | NameClash | | pkg2/tst.go:3:6:3:6 | T | pkg2/tst.go:3:8:5:1 | struct type | g | int | | pkg2/tst.go:3:6:3:6 | T | pkg2/tst.go:7:8:9:1 | struct type | g | int | | pkg2/tst.go:7:6:7:6 | G | pkg2/tst.go:3:8:5:1 | struct type | g | int | | pkg2/tst.go:7:6:7:6 | G | pkg2/tst.go:7:8:9:1 | struct type | g | int | +| pkg2/tst.go:16:6:16:14 | NameClash | pkg2/tst.go:16:16:18:1 | struct type | NCField | string | | struct_tags.go:3:6:3:7 | S1 | struct_tags.go:3:9:6:1 | struct type | field1 | int | | struct_tags.go:3:6:3:7 | S1 | struct_tags.go:3:9:6:1 | struct type | field2 | int | | struct_tags.go:8:6:8:7 | S2 | struct_tags.go:8:9:11:1 | struct type | field1 | int | diff --git a/go/ql/test/library-tests/semmle/go/Types/Types.expected b/go/ql/test/library-tests/semmle/go/Types/Types.expected index 9c04442d7aa..b18388cc31f 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Types.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Types.expected @@ -77,6 +77,7 @@ | interface.go:136:6:136:21 | testComparable21 | testComparable21 | | interface.go:137:6:137:21 | testComparable22 | testComparable22 | | interface.go:138:6:138:21 | testComparable23 | testComparable23 | +| main.go:17:6:17:20 | EmbedsNameClash | EmbedsNameClash | | pkg1/embedding.go:8:6:8:9 | base | base | | pkg1/embedding.go:19:6:19:13 | embedder | embedder | | pkg1/embedding.go:22:6:22:16 | ptrembedder | ptrembedder | @@ -95,14 +96,16 @@ | pkg1/promotedStructs.go:13:6:13:6 | P | P | | pkg1/promotedStructs.go:22:6:22:12 | SEmbedS | SEmbedS | | pkg1/promotedStructs.go:25:6:25:12 | SEmbedP | SEmbedP | -| pkg1/tst.go:3:6:3:6 | T | T | -| pkg1/tst.go:9:6:9:7 | T2 | T2 | -| pkg1/tst.go:14:6:14:7 | T3 | T3 | -| pkg1/tst.go:19:6:19:7 | T4 | T4 | -| pkg1/tst.go:24:6:24:8 | Foo | Foo | -| pkg1/tst.go:29:6:29:8 | Bar | Bar | +| pkg1/tst.go:5:6:5:6 | T | T | +| pkg1/tst.go:11:6:11:7 | T2 | T2 | +| pkg1/tst.go:16:6:16:7 | T3 | T3 | +| pkg1/tst.go:21:6:21:7 | T4 | T4 | +| pkg1/tst.go:26:6:26:8 | Foo | Foo | +| pkg1/tst.go:31:6:31:8 | Bar | Bar | +| pkg1/tst.go:61:6:61:14 | NameClash | NameClash | | pkg2/tst.go:3:6:3:6 | T | T | | pkg2/tst.go:7:6:7:6 | G | G | | pkg2/tst.go:11:6:11:24 | MixedExportedAndNot | MixedExportedAndNot | +| pkg2/tst.go:16:6:16:14 | NameClash | NameClash | | struct_tags.go:3:6:3:7 | S1 | S1 | | struct_tags.go:8:6:8:7 | S2 | S2 | diff --git a/go/ql/test/library-tests/semmle/go/Types/main.go b/go/ql/test/library-tests/semmle/go/Types/main.go index 1c7e1684725..de11cbd152f 100644 --- a/go/ql/test/library-tests/semmle/go/Types/main.go +++ b/go/ql/test/library-tests/semmle/go/Types/main.go @@ -1,6 +1,10 @@ package main -import "regexp" +import ( + "regexp" + + "github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1" +) func test(r *regexp.Regexp) {} @@ -9,3 +13,7 @@ func swap(x int, y int) (int, int) { } func main() {} + +type EmbedsNameClash struct { + pkg1.NameClash +} diff --git a/go/ql/test/library-tests/semmle/go/Types/pkg1/tst.go b/go/ql/test/library-tests/semmle/go/Types/pkg1/tst.go index 1b1920ff33a..598e711ff2c 100644 --- a/go/ql/test/library-tests/semmle/go/Types/pkg1/tst.go +++ b/go/ql/test/library-tests/semmle/go/Types/pkg1/tst.go @@ -1,5 +1,7 @@ package pkg1 +import "github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2" + type T struct { f int Foo @@ -55,3 +57,7 @@ func test(t T, t2 T2) { // methods of T2 // illegal: t2.half() } + +type NameClash struct { + pkg2.NameClash +} diff --git a/go/ql/test/library-tests/semmle/go/Types/pkg2/tst.go b/go/ql/test/library-tests/semmle/go/Types/pkg2/tst.go index af91e514b77..d1634851b6b 100644 --- a/go/ql/test/library-tests/semmle/go/Types/pkg2/tst.go +++ b/go/ql/test/library-tests/semmle/go/Types/pkg2/tst.go @@ -12,3 +12,9 @@ type MixedExportedAndNot interface { Exported() notExported() } + +type NameClash struct { + NCField string +} + +func (t NameClash) NCMethod() {} From 8dc0688b6f30961036a254a9961af072da1a3346 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Sun, 17 Nov 2024 13:26:49 +0000 Subject: [PATCH 05/56] Fix bug --- go/ql/lib/semmle/go/Types.qll | 8 ++++++-- .../semmle/go/Types/Field_getPackage.expected | 4 ++-- .../semmle/go/Types/Field_hasQualifiedName2.expected | 6 ++++-- .../semmle/go/Types/Field_hasQualifiedName3.expected | 6 ++++-- .../semmle/go/Types/ImplementsComparable.expected | 2 +- .../library-tests/semmle/go/Types/MethodTypes.expected | 1 + .../library-tests/semmle/go/Types/QualifiedNames.expected | 2 +- .../semmle/go/Types/SignatureType_isVariadic.expected | 2 +- .../library-tests/semmle/go/Types/StructFields.expected | 6 ++++-- go/ql/test/library-tests/semmle/go/Types/Types.expected | 2 +- go/ql/test/library-tests/semmle/go/Types/embedded.go | 1 - 11 files changed, 25 insertions(+), 15 deletions(-) diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index 1b09ea466cc..c05c5442061 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -523,8 +523,12 @@ class StructType extends @structtype, CompositeType { private predicate hasFieldCand(string name, Field f, int depth, boolean isEmbedded) { f = this.getOwnField(name, isEmbedded) and depth = 0 or - not this.hasOwnField(_, name, _, _) and - f = this.getFieldOfEmbedded(_, name, depth, isEmbedded) + f = this.getFieldOfEmbedded(_, name, depth, isEmbedded) and + // If this is a cyclic field and this is not the first time we see this embedded field + // then don't include it as a field candidate to avoid non-termination. + not exists(Type t | lookThroughPointerType(t) = lookThroughPointerType(f.getType()) | + this.hasOwnField(_, name, t, _) + ) } private predicate hasMethodCand(string name, Method m, int depth) { diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected b/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected index 432eaf7997a..8a527e3d4f7 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_getPackage.expected @@ -13,8 +13,8 @@ | depth.go:19:2:19:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | embedded.go:4:2:4:2 | A | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | embedded.go:8:3:8:5 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | -| embedded.go:13:2:13:4 | Qux | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | -| embedded.go:14:2:14:4 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | +| embedded.go:12:2:12:4 | Qux | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | +| embedded.go:13:2:13:4 | Baz | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | generic.go:4:2:4:11 | valueField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | generic.go:5:2:5:13 | pointerField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | | generic.go:6:2:6:11 | arrayField | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected index 6d14516813d..e7ffe6bc1ba 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName2.expected @@ -18,10 +18,11 @@ | depth.go:19:2:19:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.c | f | | depth.go:19:2:19:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.d | f | | embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Baz | A | +| embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | A | | embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | A | | embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | Baz | -| embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Qux | -| embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Baz | +| embedded.go:12:2:12:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Qux | +| embedded.go:13:2:13:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | Baz | | generic.go:4:2:4:11 | valueField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | valueField | | generic.go:5:2:5:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | pointerField | | generic.go:6:2:6:11 | arrayField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | arrayField | @@ -72,6 +73,7 @@ | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.G | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.T | g | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsNameClash | NCField | | pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1.NameClash | NCField | | pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2.NameClash | NCField | | struct_tags.go:4:2:4:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S1 | field1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected index 7a97a6d8405..03b93b37c74 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Field_hasQualifiedName3.expected @@ -18,10 +18,11 @@ | depth.go:19:2:19:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | c | f | | depth.go:19:2:19:2 | f | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | d | f | | embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | Baz | A | +| embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | A | | embedded.go:4:2:4:2 | A | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | Qux | A | | embedded.go:8:3:8:5 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | Qux | Baz | -| embedded.go:13:2:13:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Qux | -| embedded.go:14:2:14:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Baz | +| embedded.go:12:2:12:4 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Qux | +| embedded.go:13:2:13:4 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsBaz | Baz | | generic.go:4:2:4:11 | valueField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | valueField | | generic.go:5:2:5:13 | pointerField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | pointerField | | generic.go:6:2:6:11 | arrayField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | GenericStruct1 | arrayField | @@ -72,6 +73,7 @@ | pkg2/tst.go:4:2:4:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | T | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | G | g | | pkg2/tst.go:8:2:8:2 | g | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | T | g | +| pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | EmbedsNameClash | NCField | | pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg1 | NameClash | NCField | | pkg2/tst.go:17:2:17:8 | NCField | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types/pkg2 | NameClash | NCField | | struct_tags.go:4:2:4:7 | field1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S1 | field1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/ImplementsComparable.expected b/go/ql/test/library-tests/semmle/go/Types/ImplementsComparable.expected index 48de9172b36..8ec8033d086 100644 --- a/go/ql/test/library-tests/semmle/go/Types/ImplementsComparable.expected +++ b/go/ql/test/library-tests/semmle/go/Types/ImplementsComparable.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected b/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected index e02208761bf..d143fb3121e 100644 --- a/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected +++ b/go/ql/test/library-tests/semmle/go/Types/MethodTypes.expected @@ -30,6 +30,7 @@ | interface.go:95:6:95:8 | i18 | StringA | func() string | | interface.go:101:6:101:8 | i19 | StringB | func() string | | interface.go:105:6:105:8 | i20 | StringB | func() string | +| main.go:17:6:17:20 | EmbedsNameClash | NCMethod | func() | | pkg1/embedding.go:19:6:19:13 | embedder | f | func() int | | pkg1/embedding.go:22:6:22:16 | ptrembedder | f | func() int | | pkg1/embedding.go:22:6:22:16 | ptrembedder | g | func() int | diff --git a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected index 53e16bdef63..dd6e9021a4f 100644 --- a/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected +++ b/go/ql/test/library-tests/semmle/go/Types/QualifiedNames.expected @@ -9,7 +9,7 @@ | depth.go:18:6:18:6 | d | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.d | | embedded.go:3:6:3:8 | Baz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Baz | | embedded.go:7:6:7:8 | Qux | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.Qux | -| embedded.go:12:6:12:14 | EmbedsBaz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | +| embedded.go:11:6:11:14 | EmbedsBaz | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.EmbedsBaz | | generic.go:3:6:3:19 | GenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.GenericStruct1 | | generic.go:11:6:11:27 | CircularGenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.CircularGenericStruct1 | | generic.go:15:6:15:31 | UsesCircularGenericStruct1 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.UsesCircularGenericStruct1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/SignatureType_isVariadic.expected b/go/ql/test/library-tests/semmle/go/Types/SignatureType_isVariadic.expected index 48de9172b36..8ec8033d086 100644 --- a/go/ql/test/library-tests/semmle/go/Types/SignatureType_isVariadic.expected +++ b/go/ql/test/library-tests/semmle/go/Types/SignatureType_isVariadic.expected @@ -1,2 +1,2 @@ -failures testFailures +failures diff --git a/go/ql/test/library-tests/semmle/go/Types/StructFields.expected b/go/ql/test/library-tests/semmle/go/Types/StructFields.expected index bafbc2afd09..1757e0cdaf9 100644 --- a/go/ql/test/library-tests/semmle/go/Types/StructFields.expected +++ b/go/ql/test/library-tests/semmle/go/Types/StructFields.expected @@ -20,8 +20,9 @@ | embedded.go:3:6:3:8 | Baz | embedded.go:3:10:5:1 | struct type | A | string | | embedded.go:7:6:7:8 | Qux | embedded.go:7:10:9:1 | struct type | A | string | | embedded.go:7:6:7:8 | Qux | embedded.go:7:10:9:1 | struct type | Baz | * Baz | -| embedded.go:12:6:12:14 | EmbedsBaz | embedded.go:12:16:15:1 | struct type | Baz | string | -| embedded.go:12:6:12:14 | EmbedsBaz | embedded.go:12:16:15:1 | struct type | Qux | Qux | +| embedded.go:11:6:11:14 | EmbedsBaz | embedded.go:11:16:14:1 | struct type | A | string | +| embedded.go:11:6:11:14 | EmbedsBaz | embedded.go:11:16:14:1 | struct type | Baz | string | +| embedded.go:11:6:11:14 | EmbedsBaz | embedded.go:11:16:14:1 | struct type | Qux | Qux | | generic.go:3:6:3:19 | GenericStruct1 | generic.go:3:28:9:1 | struct type | arrayField | [10]T | | generic.go:3:6:3:19 | GenericStruct1 | generic.go:3:28:9:1 | struct type | mapField | [string]T | | generic.go:3:6:3:19 | GenericStruct1 | generic.go:3:28:9:1 | struct type | pointerField | * T | @@ -33,6 +34,7 @@ | generic.go:19:6:19:19 | GenericStruct2 | generic.go:19:42:22:1 | struct type | structField | GenericStruct1 | | generic.go:24:6:24:20 | GenericStruct2b | generic.go:24:39:26:1 | struct type | structField | GenericStruct2 | | generic.go:28:6:28:27 | CircularGenericStruct2 | generic.go:28:39:30:1 | struct type | pointerField | * CircularGenericStruct2 | +| main.go:17:6:17:20 | EmbedsNameClash | main.go:17:22:19:1 | struct type | NCField | string | | main.go:17:6:17:20 | EmbedsNameClash | main.go:17:22:19:1 | struct type | NameClash | NameClash | | pkg1/embedding.go:19:6:19:13 | embedder | pkg1/embedding.go:19:15:19:28 | struct type | base | base | | pkg1/embedding.go:22:6:22:16 | ptrembedder | pkg1/embedding.go:22:18:22:32 | struct type | base | * base | diff --git a/go/ql/test/library-tests/semmle/go/Types/Types.expected b/go/ql/test/library-tests/semmle/go/Types/Types.expected index b18388cc31f..ab34dd4d8ee 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Types.expected +++ b/go/ql/test/library-tests/semmle/go/Types/Types.expected @@ -9,7 +9,7 @@ | depth.go:18:6:18:6 | d | d | | embedded.go:3:6:3:8 | Baz | Baz | | embedded.go:7:6:7:8 | Qux | Qux | -| embedded.go:12:6:12:14 | EmbedsBaz | EmbedsBaz | +| embedded.go:11:6:11:14 | EmbedsBaz | EmbedsBaz | | generic.go:3:6:3:19 | GenericStruct1 | GenericStruct1 | | generic.go:11:6:11:27 | CircularGenericStruct1 | CircularGenericStruct1 | | generic.go:15:6:15:31 | UsesCircularGenericStruct1 | UsesCircularGenericStruct1 | diff --git a/go/ql/test/library-tests/semmle/go/Types/embedded.go b/go/ql/test/library-tests/semmle/go/Types/embedded.go index c9c2cf46c2b..413290dbf1a 100644 --- a/go/ql/test/library-tests/semmle/go/Types/embedded.go +++ b/go/ql/test/library-tests/semmle/go/Types/embedded.go @@ -8,7 +8,6 @@ type Qux struct { *Baz } -// EmbedsBaz should have a field A but does not type EmbedsBaz struct { Qux Baz string From 4990f16ba5e9bdfdf5518028d365e15b28f5f4cb Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 8 Nov 2024 13:36:27 +0000 Subject: [PATCH 06/56] Refactor struct field predicate to remove redundancy --- go/ql/lib/semmle/go/Types.qll | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index c05c5442061..54f5357199c 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -545,15 +545,7 @@ class StructType extends @structtype, CompositeType { predicate hasField(string name, Type tp) { exists(int mindepth | mindepth = min(int depth | this.hasFieldCand(name, _, depth, _)) and - tp = unique(Field f | f = this.getFieldCand(name, mindepth, _)).getType() - ) - } - - private Field getFieldCand(string name, int depth, boolean isEmbedded) { - result = this.getOwnField(name, isEmbedded) and depth = 0 - or - exists(Type embedded | this.hasEmbeddedField(embedded, depth - 1) | - result = embedded.getUnderlyingType().(StructType).getOwnField(name, isEmbedded) + tp = unique(Field f | this.hasFieldCand(name, f, mindepth, _)).getType() ) } @@ -568,9 +560,9 @@ class StructType extends @structtype, CompositeType { * The depth of a field `f` declared in this type is zero. */ Field getFieldAtDepth(string name, int depth) { - depth = min(int depthCand | exists(this.getFieldCand(name, depthCand, _))) and - result = this.getFieldCand(name, depth, _) and - strictcount(this.getFieldCand(name, depth, _)) = 1 + depth = min(int depthCand | exists(Field f | this.hasFieldCand(name, f, depthCand, _))) and + this.hasFieldCand(name, result, depth, _) and + strictcount(Field f | this.hasFieldCand(name, f, depth, _)) = 1 } Method getMethodAtDepth(string name, int depth) { From 1bc1472b0bf2d5a7d658faf4d27fb766ba77d7ef Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Sun, 17 Nov 2024 22:36:46 +0000 Subject: [PATCH 07/56] Add change note --- ...1-17-fix-missing-promoted-fields-and-methods-name-clash.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 go/ql/lib/change-notes/2024-11-17-fix-missing-promoted-fields-and-methods-name-clash.md diff --git a/go/ql/lib/change-notes/2024-11-17-fix-missing-promoted-fields-and-methods-name-clash.md b/go/ql/lib/change-notes/2024-11-17-fix-missing-promoted-fields-and-methods-name-clash.md new file mode 100644 index 00000000000..8b1ee9b60b2 --- /dev/null +++ b/go/ql/lib/change-notes/2024-11-17-fix-missing-promoted-fields-and-methods-name-clash.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed a bug which meant that promoted fields and methods were missing when the embedded parent was not promoted due to a name clash. From 2cba97e87d98f2a79a2205fce91428962d5c5517 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 22 Nov 2024 00:02:28 +0000 Subject: [PATCH 08/56] Small stylistic improvement --- go/ql/lib/semmle/go/Types.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index 54f5357199c..f3c07cef966 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -560,7 +560,7 @@ class StructType extends @structtype, CompositeType { * The depth of a field `f` declared in this type is zero. */ Field getFieldAtDepth(string name, int depth) { - depth = min(int depthCand | exists(Field f | this.hasFieldCand(name, f, depthCand, _))) and + depth = min(int depthCand | this.hasFieldCand(name, _, depthCand, _)) and this.hasFieldCand(name, result, depth, _) and strictcount(Field f | this.hasFieldCand(name, f, depth, _)) = 1 } From 0e94ee81aeef06a1b38651fd99bd869f7a435a1a Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 26 Nov 2024 12:27:30 +0000 Subject: [PATCH 09/56] Don't getUnderlyingType before looking through pointer type If `T` is the type of an embedded field, it is invalid for `T` to be a named type defined to be a pointer type (`type T *S`). It is also invalid for `T` to be a type parameter. So this `getUnderlyingType()` is redundant. --- go/ql/lib/semmle/go/Types.qll | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index f3c07cef966..1f1234aa1de 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -496,14 +496,15 @@ class StructType extends @structtype, CompositeType { Field getFieldOfEmbedded(Field embeddedParent, string name, int depth, boolean isEmbedded) { // embeddedParent is a field of 'this' at depth 'depth - 1' this.hasFieldCand(_, embeddedParent, depth - 1, true) and - // embeddedParent's type has the result field - exists(StructType embeddedType, Type fieldType | - fieldType = embeddedParent.getType().getUnderlyingType() and - pragma[only_bind_into](embeddedType) = - [fieldType, fieldType.(PointerType).getBaseType().getUnderlyingType()] - | - result = embeddedType.getOwnField(name, isEmbedded) - ) + // embeddedParent's type has the result field. Note that it is invalid Go + // to have an embedded field with a named type whose underlying type is a + // pointer, so we don't have to have + // `lookThroughPointerType(embeddedParent.getType().getUnderlyingType())`. + result = + lookThroughPointerType(embeddedParent.getType()) + .getUnderlyingType() + .(StructType) + .getOwnField(name, isEmbedded) } /** From 9ec9d79b4f9ae9a26628e34f7df57f35bbf821da Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 27 Nov 2024 10:02:28 +0100 Subject: [PATCH 10/56] Rust: Add additional tests for flow through structs --- .../dataflow/local/DataFlowStep.expected | 542 ++++++++++-------- .../dataflow/local/inline-flow.expected | 88 +-- .../test/library-tests/dataflow/local/main.rs | 154 +++-- 3 files changed, 455 insertions(+), 329 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index a49da751679..63666e3dec6 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -54,253 +54,301 @@ localStep | main.rs:53:5:53:5 | [SSA] i | main.rs:54:10:54:10 | i | | main.rs:53:5:53:5 | i | main.rs:53:5:53:5 | [SSA] i | | main.rs:53:9:53:17 | source(...) | main.rs:53:5:53:5 | i | -| main.rs:61:9:61:9 | [SSA] i | main.rs:62:11:62:11 | i | -| main.rs:61:9:61:9 | i | main.rs:61:9:61:9 | [SSA] i | -| main.rs:61:13:61:31 | ...::new(...) | main.rs:61:9:61:9 | i | -| main.rs:66:9:66:9 | [SSA] a | main.rs:67:10:67:10 | a | -| main.rs:66:9:66:9 | a | main.rs:66:9:66:9 | [SSA] a | -| main.rs:66:13:66:26 | TupleExpr | main.rs:66:9:66:9 | a | -| main.rs:67:10:67:10 | a | main.rs:68:10:68:10 | a | -| main.rs:78:9:78:9 | [SSA] p | main.rs:83:10:83:10 | p | -| main.rs:78:9:78:9 | p | main.rs:78:9:78:9 | [SSA] p | -| main.rs:78:13:82:5 | Point {...} | main.rs:78:9:78:9 | p | -| main.rs:83:10:83:10 | p | main.rs:84:10:84:10 | p | -| main.rs:84:10:84:10 | p | main.rs:85:10:85:10 | p | -| main.rs:92:9:92:9 | [SSA] p | main.rs:97:38:97:38 | p | -| main.rs:92:9:92:9 | p | main.rs:92:9:92:9 | [SSA] p | -| main.rs:92:13:96:5 | Point {...} | main.rs:92:9:92:9 | p | -| main.rs:97:20:97:20 | [SSA] a | main.rs:98:10:98:10 | a | -| main.rs:97:20:97:20 | a | main.rs:97:20:97:20 | [SSA] a | -| main.rs:97:26:97:26 | [SSA] b | main.rs:99:10:99:10 | b | -| main.rs:97:26:97:26 | b | main.rs:97:26:97:26 | [SSA] b | -| main.rs:97:32:97:32 | [SSA] c | main.rs:100:10:100:10 | c | -| main.rs:97:32:97:32 | c | main.rs:97:32:97:32 | [SSA] c | -| main.rs:97:38:97:38 | p | main.rs:97:9:97:34 | Point {...} | -| main.rs:104:9:104:10 | [SSA] s1 | main.rs:106:11:106:12 | s1 | -| main.rs:104:9:104:10 | s1 | main.rs:104:9:104:10 | [SSA] s1 | -| main.rs:104:14:104:37 | ...::Some(...) | main.rs:104:9:104:10 | s1 | -| main.rs:105:9:105:10 | [SSA] s2 | main.rs:110:11:110:12 | s2 | -| main.rs:105:9:105:10 | s2 | main.rs:105:9:105:10 | [SSA] s2 | -| main.rs:105:14:105:28 | ...::Some(...) | main.rs:105:9:105:10 | s2 | -| main.rs:106:11:106:12 | s1 | main.rs:107:9:107:23 | TupleStructPat | -| main.rs:106:11:106:12 | s1 | main.rs:108:9:108:20 | ...::None | -| main.rs:107:22:107:22 | [SSA] n | main.rs:107:33:107:33 | n | -| main.rs:107:22:107:22 | n | main.rs:107:22:107:22 | [SSA] n | -| main.rs:107:28:107:34 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } | -| main.rs:108:25:108:31 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } | -| main.rs:110:5:113:5 | match s2 { ... } | main.rs:103:37:114:1 | { ... } | -| main.rs:110:11:110:12 | s2 | main.rs:111:9:111:23 | TupleStructPat | -| main.rs:110:11:110:12 | s2 | main.rs:112:9:112:20 | ...::None | -| main.rs:111:22:111:22 | [SSA] n | main.rs:111:33:111:33 | n | -| main.rs:111:22:111:22 | n | main.rs:111:22:111:22 | [SSA] n | -| main.rs:111:28:111:34 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } | -| main.rs:112:25:112:31 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } | -| main.rs:117:9:117:10 | [SSA] s1 | main.rs:119:11:119:12 | s1 | -| main.rs:117:9:117:10 | s1 | main.rs:117:9:117:10 | [SSA] s1 | -| main.rs:117:14:117:29 | Some(...) | main.rs:117:9:117:10 | s1 | -| main.rs:118:9:118:10 | [SSA] s2 | main.rs:123:11:123:12 | s2 | -| main.rs:118:9:118:10 | s2 | main.rs:118:9:118:10 | [SSA] s2 | -| main.rs:118:14:118:20 | Some(...) | main.rs:118:9:118:10 | s2 | -| main.rs:119:11:119:12 | s1 | main.rs:120:9:120:15 | TupleStructPat | -| main.rs:119:11:119:12 | s1 | main.rs:121:9:121:12 | None | -| main.rs:120:14:120:14 | [SSA] n | main.rs:120:25:120:25 | n | -| main.rs:120:14:120:14 | n | main.rs:120:14:120:14 | [SSA] n | -| main.rs:120:20:120:26 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } | -| main.rs:121:17:121:23 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } | -| main.rs:123:5:126:5 | match s2 { ... } | main.rs:116:39:127:1 | { ... } | -| main.rs:123:11:123:12 | s2 | main.rs:124:9:124:15 | TupleStructPat | -| main.rs:123:11:123:12 | s2 | main.rs:125:9:125:12 | None | -| main.rs:124:14:124:14 | [SSA] n | main.rs:124:25:124:25 | n | -| main.rs:124:14:124:14 | n | main.rs:124:14:124:14 | [SSA] n | -| main.rs:124:20:124:26 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } | -| main.rs:125:17:125:23 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } | -| main.rs:135:9:135:10 | [SSA] s1 | main.rs:137:11:137:12 | s1 | -| main.rs:135:9:135:10 | s1 | main.rs:135:9:135:10 | [SSA] s1 | -| main.rs:135:14:135:39 | ...::A(...) | main.rs:135:9:135:10 | s1 | -| main.rs:136:9:136:10 | [SSA] s2 | main.rs:144:11:144:12 | s2 | -| main.rs:136:9:136:10 | s2 | main.rs:136:9:136:10 | [SSA] s2 | -| main.rs:136:14:136:30 | ...::B(...) | main.rs:136:9:136:10 | s2 | -| main.rs:137:11:137:12 | s1 | main.rs:138:9:138:25 | TupleStructPat | -| main.rs:137:11:137:12 | s1 | main.rs:139:9:139:25 | TupleStructPat | -| main.rs:137:11:137:12 | s1 | main.rs:141:11:141:12 | s1 | -| main.rs:138:24:138:24 | [SSA] n | main.rs:138:35:138:35 | n | -| main.rs:138:24:138:24 | n | main.rs:138:24:138:24 | [SSA] n | -| main.rs:138:30:138:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } | -| main.rs:139:24:139:24 | [SSA] n | main.rs:139:35:139:35 | n | -| main.rs:139:24:139:24 | n | main.rs:139:24:139:24 | [SSA] n | -| main.rs:139:30:139:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } | -| main.rs:141:11:141:12 | s1 | main.rs:142:10:142:46 | ... \| ... | -| main.rs:142:10:142:46 | ... \| ... | main.rs:142:10:142:26 | TupleStructPat | -| main.rs:142:10:142:46 | ... \| ... | main.rs:142:30:142:46 | TupleStructPat | -| main.rs:142:10:142:46 | [SSA] [match(true)] phi | main.rs:142:57:142:57 | n | -| main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi | -| main.rs:142:25:142:25 | [SSA] n | main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi | -| main.rs:142:25:142:25 | n | main.rs:142:25:142:25 | [SSA] n | -| main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi | -| main.rs:142:45:142:45 | [SSA] n | main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi | -| main.rs:142:45:142:45 | n | main.rs:142:45:142:45 | [SSA] n | -| main.rs:142:52:142:58 | sink(...) | main.rs:141:5:143:5 | match s1 { ... } | -| main.rs:144:5:147:5 | match s2 { ... } | main.rs:134:48:148:1 | { ... } | -| main.rs:144:11:144:12 | s2 | main.rs:145:9:145:25 | TupleStructPat | -| main.rs:144:11:144:12 | s2 | main.rs:146:9:146:25 | TupleStructPat | -| main.rs:145:24:145:24 | [SSA] n | main.rs:145:35:145:35 | n | -| main.rs:145:24:145:24 | n | main.rs:145:24:145:24 | [SSA] n | -| main.rs:145:30:145:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } | -| main.rs:146:24:146:24 | [SSA] n | main.rs:146:35:146:35 | n | -| main.rs:146:24:146:24 | n | main.rs:146:24:146:24 | [SSA] n | -| main.rs:146:30:146:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } | -| main.rs:153:9:153:10 | [SSA] s1 | main.rs:155:11:155:12 | s1 | -| main.rs:153:9:153:10 | s1 | main.rs:153:9:153:10 | [SSA] s1 | -| main.rs:153:14:153:26 | A(...) | main.rs:153:9:153:10 | s1 | -| main.rs:154:9:154:10 | [SSA] s2 | main.rs:162:11:162:12 | s2 | -| main.rs:154:9:154:10 | s2 | main.rs:154:9:154:10 | [SSA] s2 | -| main.rs:154:14:154:17 | B(...) | main.rs:154:9:154:10 | s2 | -| main.rs:155:11:155:12 | s1 | main.rs:156:9:156:12 | TupleStructPat | -| main.rs:155:11:155:12 | s1 | main.rs:157:9:157:12 | TupleStructPat | -| main.rs:155:11:155:12 | s1 | main.rs:159:11:159:12 | s1 | -| main.rs:156:11:156:11 | [SSA] n | main.rs:156:22:156:22 | n | -| main.rs:156:11:156:11 | n | main.rs:156:11:156:11 | [SSA] n | -| main.rs:156:17:156:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } | -| main.rs:157:11:157:11 | [SSA] n | main.rs:157:22:157:22 | n | -| main.rs:157:11:157:11 | n | main.rs:157:11:157:11 | [SSA] n | -| main.rs:157:17:157:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } | -| main.rs:159:11:159:12 | s1 | main.rs:160:10:160:20 | ... \| ... | -| main.rs:160:10:160:20 | ... \| ... | main.rs:160:10:160:13 | TupleStructPat | -| main.rs:160:10:160:20 | ... \| ... | main.rs:160:17:160:20 | TupleStructPat | -| main.rs:160:10:160:20 | [SSA] [match(true)] phi | main.rs:160:31:160:31 | n | -| main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi | -| main.rs:160:12:160:12 | [SSA] n | main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi | -| main.rs:160:12:160:12 | n | main.rs:160:12:160:12 | [SSA] n | -| main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi | -| main.rs:160:19:160:19 | [SSA] n | main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi | -| main.rs:160:19:160:19 | n | main.rs:160:19:160:19 | [SSA] n | -| main.rs:160:26:160:32 | sink(...) | main.rs:159:5:161:5 | match s1 { ... } | -| main.rs:162:5:165:5 | match s2 { ... } | main.rs:152:50:166:1 | { ... } | -| main.rs:162:11:162:12 | s2 | main.rs:163:9:163:12 | TupleStructPat | -| main.rs:162:11:162:12 | s2 | main.rs:164:9:164:12 | TupleStructPat | -| main.rs:163:11:163:11 | [SSA] n | main.rs:163:22:163:22 | n | -| main.rs:163:11:163:11 | n | main.rs:163:11:163:11 | [SSA] n | -| main.rs:163:17:163:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } | -| main.rs:164:11:164:11 | [SSA] n | main.rs:164:22:164:22 | n | -| main.rs:164:11:164:11 | n | main.rs:164:11:164:11 | [SSA] n | -| main.rs:164:17:164:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } | -| main.rs:174:9:174:10 | [SSA] s1 | main.rs:178:11:178:12 | s1 | -| main.rs:174:9:174:10 | s1 | main.rs:174:9:174:10 | [SSA] s1 | -| main.rs:174:14:176:5 | ...::C {...} | main.rs:174:9:174:10 | s1 | -| main.rs:177:9:177:10 | [SSA] s2 | main.rs:185:11:185:12 | s2 | -| main.rs:177:9:177:10 | s2 | main.rs:177:9:177:10 | [SSA] s2 | -| main.rs:177:14:177:43 | ...::D {...} | main.rs:177:9:177:10 | s2 | -| main.rs:178:11:178:12 | s1 | main.rs:179:9:179:38 | ...::C {...} | -| main.rs:178:11:178:12 | s1 | main.rs:180:9:180:38 | ...::D {...} | -| main.rs:178:11:178:12 | s1 | main.rs:182:11:182:12 | s1 | -| main.rs:179:36:179:36 | [SSA] n | main.rs:179:48:179:48 | n | -| main.rs:179:36:179:36 | n | main.rs:179:36:179:36 | [SSA] n | -| main.rs:179:43:179:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } | -| main.rs:180:36:180:36 | [SSA] n | main.rs:180:48:180:48 | n | -| main.rs:180:36:180:36 | n | main.rs:180:36:180:36 | [SSA] n | -| main.rs:180:43:180:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } | -| main.rs:182:11:182:12 | s1 | main.rs:183:10:183:72 | ... \| ... | -| main.rs:183:10:183:72 | ... \| ... | main.rs:183:10:183:39 | ...::C {...} | -| main.rs:183:10:183:72 | ... \| ... | main.rs:183:43:183:72 | ...::D {...} | -| main.rs:183:10:183:72 | [SSA] [match(true)] phi | main.rs:183:83:183:83 | n | -| main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi | -| main.rs:183:37:183:37 | [SSA] n | main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi | -| main.rs:183:37:183:37 | n | main.rs:183:37:183:37 | [SSA] n | -| main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi | -| main.rs:183:70:183:70 | [SSA] n | main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi | -| main.rs:183:70:183:70 | n | main.rs:183:70:183:70 | [SSA] n | -| main.rs:183:78:183:84 | sink(...) | main.rs:182:5:184:5 | match s1 { ... } | -| main.rs:185:5:188:5 | match s2 { ... } | main.rs:173:49:189:1 | { ... } | -| main.rs:185:11:185:12 | s2 | main.rs:186:9:186:38 | ...::C {...} | -| main.rs:185:11:185:12 | s2 | main.rs:187:9:187:38 | ...::D {...} | -| main.rs:186:36:186:36 | [SSA] n | main.rs:186:48:186:48 | n | -| main.rs:186:36:186:36 | n | main.rs:186:36:186:36 | [SSA] n | -| main.rs:186:43:186:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } | -| main.rs:187:36:187:36 | [SSA] n | main.rs:187:48:187:48 | n | -| main.rs:187:36:187:36 | n | main.rs:187:36:187:36 | [SSA] n | -| main.rs:187:43:187:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } | -| main.rs:194:9:194:10 | [SSA] s1 | main.rs:198:11:198:12 | s1 | -| main.rs:194:9:194:10 | s1 | main.rs:194:9:194:10 | [SSA] s1 | -| main.rs:194:14:196:5 | C {...} | main.rs:194:9:194:10 | s1 | -| main.rs:197:9:197:10 | [SSA] s2 | main.rs:205:11:205:12 | s2 | -| main.rs:197:9:197:10 | s2 | main.rs:197:9:197:10 | [SSA] s2 | -| main.rs:197:14:197:29 | D {...} | main.rs:197:9:197:10 | s2 | -| main.rs:198:11:198:12 | s1 | main.rs:199:9:199:24 | C {...} | -| main.rs:198:11:198:12 | s1 | main.rs:200:9:200:24 | D {...} | -| main.rs:198:11:198:12 | s1 | main.rs:202:11:202:12 | s1 | -| main.rs:199:22:199:22 | [SSA] n | main.rs:199:34:199:34 | n | -| main.rs:199:22:199:22 | n | main.rs:199:22:199:22 | [SSA] n | -| main.rs:199:29:199:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } | -| main.rs:200:22:200:22 | [SSA] n | main.rs:200:34:200:34 | n | -| main.rs:200:22:200:22 | n | main.rs:200:22:200:22 | [SSA] n | -| main.rs:200:29:200:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } | -| main.rs:202:11:202:12 | s1 | main.rs:203:10:203:44 | ... \| ... | -| main.rs:203:10:203:44 | ... \| ... | main.rs:203:10:203:25 | C {...} | -| main.rs:203:10:203:44 | ... \| ... | main.rs:203:29:203:44 | D {...} | -| main.rs:203:10:203:44 | [SSA] [match(true)] phi | main.rs:203:55:203:55 | n | -| main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi | -| main.rs:203:23:203:23 | [SSA] n | main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi | -| main.rs:203:23:203:23 | n | main.rs:203:23:203:23 | [SSA] n | -| main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi | -| main.rs:203:42:203:42 | [SSA] n | main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi | -| main.rs:203:42:203:42 | n | main.rs:203:42:203:42 | [SSA] n | -| main.rs:203:50:203:56 | sink(...) | main.rs:202:5:204:5 | match s1 { ... } | -| main.rs:205:5:208:5 | match s2 { ... } | main.rs:193:51:209:1 | { ... } | -| main.rs:205:11:205:12 | s2 | main.rs:206:9:206:24 | C {...} | -| main.rs:205:11:205:12 | s2 | main.rs:207:9:207:24 | D {...} | -| main.rs:206:22:206:22 | [SSA] n | main.rs:206:34:206:34 | n | -| main.rs:206:22:206:22 | n | main.rs:206:22:206:22 | [SSA] n | -| main.rs:206:29:206:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } | -| main.rs:207:22:207:22 | [SSA] n | main.rs:207:34:207:34 | n | -| main.rs:207:22:207:22 | n | main.rs:207:22:207:22 | [SSA] n | -| main.rs:207:29:207:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } | -| main.rs:212:9:212:9 | [SSA] a | main.rs:213:5:213:5 | a | -| main.rs:212:9:212:9 | a | main.rs:212:9:212:9 | [SSA] a | -| main.rs:212:13:212:17 | { ... } | main.rs:212:9:212:9 | a | -| main.rs:212:15:212:15 | 0 | main.rs:212:13:212:17 | { ... } | -| main.rs:213:5:213:5 | a | main.rs:211:31:214:1 | { ... } | -| main.rs:216:22:216:22 | [SSA] b | main.rs:218:12:218:12 | b | -| main.rs:216:22:216:22 | b | main.rs:216:22:216:22 | [SSA] b | -| main.rs:216:22:216:28 | ...: bool | main.rs:216:22:216:22 | b | -| main.rs:217:9:217:9 | [SSA] a | main.rs:223:5:223:5 | a | -| main.rs:217:9:217:9 | a | main.rs:217:9:217:9 | [SSA] a | -| main.rs:217:13:222:5 | 'block: { ... } | main.rs:217:9:217:9 | a | -| main.rs:219:13:219:26 | break ''block 1 | main.rs:217:13:222:5 | 'block: { ... } | -| main.rs:219:26:219:26 | 1 | main.rs:219:13:219:26 | break ''block 1 | -| main.rs:221:9:221:9 | 2 | main.rs:217:13:222:5 | 'block: { ... } | -| main.rs:223:5:223:5 | a | main.rs:216:38:224:1 | { ... } | -| main.rs:226:22:226:22 | [SSA] b | main.rs:228:12:228:12 | b | -| main.rs:226:22:226:22 | b | main.rs:226:22:226:22 | [SSA] b | -| main.rs:226:22:226:28 | ...: bool | main.rs:226:22:226:22 | b | -| main.rs:227:9:227:9 | [SSA] a | main.rs:233:5:233:5 | a | -| main.rs:227:9:227:9 | a | main.rs:227:9:227:9 | [SSA] a | -| main.rs:227:13:232:5 | 'block: { ... } | main.rs:227:9:227:9 | a | -| main.rs:229:13:229:26 | break ''block 1 | main.rs:227:13:232:5 | 'block: { ... } | -| main.rs:229:26:229:26 | 1 | main.rs:229:13:229:26 | break ''block 1 | -| main.rs:231:9:231:22 | break ''block 2 | main.rs:227:13:232:5 | 'block: { ... } | -| main.rs:231:22:231:22 | 2 | main.rs:231:9:231:22 | break ''block 2 | -| main.rs:233:5:233:5 | a | main.rs:226:38:234:1 | { ... } | +| main.rs:58:9:58:9 | [SSA] a | main.rs:59:5:59:5 | a | +| main.rs:58:9:58:9 | a | main.rs:58:9:58:9 | [SSA] a | +| main.rs:58:13:58:17 | { ... } | main.rs:58:9:58:9 | a | +| main.rs:58:15:58:15 | 0 | main.rs:58:13:58:17 | { ... } | +| main.rs:59:5:59:5 | a | main.rs:57:31:60:1 | { ... } | +| main.rs:62:22:62:22 | [SSA] b | main.rs:64:12:64:12 | b | +| main.rs:62:22:62:22 | b | main.rs:62:22:62:22 | [SSA] b | +| main.rs:62:22:62:28 | ...: bool | main.rs:62:22:62:22 | b | +| main.rs:63:9:63:9 | [SSA] a | main.rs:69:5:69:5 | a | +| main.rs:63:9:63:9 | a | main.rs:63:9:63:9 | [SSA] a | +| main.rs:63:13:68:5 | 'block: { ... } | main.rs:63:9:63:9 | a | +| main.rs:65:13:65:26 | break ''block 1 | main.rs:63:13:68:5 | 'block: { ... } | +| main.rs:65:26:65:26 | 1 | main.rs:65:13:65:26 | break ''block 1 | +| main.rs:67:9:67:9 | 2 | main.rs:63:13:68:5 | 'block: { ... } | +| main.rs:69:5:69:5 | a | main.rs:62:38:70:1 | { ... } | +| main.rs:72:22:72:22 | [SSA] b | main.rs:74:12:74:12 | b | +| main.rs:72:22:72:22 | b | main.rs:72:22:72:22 | [SSA] b | +| main.rs:72:22:72:28 | ...: bool | main.rs:72:22:72:22 | b | +| main.rs:73:9:73:9 | [SSA] a | main.rs:79:5:79:5 | a | +| main.rs:73:9:73:9 | a | main.rs:73:9:73:9 | [SSA] a | +| main.rs:73:13:78:5 | 'block: { ... } | main.rs:73:9:73:9 | a | +| main.rs:75:13:75:26 | break ''block 1 | main.rs:73:13:78:5 | 'block: { ... } | +| main.rs:75:26:75:26 | 1 | main.rs:75:13:75:26 | break ''block 1 | +| main.rs:77:9:77:22 | break ''block 2 | main.rs:73:13:78:5 | 'block: { ... } | +| main.rs:77:22:77:22 | 2 | main.rs:77:9:77:22 | break ''block 2 | +| main.rs:79:5:79:5 | a | main.rs:72:38:80:1 | { ... } | +| main.rs:86:9:86:9 | [SSA] i | main.rs:87:11:87:11 | i | +| main.rs:86:9:86:9 | i | main.rs:86:9:86:9 | [SSA] i | +| main.rs:86:13:86:31 | ...::new(...) | main.rs:86:9:86:9 | i | +| main.rs:94:9:94:9 | [SSA] a | main.rs:95:10:95:10 | a | +| main.rs:94:9:94:9 | a | main.rs:94:9:94:9 | [SSA] a | +| main.rs:94:13:94:26 | TupleExpr | main.rs:94:9:94:9 | a | +| main.rs:95:10:95:10 | a | main.rs:96:10:96:10 | a | +| main.rs:100:9:100:9 | [SSA] a | main.rs:101:24:101:24 | a | +| main.rs:100:9:100:9 | a | main.rs:100:9:100:9 | [SSA] a | +| main.rs:100:13:100:30 | TupleExpr | main.rs:100:9:100:9 | a | +| main.rs:101:10:101:11 | [SSA] a0 | main.rs:102:10:102:11 | a0 | +| main.rs:101:10:101:11 | a0 | main.rs:101:10:101:11 | [SSA] a0 | +| main.rs:101:14:101:15 | [SSA] a1 | main.rs:103:10:103:11 | a1 | +| main.rs:101:14:101:15 | a1 | main.rs:101:14:101:15 | [SSA] a1 | +| main.rs:101:18:101:19 | [SSA] a2 | main.rs:104:10:104:11 | a2 | +| main.rs:101:18:101:19 | a2 | main.rs:101:18:101:19 | [SSA] a2 | +| main.rs:101:24:101:24 | a | main.rs:101:9:101:20 | TuplePat | +| main.rs:108:9:108:13 | [SSA] a | main.rs:109:10:109:10 | a | +| main.rs:108:9:108:13 | a | main.rs:108:9:108:13 | [SSA] a | +| main.rs:108:17:108:31 | TupleExpr | main.rs:108:9:108:13 | a | +| main.rs:109:10:109:10 | a | main.rs:110:10:110:10 | a | +| main.rs:110:10:110:10 | a | main.rs:111:5:111:5 | a | +| main.rs:111:5:111:5 | a | main.rs:112:5:112:5 | a | +| main.rs:111:11:111:11 | 2 | main.rs:111:5:111:7 | a.1 | +| main.rs:112:5:112:5 | a | main.rs:113:10:113:10 | a | +| main.rs:112:11:112:20 | source(...) | main.rs:112:5:112:7 | a.0 | +| main.rs:113:10:113:10 | a | main.rs:114:10:114:10 | a | +| main.rs:118:9:118:9 | [SSA] a | main.rs:119:14:119:14 | a | +| main.rs:118:9:118:9 | a | main.rs:118:9:118:9 | [SSA] a | +| main.rs:118:13:118:27 | TupleExpr | main.rs:118:9:118:9 | a | +| main.rs:119:9:119:9 | [SSA] b | main.rs:120:10:120:10 | b | +| main.rs:119:9:119:9 | b | main.rs:119:9:119:9 | [SSA] b | +| main.rs:119:13:119:18 | TupleExpr | main.rs:119:9:119:9 | b | +| main.rs:120:10:120:10 | b | main.rs:121:10:121:10 | b | +| main.rs:121:10:121:10 | b | main.rs:122:10:122:10 | b | +| main.rs:134:9:134:9 | [SSA] p | main.rs:138:10:138:10 | p | +| main.rs:134:9:134:9 | p | main.rs:134:9:134:9 | [SSA] p | +| main.rs:134:13:137:5 | Point {...} | main.rs:134:9:134:9 | p | +| main.rs:138:10:138:10 | p | main.rs:139:10:139:10 | p | +| main.rs:143:9:143:13 | [SSA] p | main.rs:147:10:147:10 | p | +| main.rs:143:9:143:13 | p | main.rs:143:9:143:13 | [SSA] p | +| main.rs:143:17:146:5 | Point {...} | main.rs:143:9:143:13 | p | +| main.rs:147:10:147:10 | p | main.rs:148:5:148:5 | p | +| main.rs:148:5:148:5 | p | main.rs:149:10:149:10 | p | +| main.rs:148:11:148:20 | source(...) | main.rs:148:5:148:7 | p.y | +| main.rs:153:9:153:9 | [SSA] p | main.rs:157:32:157:32 | p | +| main.rs:153:9:153:9 | p | main.rs:153:9:153:9 | [SSA] p | +| main.rs:153:13:156:5 | Point {...} | main.rs:153:9:153:9 | p | +| main.rs:157:20:157:20 | [SSA] a | main.rs:158:10:158:10 | a | +| main.rs:157:20:157:20 | a | main.rs:157:20:157:20 | [SSA] a | +| main.rs:157:26:157:26 | [SSA] b | main.rs:159:10:159:10 | b | +| main.rs:157:26:157:26 | b | main.rs:157:26:157:26 | [SSA] b | +| main.rs:157:32:157:32 | p | main.rs:157:9:157:28 | Point {...} | +| main.rs:168:9:168:9 | [SSA] p | main.rs:175:10:175:10 | p | +| main.rs:168:9:168:9 | p | main.rs:168:9:168:9 | [SSA] p | +| main.rs:168:13:174:5 | Point3D {...} | main.rs:168:9:168:9 | p | +| main.rs:175:10:175:10 | p | main.rs:176:10:176:10 | p | +| main.rs:176:10:176:10 | p | main.rs:177:10:177:10 | p | +| main.rs:181:9:181:9 | [SSA] p | main.rs:188:11:188:11 | p | +| main.rs:181:9:181:9 | p | main.rs:181:9:181:9 | [SSA] p | +| main.rs:181:13:187:5 | Point3D {...} | main.rs:181:9:181:9 | p | +| main.rs:188:5:194:5 | match p { ... } | main.rs:180:26:195:1 | { ... } | +| main.rs:188:11:188:11 | p | main.rs:189:9:189:45 | Point3D {...} | +| main.rs:189:34:189:34 | [SSA] x | main.rs:190:18:190:18 | x | +| main.rs:189:34:189:34 | x | main.rs:189:34:189:34 | [SSA] x | +| main.rs:189:37:189:37 | [SSA] y | main.rs:191:18:191:18 | y | +| main.rs:189:37:189:37 | y | main.rs:189:37:189:37 | [SSA] y | +| main.rs:189:42:189:42 | [SSA] z | main.rs:192:18:192:18 | z | +| main.rs:189:42:189:42 | z | main.rs:189:42:189:42 | [SSA] z | +| main.rs:189:50:193:9 | { ... } | main.rs:188:5:194:5 | match p { ... } | +| main.rs:201:9:201:10 | [SSA] s1 | main.rs:203:11:203:12 | s1 | +| main.rs:201:9:201:10 | s1 | main.rs:201:9:201:10 | [SSA] s1 | +| main.rs:201:14:201:37 | ...::Some(...) | main.rs:201:9:201:10 | s1 | +| main.rs:202:9:202:10 | [SSA] s2 | main.rs:207:11:207:12 | s2 | +| main.rs:202:9:202:10 | s2 | main.rs:202:9:202:10 | [SSA] s2 | +| main.rs:202:14:202:28 | ...::Some(...) | main.rs:202:9:202:10 | s2 | +| main.rs:203:11:203:12 | s1 | main.rs:204:9:204:23 | TupleStructPat | +| main.rs:203:11:203:12 | s1 | main.rs:205:9:205:20 | ...::None | +| main.rs:204:22:204:22 | [SSA] n | main.rs:204:33:204:33 | n | +| main.rs:204:22:204:22 | n | main.rs:204:22:204:22 | [SSA] n | +| main.rs:204:28:204:34 | sink(...) | main.rs:203:5:206:5 | match s1 { ... } | +| main.rs:205:25:205:31 | sink(...) | main.rs:203:5:206:5 | match s1 { ... } | +| main.rs:207:5:210:5 | match s2 { ... } | main.rs:200:37:211:1 | { ... } | +| main.rs:207:11:207:12 | s2 | main.rs:208:9:208:23 | TupleStructPat | +| main.rs:207:11:207:12 | s2 | main.rs:209:9:209:20 | ...::None | +| main.rs:208:22:208:22 | [SSA] n | main.rs:208:33:208:33 | n | +| main.rs:208:22:208:22 | n | main.rs:208:22:208:22 | [SSA] n | +| main.rs:208:28:208:34 | sink(...) | main.rs:207:5:210:5 | match s2 { ... } | +| main.rs:209:25:209:31 | sink(...) | main.rs:207:5:210:5 | match s2 { ... } | +| main.rs:214:9:214:10 | [SSA] s1 | main.rs:216:11:216:12 | s1 | +| main.rs:214:9:214:10 | s1 | main.rs:214:9:214:10 | [SSA] s1 | +| main.rs:214:14:214:29 | Some(...) | main.rs:214:9:214:10 | s1 | +| main.rs:215:9:215:10 | [SSA] s2 | main.rs:220:11:220:12 | s2 | +| main.rs:215:9:215:10 | s2 | main.rs:215:9:215:10 | [SSA] s2 | +| main.rs:215:14:215:20 | Some(...) | main.rs:215:9:215:10 | s2 | +| main.rs:216:11:216:12 | s1 | main.rs:217:9:217:15 | TupleStructPat | +| main.rs:216:11:216:12 | s1 | main.rs:218:9:218:12 | None | +| main.rs:217:14:217:14 | [SSA] n | main.rs:217:25:217:25 | n | +| main.rs:217:14:217:14 | n | main.rs:217:14:217:14 | [SSA] n | +| main.rs:217:20:217:26 | sink(...) | main.rs:216:5:219:5 | match s1 { ... } | +| main.rs:218:17:218:23 | sink(...) | main.rs:216:5:219:5 | match s1 { ... } | +| main.rs:220:5:223:5 | match s2 { ... } | main.rs:213:39:224:1 | { ... } | +| main.rs:220:11:220:12 | s2 | main.rs:221:9:221:15 | TupleStructPat | +| main.rs:220:11:220:12 | s2 | main.rs:222:9:222:12 | None | +| main.rs:221:14:221:14 | [SSA] n | main.rs:221:25:221:25 | n | +| main.rs:221:14:221:14 | n | main.rs:221:14:221:14 | [SSA] n | +| main.rs:221:20:221:26 | sink(...) | main.rs:220:5:223:5 | match s2 { ... } | +| main.rs:222:17:222:23 | sink(...) | main.rs:220:5:223:5 | match s2 { ... } | +| main.rs:232:9:232:10 | [SSA] s1 | main.rs:234:11:234:12 | s1 | +| main.rs:232:9:232:10 | s1 | main.rs:232:9:232:10 | [SSA] s1 | +| main.rs:232:14:232:39 | ...::A(...) | main.rs:232:9:232:10 | s1 | +| main.rs:233:9:233:10 | [SSA] s2 | main.rs:241:11:241:12 | s2 | +| main.rs:233:9:233:10 | s2 | main.rs:233:9:233:10 | [SSA] s2 | +| main.rs:233:14:233:30 | ...::B(...) | main.rs:233:9:233:10 | s2 | +| main.rs:234:11:234:12 | s1 | main.rs:235:9:235:25 | TupleStructPat | +| main.rs:234:11:234:12 | s1 | main.rs:236:9:236:25 | TupleStructPat | +| main.rs:234:11:234:12 | s1 | main.rs:238:11:238:12 | s1 | +| main.rs:235:24:235:24 | [SSA] n | main.rs:235:35:235:35 | n | +| main.rs:235:24:235:24 | n | main.rs:235:24:235:24 | [SSA] n | +| main.rs:235:30:235:36 | sink(...) | main.rs:234:5:237:5 | match s1 { ... } | +| main.rs:236:24:236:24 | [SSA] n | main.rs:236:35:236:35 | n | +| main.rs:236:24:236:24 | n | main.rs:236:24:236:24 | [SSA] n | +| main.rs:236:30:236:36 | sink(...) | main.rs:234:5:237:5 | match s1 { ... } | +| main.rs:238:11:238:12 | s1 | main.rs:239:9:239:45 | ... \| ... | +| main.rs:239:9:239:45 | ... \| ... | main.rs:239:9:239:25 | TupleStructPat | +| main.rs:239:9:239:45 | ... \| ... | main.rs:239:29:239:45 | TupleStructPat | +| main.rs:239:9:239:45 | [SSA] [match(true)] phi | main.rs:239:55:239:55 | n | +| main.rs:239:24:239:24 | [SSA] [input] [match(true)] phi | main.rs:239:9:239:45 | [SSA] [match(true)] phi | +| main.rs:239:24:239:24 | [SSA] n | main.rs:239:24:239:24 | [SSA] [input] [match(true)] phi | +| main.rs:239:24:239:24 | n | main.rs:239:24:239:24 | [SSA] n | +| main.rs:239:44:239:44 | [SSA] [input] [match(true)] phi | main.rs:239:9:239:45 | [SSA] [match(true)] phi | +| main.rs:239:44:239:44 | [SSA] n | main.rs:239:44:239:44 | [SSA] [input] [match(true)] phi | +| main.rs:239:44:239:44 | n | main.rs:239:44:239:44 | [SSA] n | +| main.rs:239:50:239:56 | sink(...) | main.rs:238:5:240:5 | match s1 { ... } | +| main.rs:241:5:244:5 | match s2 { ... } | main.rs:231:48:245:1 | { ... } | +| main.rs:241:11:241:12 | s2 | main.rs:242:9:242:25 | TupleStructPat | +| main.rs:241:11:241:12 | s2 | main.rs:243:9:243:25 | TupleStructPat | +| main.rs:242:24:242:24 | [SSA] n | main.rs:242:35:242:35 | n | +| main.rs:242:24:242:24 | n | main.rs:242:24:242:24 | [SSA] n | +| main.rs:242:30:242:36 | sink(...) | main.rs:241:5:244:5 | match s2 { ... } | +| main.rs:243:24:243:24 | [SSA] n | main.rs:243:35:243:35 | n | +| main.rs:243:24:243:24 | n | main.rs:243:24:243:24 | [SSA] n | +| main.rs:243:30:243:36 | sink(...) | main.rs:241:5:244:5 | match s2 { ... } | +| main.rs:250:9:250:10 | [SSA] s1 | main.rs:252:11:252:12 | s1 | +| main.rs:250:9:250:10 | s1 | main.rs:250:9:250:10 | [SSA] s1 | +| main.rs:250:14:250:26 | A(...) | main.rs:250:9:250:10 | s1 | +| main.rs:251:9:251:10 | [SSA] s2 | main.rs:259:11:259:12 | s2 | +| main.rs:251:9:251:10 | s2 | main.rs:251:9:251:10 | [SSA] s2 | +| main.rs:251:14:251:17 | B(...) | main.rs:251:9:251:10 | s2 | +| main.rs:252:11:252:12 | s1 | main.rs:253:9:253:12 | TupleStructPat | +| main.rs:252:11:252:12 | s1 | main.rs:254:9:254:12 | TupleStructPat | +| main.rs:252:11:252:12 | s1 | main.rs:256:11:256:12 | s1 | +| main.rs:253:11:253:11 | [SSA] n | main.rs:253:22:253:22 | n | +| main.rs:253:11:253:11 | n | main.rs:253:11:253:11 | [SSA] n | +| main.rs:253:17:253:23 | sink(...) | main.rs:252:5:255:5 | match s1 { ... } | +| main.rs:254:11:254:11 | [SSA] n | main.rs:254:22:254:22 | n | +| main.rs:254:11:254:11 | n | main.rs:254:11:254:11 | [SSA] n | +| main.rs:254:17:254:23 | sink(...) | main.rs:252:5:255:5 | match s1 { ... } | +| main.rs:256:11:256:12 | s1 | main.rs:257:9:257:19 | ... \| ... | +| main.rs:257:9:257:19 | ... \| ... | main.rs:257:9:257:12 | TupleStructPat | +| main.rs:257:9:257:19 | ... \| ... | main.rs:257:16:257:19 | TupleStructPat | +| main.rs:257:9:257:19 | [SSA] [match(true)] phi | main.rs:257:29:257:29 | n | +| main.rs:257:11:257:11 | [SSA] [input] [match(true)] phi | main.rs:257:9:257:19 | [SSA] [match(true)] phi | +| main.rs:257:11:257:11 | [SSA] n | main.rs:257:11:257:11 | [SSA] [input] [match(true)] phi | +| main.rs:257:11:257:11 | n | main.rs:257:11:257:11 | [SSA] n | +| main.rs:257:18:257:18 | [SSA] [input] [match(true)] phi | main.rs:257:9:257:19 | [SSA] [match(true)] phi | +| main.rs:257:18:257:18 | [SSA] n | main.rs:257:18:257:18 | [SSA] [input] [match(true)] phi | +| main.rs:257:18:257:18 | n | main.rs:257:18:257:18 | [SSA] n | +| main.rs:257:24:257:30 | sink(...) | main.rs:256:5:258:5 | match s1 { ... } | +| main.rs:259:5:262:5 | match s2 { ... } | main.rs:249:50:263:1 | { ... } | +| main.rs:259:11:259:12 | s2 | main.rs:260:9:260:12 | TupleStructPat | +| main.rs:259:11:259:12 | s2 | main.rs:261:9:261:12 | TupleStructPat | +| main.rs:260:11:260:11 | [SSA] n | main.rs:260:22:260:22 | n | +| main.rs:260:11:260:11 | n | main.rs:260:11:260:11 | [SSA] n | +| main.rs:260:17:260:23 | sink(...) | main.rs:259:5:262:5 | match s2 { ... } | +| main.rs:261:11:261:11 | [SSA] n | main.rs:261:22:261:22 | n | +| main.rs:261:11:261:11 | n | main.rs:261:11:261:11 | [SSA] n | +| main.rs:261:17:261:23 | sink(...) | main.rs:259:5:262:5 | match s2 { ... } | +| main.rs:271:9:271:10 | [SSA] s1 | main.rs:275:11:275:12 | s1 | +| main.rs:271:9:271:10 | s1 | main.rs:271:9:271:10 | [SSA] s1 | +| main.rs:271:14:273:5 | ...::C {...} | main.rs:271:9:271:10 | s1 | +| main.rs:274:9:274:10 | [SSA] s2 | main.rs:282:11:282:12 | s2 | +| main.rs:274:9:274:10 | s2 | main.rs:274:9:274:10 | [SSA] s2 | +| main.rs:274:14:274:43 | ...::D {...} | main.rs:274:9:274:10 | s2 | +| main.rs:275:11:275:12 | s1 | main.rs:276:9:276:38 | ...::C {...} | +| main.rs:275:11:275:12 | s1 | main.rs:277:9:277:38 | ...::D {...} | +| main.rs:275:11:275:12 | s1 | main.rs:279:11:279:12 | s1 | +| main.rs:276:36:276:36 | [SSA] n | main.rs:276:48:276:48 | n | +| main.rs:276:36:276:36 | n | main.rs:276:36:276:36 | [SSA] n | +| main.rs:276:43:276:49 | sink(...) | main.rs:275:5:278:5 | match s1 { ... } | +| main.rs:277:36:277:36 | [SSA] n | main.rs:277:48:277:48 | n | +| main.rs:277:36:277:36 | n | main.rs:277:36:277:36 | [SSA] n | +| main.rs:277:43:277:49 | sink(...) | main.rs:275:5:278:5 | match s1 { ... } | +| main.rs:279:11:279:12 | s1 | main.rs:280:9:280:71 | ... \| ... | +| main.rs:280:9:280:71 | ... \| ... | main.rs:280:9:280:38 | ...::C {...} | +| main.rs:280:9:280:71 | ... \| ... | main.rs:280:42:280:71 | ...::D {...} | +| main.rs:280:9:280:71 | [SSA] [match(true)] phi | main.rs:280:81:280:81 | n | +| main.rs:280:36:280:36 | [SSA] [input] [match(true)] phi | main.rs:280:9:280:71 | [SSA] [match(true)] phi | +| main.rs:280:36:280:36 | [SSA] n | main.rs:280:36:280:36 | [SSA] [input] [match(true)] phi | +| main.rs:280:36:280:36 | n | main.rs:280:36:280:36 | [SSA] n | +| main.rs:280:69:280:69 | [SSA] [input] [match(true)] phi | main.rs:280:9:280:71 | [SSA] [match(true)] phi | +| main.rs:280:69:280:69 | [SSA] n | main.rs:280:69:280:69 | [SSA] [input] [match(true)] phi | +| main.rs:280:69:280:69 | n | main.rs:280:69:280:69 | [SSA] n | +| main.rs:280:76:280:82 | sink(...) | main.rs:279:5:281:5 | match s1 { ... } | +| main.rs:282:5:285:5 | match s2 { ... } | main.rs:270:49:286:1 | { ... } | +| main.rs:282:11:282:12 | s2 | main.rs:283:9:283:38 | ...::C {...} | +| main.rs:282:11:282:12 | s2 | main.rs:284:9:284:38 | ...::D {...} | +| main.rs:283:36:283:36 | [SSA] n | main.rs:283:48:283:48 | n | +| main.rs:283:36:283:36 | n | main.rs:283:36:283:36 | [SSA] n | +| main.rs:283:43:283:49 | sink(...) | main.rs:282:5:285:5 | match s2 { ... } | +| main.rs:284:36:284:36 | [SSA] n | main.rs:284:48:284:48 | n | +| main.rs:284:36:284:36 | n | main.rs:284:36:284:36 | [SSA] n | +| main.rs:284:43:284:49 | sink(...) | main.rs:282:5:285:5 | match s2 { ... } | +| main.rs:291:9:291:10 | [SSA] s1 | main.rs:295:11:295:12 | s1 | +| main.rs:291:9:291:10 | s1 | main.rs:291:9:291:10 | [SSA] s1 | +| main.rs:291:14:293:5 | C {...} | main.rs:291:9:291:10 | s1 | +| main.rs:294:9:294:10 | [SSA] s2 | main.rs:302:11:302:12 | s2 | +| main.rs:294:9:294:10 | s2 | main.rs:294:9:294:10 | [SSA] s2 | +| main.rs:294:14:294:29 | D {...} | main.rs:294:9:294:10 | s2 | +| main.rs:295:11:295:12 | s1 | main.rs:296:9:296:24 | C {...} | +| main.rs:295:11:295:12 | s1 | main.rs:297:9:297:24 | D {...} | +| main.rs:295:11:295:12 | s1 | main.rs:299:11:299:12 | s1 | +| main.rs:296:22:296:22 | [SSA] n | main.rs:296:34:296:34 | n | +| main.rs:296:22:296:22 | n | main.rs:296:22:296:22 | [SSA] n | +| main.rs:296:29:296:35 | sink(...) | main.rs:295:5:298:5 | match s1 { ... } | +| main.rs:297:22:297:22 | [SSA] n | main.rs:297:34:297:34 | n | +| main.rs:297:22:297:22 | n | main.rs:297:22:297:22 | [SSA] n | +| main.rs:297:29:297:35 | sink(...) | main.rs:295:5:298:5 | match s1 { ... } | +| main.rs:299:11:299:12 | s1 | main.rs:300:9:300:43 | ... \| ... | +| main.rs:300:9:300:43 | ... \| ... | main.rs:300:9:300:24 | C {...} | +| main.rs:300:9:300:43 | ... \| ... | main.rs:300:28:300:43 | D {...} | +| main.rs:300:9:300:43 | [SSA] [match(true)] phi | main.rs:300:53:300:53 | n | +| main.rs:300:22:300:22 | [SSA] [input] [match(true)] phi | main.rs:300:9:300:43 | [SSA] [match(true)] phi | +| main.rs:300:22:300:22 | [SSA] n | main.rs:300:22:300:22 | [SSA] [input] [match(true)] phi | +| main.rs:300:22:300:22 | n | main.rs:300:22:300:22 | [SSA] n | +| main.rs:300:41:300:41 | [SSA] [input] [match(true)] phi | main.rs:300:9:300:43 | [SSA] [match(true)] phi | +| main.rs:300:41:300:41 | [SSA] n | main.rs:300:41:300:41 | [SSA] [input] [match(true)] phi | +| main.rs:300:41:300:41 | n | main.rs:300:41:300:41 | [SSA] n | +| main.rs:300:48:300:54 | sink(...) | main.rs:299:5:301:5 | match s1 { ... } | +| main.rs:302:5:305:5 | match s2 { ... } | main.rs:290:51:306:1 | { ... } | +| main.rs:302:11:302:12 | s2 | main.rs:303:9:303:24 | C {...} | +| main.rs:302:11:302:12 | s2 | main.rs:304:9:304:24 | D {...} | +| main.rs:303:22:303:22 | [SSA] n | main.rs:303:34:303:34 | n | +| main.rs:303:22:303:22 | n | main.rs:303:22:303:22 | [SSA] n | +| main.rs:303:29:303:35 | sink(...) | main.rs:302:5:305:5 | match s2 { ... } | +| main.rs:304:22:304:22 | [SSA] n | main.rs:304:34:304:34 | n | +| main.rs:304:22:304:22 | n | main.rs:304:22:304:22 | [SSA] n | +| main.rs:304:29:304:35 | sink(...) | main.rs:302:5:305:5 | match s2 { ... } | storeStep -| main.rs:117:19:117:28 | source(...) | Some | main.rs:117:14:117:29 | Some(...) | -| main.rs:118:19:118:19 | 2 | Some | main.rs:118:14:118:20 | Some(...) | -| main.rs:135:29:135:38 | source(...) | A | main.rs:135:14:135:39 | ...::A(...) | -| main.rs:136:29:136:29 | 2 | B | main.rs:136:14:136:30 | ...::B(...) | -| main.rs:175:18:175:27 | source(...) | C | main.rs:174:14:176:5 | ...::C {...} | -| main.rs:177:41:177:41 | 2 | D | main.rs:177:14:177:43 | ...::D {...} | -| main.rs:240:27:240:27 | 0 | Some | main.rs:240:22:240:28 | Some(...) | +| main.rs:214:19:214:28 | source(...) | Some | main.rs:214:14:214:29 | Some(...) | +| main.rs:215:19:215:19 | 2 | Some | main.rs:215:14:215:20 | Some(...) | +| main.rs:232:29:232:38 | source(...) | A | main.rs:232:14:232:39 | ...::A(...) | +| main.rs:233:29:233:29 | 2 | B | main.rs:233:14:233:30 | ...::B(...) | +| main.rs:272:18:272:27 | source(...) | C | main.rs:271:14:273:5 | ...::C {...} | +| main.rs:274:41:274:41 | 2 | D | main.rs:274:14:274:43 | ...::D {...} | +| main.rs:312:27:312:27 | 0 | Some | main.rs:312:22:312:28 | Some(...) | readStep | main.rs:33:9:33:15 | TupleStructPat | Some | main.rs:33:14:33:14 | _ | -| main.rs:120:9:120:15 | TupleStructPat | Some | main.rs:120:14:120:14 | n | -| main.rs:124:9:124:15 | TupleStructPat | Some | main.rs:124:14:124:14 | n | -| main.rs:138:9:138:25 | TupleStructPat | A | main.rs:138:24:138:24 | n | -| main.rs:139:9:139:25 | TupleStructPat | B | main.rs:139:24:139:24 | n | -| main.rs:142:10:142:26 | TupleStructPat | A | main.rs:142:25:142:25 | n | -| main.rs:142:30:142:46 | TupleStructPat | B | main.rs:142:45:142:45 | n | -| main.rs:145:9:145:25 | TupleStructPat | A | main.rs:145:24:145:24 | n | -| main.rs:146:9:146:25 | TupleStructPat | B | main.rs:146:24:146:24 | n | -| main.rs:179:9:179:38 | ...::C {...} | C | main.rs:179:36:179:36 | n | -| main.rs:180:9:180:38 | ...::D {...} | D | main.rs:180:36:180:36 | n | -| main.rs:183:10:183:39 | ...::C {...} | C | main.rs:183:37:183:37 | n | -| main.rs:183:43:183:72 | ...::D {...} | D | main.rs:183:70:183:70 | n | -| main.rs:186:9:186:38 | ...::C {...} | C | main.rs:186:36:186:36 | n | -| main.rs:187:9:187:38 | ...::D {...} | D | main.rs:187:36:187:36 | n | +| main.rs:217:9:217:15 | TupleStructPat | Some | main.rs:217:14:217:14 | n | +| main.rs:221:9:221:15 | TupleStructPat | Some | main.rs:221:14:221:14 | n | +| main.rs:235:9:235:25 | TupleStructPat | A | main.rs:235:24:235:24 | n | +| main.rs:236:9:236:25 | TupleStructPat | B | main.rs:236:24:236:24 | n | +| main.rs:239:9:239:25 | TupleStructPat | A | main.rs:239:24:239:24 | n | +| main.rs:239:29:239:45 | TupleStructPat | B | main.rs:239:44:239:44 | n | +| main.rs:242:9:242:25 | TupleStructPat | A | main.rs:242:24:242:24 | n | +| main.rs:243:9:243:25 | TupleStructPat | B | main.rs:243:24:243:24 | n | +| main.rs:276:9:276:38 | ...::C {...} | C | main.rs:276:36:276:36 | n | +| main.rs:277:9:277:38 | ...::D {...} | D | main.rs:277:36:277:36 | n | +| main.rs:280:9:280:38 | ...::C {...} | C | main.rs:280:36:280:36 | n | +| main.rs:280:42:280:71 | ...::D {...} | D | main.rs:280:69:280:69 | n | +| main.rs:283:9:283:38 | ...::C {...} | C | main.rs:283:36:283:36 | n | +| main.rs:284:9:284:38 | ...::D {...} | D | main.rs:284:36:284:36 | n | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index bfafa38c3ff..d9a10521997 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -5,24 +5,24 @@ edges | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | provenance | | | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | provenance | | | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | provenance | | -| main.rs:117:14:117:29 | Some(...) [Some] | main.rs:120:9:120:15 | TupleStructPat [Some] | provenance | | -| main.rs:117:19:117:28 | source(...) | main.rs:117:14:117:29 | Some(...) [Some] | provenance | | -| main.rs:120:9:120:15 | TupleStructPat [Some] | main.rs:120:14:120:14 | n | provenance | | -| main.rs:120:14:120:14 | n | main.rs:120:25:120:25 | n | provenance | | -| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:138:9:138:25 | TupleStructPat [A] | provenance | | -| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:142:10:142:26 | TupleStructPat [A] | provenance | | -| main.rs:135:29:135:38 | source(...) | main.rs:135:14:135:39 | ...::A(...) [A] | provenance | | -| main.rs:138:9:138:25 | TupleStructPat [A] | main.rs:138:24:138:24 | n | provenance | | -| main.rs:138:24:138:24 | n | main.rs:138:35:138:35 | n | provenance | | -| main.rs:142:10:142:26 | TupleStructPat [A] | main.rs:142:25:142:25 | n | provenance | | -| main.rs:142:25:142:25 | n | main.rs:142:57:142:57 | n | provenance | | -| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:179:9:179:38 | ...::C {...} [C] | provenance | | -| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:183:10:183:39 | ...::C {...} [C] | provenance | | -| main.rs:175:18:175:27 | source(...) | main.rs:174:14:176:5 | ...::C {...} [C] | provenance | | -| main.rs:179:9:179:38 | ...::C {...} [C] | main.rs:179:36:179:36 | n | provenance | | -| main.rs:179:36:179:36 | n | main.rs:179:48:179:48 | n | provenance | | -| main.rs:183:10:183:39 | ...::C {...} [C] | main.rs:183:37:183:37 | n | provenance | | -| main.rs:183:37:183:37 | n | main.rs:183:83:183:83 | n | provenance | | +| main.rs:214:14:214:29 | Some(...) [Some] | main.rs:217:9:217:15 | TupleStructPat [Some] | provenance | | +| main.rs:214:19:214:28 | source(...) | main.rs:214:14:214:29 | Some(...) [Some] | provenance | | +| main.rs:217:9:217:15 | TupleStructPat [Some] | main.rs:217:14:217:14 | n | provenance | | +| main.rs:217:14:217:14 | n | main.rs:217:25:217:25 | n | provenance | | +| main.rs:232:14:232:39 | ...::A(...) [A] | main.rs:235:9:235:25 | TupleStructPat [A] | provenance | | +| main.rs:232:14:232:39 | ...::A(...) [A] | main.rs:239:9:239:25 | TupleStructPat [A] | provenance | | +| main.rs:232:29:232:38 | source(...) | main.rs:232:14:232:39 | ...::A(...) [A] | provenance | | +| main.rs:235:9:235:25 | TupleStructPat [A] | main.rs:235:24:235:24 | n | provenance | | +| main.rs:235:24:235:24 | n | main.rs:235:35:235:35 | n | provenance | | +| main.rs:239:9:239:25 | TupleStructPat [A] | main.rs:239:24:239:24 | n | provenance | | +| main.rs:239:24:239:24 | n | main.rs:239:55:239:55 | n | provenance | | +| main.rs:271:14:273:5 | ...::C {...} [C] | main.rs:276:9:276:38 | ...::C {...} [C] | provenance | | +| main.rs:271:14:273:5 | ...::C {...} [C] | main.rs:280:9:280:38 | ...::C {...} [C] | provenance | | +| main.rs:272:18:272:27 | source(...) | main.rs:271:14:273:5 | ...::C {...} [C] | provenance | | +| main.rs:276:9:276:38 | ...::C {...} [C] | main.rs:276:36:276:36 | n | provenance | | +| main.rs:276:36:276:36 | n | main.rs:276:48:276:48 | n | provenance | | +| main.rs:280:9:280:38 | ...::C {...} [C] | main.rs:280:36:280:36 | n | provenance | | +| main.rs:280:36:280:36 | n | main.rs:280:81:280:81 | n | provenance | | nodes | main.rs:15:10:15:18 | source(...) | semmle.label | source(...) | | main.rs:19:13:19:21 | source(...) | semmle.label | source(...) | @@ -35,27 +35,27 @@ nodes | main.rs:47:10:47:10 | b | semmle.label | b | | main.rs:53:9:53:17 | source(...) | semmle.label | source(...) | | main.rs:54:10:54:10 | i | semmle.label | i | -| main.rs:117:14:117:29 | Some(...) [Some] | semmle.label | Some(...) [Some] | -| main.rs:117:19:117:28 | source(...) | semmle.label | source(...) | -| main.rs:120:9:120:15 | TupleStructPat [Some] | semmle.label | TupleStructPat [Some] | -| main.rs:120:14:120:14 | n | semmle.label | n | -| main.rs:120:25:120:25 | n | semmle.label | n | -| main.rs:135:14:135:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | -| main.rs:135:29:135:38 | source(...) | semmle.label | source(...) | -| main.rs:138:9:138:25 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | -| main.rs:138:24:138:24 | n | semmle.label | n | -| main.rs:138:35:138:35 | n | semmle.label | n | -| main.rs:142:10:142:26 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | -| main.rs:142:25:142:25 | n | semmle.label | n | -| main.rs:142:57:142:57 | n | semmle.label | n | -| main.rs:174:14:176:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | -| main.rs:175:18:175:27 | source(...) | semmle.label | source(...) | -| main.rs:179:9:179:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | -| main.rs:179:36:179:36 | n | semmle.label | n | -| main.rs:179:48:179:48 | n | semmle.label | n | -| main.rs:183:10:183:39 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | -| main.rs:183:37:183:37 | n | semmle.label | n | -| main.rs:183:83:183:83 | n | semmle.label | n | +| main.rs:214:14:214:29 | Some(...) [Some] | semmle.label | Some(...) [Some] | +| main.rs:214:19:214:28 | source(...) | semmle.label | source(...) | +| main.rs:217:9:217:15 | TupleStructPat [Some] | semmle.label | TupleStructPat [Some] | +| main.rs:217:14:217:14 | n | semmle.label | n | +| main.rs:217:25:217:25 | n | semmle.label | n | +| main.rs:232:14:232:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | +| main.rs:232:29:232:38 | source(...) | semmle.label | source(...) | +| main.rs:235:9:235:25 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | +| main.rs:235:24:235:24 | n | semmle.label | n | +| main.rs:235:35:235:35 | n | semmle.label | n | +| main.rs:239:9:239:25 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | +| main.rs:239:24:239:24 | n | semmle.label | n | +| main.rs:239:55:239:55 | n | semmle.label | n | +| main.rs:271:14:273:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:272:18:272:27 | source(...) | semmle.label | source(...) | +| main.rs:276:9:276:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:276:36:276:36 | n | semmle.label | n | +| main.rs:276:48:276:48 | n | semmle.label | n | +| main.rs:280:9:280:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:280:36:280:36 | n | semmle.label | n | +| main.rs:280:81:280:81 | n | semmle.label | n | subpaths testFailures #select @@ -65,8 +65,8 @@ testFailures | main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | source(...) | source(...) | | main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) | source(...) | | main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) | source(...) | -| main.rs:120:25:120:25 | n | main.rs:117:19:117:28 | source(...) | main.rs:120:25:120:25 | n | $@ | main.rs:117:19:117:28 | source(...) | source(...) | -| main.rs:138:35:138:35 | n | main.rs:135:29:135:38 | source(...) | main.rs:138:35:138:35 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) | -| main.rs:142:57:142:57 | n | main.rs:135:29:135:38 | source(...) | main.rs:142:57:142:57 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) | -| main.rs:179:48:179:48 | n | main.rs:175:18:175:27 | source(...) | main.rs:179:48:179:48 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) | -| main.rs:183:83:183:83 | n | main.rs:175:18:175:27 | source(...) | main.rs:183:83:183:83 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) | +| main.rs:217:25:217:25 | n | main.rs:214:19:214:28 | source(...) | main.rs:217:25:217:25 | n | $@ | main.rs:214:19:214:28 | source(...) | source(...) | +| main.rs:235:35:235:35 | n | main.rs:232:29:232:38 | source(...) | main.rs:235:35:235:35 | n | $@ | main.rs:232:29:232:38 | source(...) | source(...) | +| main.rs:239:55:239:55 | n | main.rs:232:29:232:38 | source(...) | main.rs:239:55:239:55 | n | $@ | main.rs:232:29:232:38 | source(...) | source(...) | +| main.rs:276:48:276:48 | n | main.rs:272:18:272:27 | source(...) | main.rs:276:48:276:48 | n | $@ | main.rs:272:18:272:27 | source(...) | source(...) | +| main.rs:280:81:280:81 | n | main.rs:272:18:272:27 | source(...) | main.rs:280:81:280:81 | n | $@ | main.rs:272:18:272:27 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index 9a9e6b467e0..89482c86db4 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -54,52 +54,149 @@ fn assignment() { sink(i); // $ hasValueFlow=6 } +fn block_expression1() -> i64 { + let a = { 0 }; + a +} + +fn block_expression2(b: bool) -> i64 { + let a = 'block: { + if b { + break 'block 1; + }; + 2 + }; + a +} + +fn block_expression3(b: bool) -> i64 { + let a = 'block: { + if b { + break 'block 1; + } + break 'block 2; + }; + a +} + // ----------------------------------------------------------------------------- -// Data flow through data structures by writing and reading +// Data flow through `Box` fn box_deref() { let i = Box::new(source(7)); sink(*i); // $ MISSING: hasValueFlow=7 } +// ----------------------------------------------------------------------------- +// Data flow through tuples + fn tuple() { let a = (source(8), 2); sink(a.0); // $ MISSING: hasValueFlow=8 sink(a.1); } +fn tuple_match() { + let a = (2, source(38), 2); + let (a0, a1, a2) = a; + sink(a0); + sink(a1); // $ MISSING: hasValueFlow=38 + sink(a2); +} + +fn tuple_mutation() { + let mut a = (2, source(38)); + sink(a.0); + sink(a.1); // $ MISSING: hasValueFlow=38 + a.1 = 2; + a.0 = source(70); + sink(a.0); // $ MISSING: hasValueFlow=70 + sink(a.1); +} + +fn tuple_nested() { + let a = (source(59), 3); + let b = (a, 3); + sink(b.0.0); + sink(b.0.1); // $ MISSING: hasValueFlow=59 + sink(b.1); +} + +// ----------------------------------------------------------------------------- +// Data flow through structs + struct Point { x: i64, y: i64, - z: i64, } fn struct_field() { let p = Point { x: source(9), y: 2, - z: source(10), }; sink(p.x); // $ MISSING: hasValueFlow=9 sink(p.y); - sink(p.z); // $ MISSING: hasValueFlow=10 } -// ----------------------------------------------------------------------------- -// Data flow through data structures by pattern matching +fn struct_mutation() { + let mut p = Point { + x: source(9), + y: 2, + }; + sink(p.y); + p.y = source(54); + sink(p.y); // $ MISSING: hasValueFlow=54 +} fn struct_pattern_match() { let p = Point { x: source(11), y: 2, - z: source(12), }; - let Point { x: a, y: b, z: c } = p; + let Point { x: a, y: b } = p; sink(a); // $ MISSING: hasValueFlow=11 sink(b); - sink(c); // $ MISSING: hasValueFlow=12 } +struct Point3D { + plane: Point, + z: i64 +} + +fn struct_nested_field() { + let p = Point3D { + plane: Point { + x: 2, + y: source(77), + }, + z: 4 + }; + sink(p.plane.x); + sink(p.plane.y); // $ MISSING: hasValueFlow=77 + sink(p.z); +} + +fn struct_nested_match() { + let p = Point3D { + plane: Point { + x: 2, + y: source(93), + }, + z: 4 + }; + match p { + Point3D { plane: Point { x, y }, z, } => { + sink(x); + sink(y); // MISSING: hasValueFlow=93 + sink(z); + } + } +} + +// ----------------------------------------------------------------------------- +// Data flow through enums + fn option_pattern_match_qualified() { let s1 = Option::Some(source(13)); let s2 = Option::Some(2); @@ -139,7 +236,7 @@ fn custom_tuple_enum_pattern_match_qualified() { MyTupleEnum::B(n) => sink(n), } match s1 { - (MyTupleEnum::A(n) | MyTupleEnum::B(n)) => sink(n), // $ hasValueFlow=15 + MyTupleEnum::A(n) | MyTupleEnum::B(n) => sink(n), // $ hasValueFlow=15 } match s2 { MyTupleEnum::A(n) => sink(n), @@ -157,7 +254,7 @@ fn custom_tuple_enum_pattern_match_unqualified() { B(n) => sink(n), } match s1 { - (A(n) | B(n)) => sink(n), // $ MISSING: hasValueFlow=16 + A(n) | B(n) => sink(n), // $ MISSING: hasValueFlow=16 } match s2 { A(n) => sink(n), @@ -180,7 +277,7 @@ fn custom_record_enum_pattern_match_qualified() { MyRecordEnum::D { field_d: n } => sink(n), } match s1 { - (MyRecordEnum::C { field_c: n } | MyRecordEnum::D { field_d: n }) => sink(n), // $ hasValueFlow=17 + MyRecordEnum::C { field_c: n } | MyRecordEnum::D { field_d: n } => sink(n), // $ hasValueFlow=17 } match s2 { MyRecordEnum::C { field_c: n } => sink(n), @@ -200,7 +297,7 @@ fn custom_record_enum_pattern_match_unqualified() { D { field_d: n } => sink(n), } match s1 { - (C { field_c: n } | D { field_d: n }) => sink(n), // $ MISSING: hasValueFlow=18 + C { field_c: n } | D { field_d: n } => sink(n), // $ MISSING: hasValueFlow=18 } match s2 { C { field_c: n } => sink(n), @@ -208,31 +305,6 @@ fn custom_record_enum_pattern_match_unqualified() { } } -fn block_expression1() -> i64 { - let a = { 0 }; - a -} - -fn block_expression2(b: bool) -> i64 { - let a = 'block: { - if b { - break 'block 1; - }; - 2 - }; - a -} - -fn block_expression3(b: bool) -> i64 { - let a = 'block: { - if b { - break 'block 1; - } - break 'block 2; - }; - a -} - fn main() { direct(); variable_usage(); @@ -242,8 +314,14 @@ fn main() { assignment(); box_deref(); tuple(); + tuple_match(); + tuple_mutation(); + tuple_nested(); struct_field(); + struct_mutation(); struct_pattern_match(); + struct_nested_field(); + struct_nested_match(); option_pattern_match_qualified(); option_pattern_match_unqualified(); custom_tuple_enum_pattern_match_qualified(); From d89678f49f46e79421a4da65111de531dc80f6de Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Wed, 27 Nov 2024 14:26:25 +0100 Subject: [PATCH 11/56] Rust: Data flow through tuple and struct fields --- .../rust/dataflow/internal/DataFlowImpl.qll | 152 +++++++++++++++--- .../dataflow/local/DataFlowStep.expected | 45 +++++- .../dataflow/local/inline-flow.expected | 40 +++++ .../test/library-tests/dataflow/local/main.rs | 12 +- 4 files changed, 220 insertions(+), 29 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 6fcb878c8ea..84f1805a649 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -252,10 +252,10 @@ module Node { * Nodes corresponding to AST elements, for example `ExprNode`, usually refer * to the value before the update. */ - final class PostUpdateNode extends Node, TArgumentPostUpdateNode { + final class PostUpdateNode extends Node, TExprPostUpdateNode { private ExprCfgNode n; - PostUpdateNode() { this = TArgumentPostUpdateNode(n) } + PostUpdateNode() { this = TExprPostUpdateNode(n) } /** Gets the node before the state update. */ Node getPreUpdateNode() { result = TExprNode(n) } @@ -449,6 +449,49 @@ private class VariantFieldContent extends VariantContent, TVariantFieldContent { } } +/** A canonical path pointing to a struct. */ +private class StructCanonicalPath extends MkStructCanonicalPath { + CrateOriginOption crate; + string path; + + StructCanonicalPath() { this = MkStructCanonicalPath(crate, path) } + + /** Gets the underlying struct. */ + Struct getStruct() { hasExtendedCanonicalPath(result, crate, path) } + + string toString() { result = this.getStruct().getName().getText() } + + Location getLocation() { result = this.getStruct().getLocation() } +} + +/** Content stored in a field on a struct. */ +private class StructFieldContent extends VariantContent, TStructFieldContent { + private StructCanonicalPath s; + private string field_; + + StructFieldContent() { this = TStructFieldContent(s, field_) } + + StructCanonicalPath getStructCanonicalPath(string field) { result = s and field = field_ } + + override string toString() { result = s.toString() + "." + field_.toString() } +} + +/** + * Content stored at a position in a tuple. + * + * NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal, + * hence we don't store a canonical path for them. + */ +private class TuplePositionContent extends VariantContent, TTuplePositionContent { + private int pos; + + TuplePositionContent() { this = TTuplePositionContent(pos) } + + int getPosition() { result = pos } + + override string toString() { result = "tuple." + pos.toString() } +} + /** A value that represents a set of `Content`s. */ abstract class ContentSet extends TContentSet { /** Gets a textual representation of this element. */ @@ -608,6 +651,14 @@ module RustDataFlow implements InputSig { */ predicate jumpStep(Node node1, Node node2) { none() } + /** Holds if path `p` resolves to struct `s`. */ + private predicate pathResolveToStructCanonicalPath(Path p, StructCanonicalPath s) { + exists(CrateOriginOption crate, string path | + resolveExtendedCanonicalPath(p, crate, path) and + s = MkStructCanonicalPath(crate, path) + ) + } + /** Holds if path `p` resolves to variant `v`. */ private predicate pathResolveToVariantCanonicalPath(Path p, VariantCanonicalPath v) { exists(CrateOriginOption crate, string path | @@ -636,6 +687,12 @@ module RustDataFlow implements InputSig { pathResolveToVariantCanonicalPath(p.getPath(), v) } + /** Holds if `p` destructs an struct `s`. */ + pragma[nomagic] + private predicate structDestruction(RecordPat p, StructCanonicalPath s) { + pathResolveToStructCanonicalPath(p.getPath(), s) + } + /** * Holds if data can flow from `node1` to `node2` via a read of `c`. Thus, * `node1` references an object with a content `c.getAReadContent()` whose @@ -652,10 +709,24 @@ module RustDataFlow implements InputSig { or exists(RecordPatCfgNode pat, string field | pat = node1.asPat() and - recordVariantDestruction(pat.getPat(), - c.(VariantFieldContent).getVariantCanonicalPath(field)) and + ( + // Pattern destructs a struct-like variant. + recordVariantDestruction(pat.getPat(), + c.(VariantFieldContent).getVariantCanonicalPath(field)) + or + // Pattern destructs a struct. + structDestruction(pat.getPat(), c.(StructFieldContent).getStructCanonicalPath(field)) + ) and node2.asPat() = pat.getFieldPat(field) ) + or + exists(FieldExprCfgNode access | + // Read of a tuple entry + access.getNameRef().getText().toInt() = c.(TuplePositionContent).getPosition() and + // TODO: Handle read of a struct field. + node1.asExpr() = access.getExpr() and + node2.asExpr() = access + ) ) } @@ -671,6 +742,12 @@ module RustDataFlow implements InputSig { pathResolveToVariantCanonicalPath(re.getPath(), v) } + /** Holds if `re` constructs a struct value of type `v`. */ + pragma[nomagic] + private predicate structConstruction(RecordExpr re, StructCanonicalPath s) { + pathResolveToStructCanonicalPath(re.getPath(), s) + } + /** * Holds if data can flow from `node1` to `node2` via a store into `c`. Thus, * `node2` references an object with a content `c.getAStoreContent()` that @@ -678,23 +755,31 @@ module RustDataFlow implements InputSig { */ predicate storeStep(Node node1, ContentSet cs, Node node2) { exists(Content c | c = cs.(SingletonContentSet).getContent() | - node2.asExpr() = - any(CallExprCfgNode call, int pos | - tupleVariantConstruction(call.getCallExpr(), - c.(VariantPositionContent).getVariantCanonicalPath(pos)) and - node1.asExpr() = call.getArgument(pos) - | - call - ) + exists(CallExprCfgNode call, int pos | + tupleVariantConstruction(call.getCallExpr(), + c.(VariantPositionContent).getVariantCanonicalPath(pos)) and + node1.asExpr() = call.getArgument(pos) and + node2.asExpr() = call + ) or - node2.asExpr() = - any(RecordExprCfgNode re, string field | + exists(RecordExprCfgNode re, string field | + ( + // Expression is for a struct-like enum variant. recordVariantConstruction(re.getRecordExpr(), - c.(VariantFieldContent).getVariantCanonicalPath(field)) and - node1.asExpr() = re.getFieldExpr(field) - | - re - ) + c.(VariantFieldContent).getVariantCanonicalPath(field)) + or + // Expression is for a struct. + structConstruction(re.getRecordExpr(), + c.(StructFieldContent).getStructCanonicalPath(field)) + ) and + node1.asExpr() = re.getFieldExpr(field) and + node2.asExpr() = re + ) + or + exists(TupleExprCfgNode tuple | + node1.asExpr() = tuple.getField(c.(TuplePositionContent).getPosition()) and + node2.asExpr() = tuple + ) ) } @@ -703,7 +788,14 @@ module RustDataFlow implements InputSig { * any value stored inside `f` is cleared at the pre-update node associated with `x` * in `x.f = newValue`. */ - predicate clearsContent(Node n, ContentSet c) { none() } + predicate clearsContent(Node n, ContentSet c) { + exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access | + assignment.getLhs() = access and + n.asExpr() = access.getExpr() and + access.getNameRef().getText().toInt() = + c.(SingletonContentSet).getContent().(TuplePositionContent).getPosition() + ) + } /** * Holds if the value that is being tracked is expected to be stored inside content `c` @@ -773,7 +865,9 @@ private module Cached { TExprNode(ExprCfgNode n) or TParameterNode(ParamBaseCfgNode p) or TPatNode(PatCfgNode p) or - TArgumentPostUpdateNode(ExprCfgNode e) { isArgumentForCall(e, _, _) } or + TExprPostUpdateNode(ExprCfgNode e) { + isArgumentForCall(e, _, _) or e = any(FieldExprCfgNode access).getExpr() + } or TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) cached @@ -811,6 +905,12 @@ private module Cached { name = ["Ok", "Err"] } + cached + newtype TStructCanonicalPath = + MkStructCanonicalPath(CrateOriginOption crate, string path) { + exists(Struct s | hasExtendedCanonicalPath(s, crate, path)) + } + cached newtype TContent = TVariantPositionContent(VariantCanonicalPath v, int pos) { @@ -826,6 +926,16 @@ private module Cached { } or TVariantFieldContent(VariantCanonicalPath v, string field) { field = v.getVariant().getFieldList().(RecordFieldList).getAField().getName().getText() + } or + TTuplePositionContent(int pos) { + pos in [0 .. max([ + any(TuplePat pat).getNumberOfFields(), + any(FieldExpr access).getNameRef().getText().toInt() + ] + )] + } or + TStructFieldContent(StructCanonicalPath s, string field) { + field = s.getStruct().getFieldList().(RecordFieldList).getAField().getName().getText() } cached diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 63666e3dec6..1f8464c8152 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -103,9 +103,9 @@ localStep | main.rs:109:10:109:10 | a | main.rs:110:10:110:10 | a | | main.rs:110:10:110:10 | a | main.rs:111:5:111:5 | a | | main.rs:111:5:111:5 | a | main.rs:112:5:112:5 | a | -| main.rs:111:11:111:11 | 2 | main.rs:111:5:111:7 | a.1 | +| main.rs:111:11:111:20 | source(...) | main.rs:111:5:111:7 | a.0 | | main.rs:112:5:112:5 | a | main.rs:113:10:113:10 | a | -| main.rs:112:11:112:20 | source(...) | main.rs:112:5:112:7 | a.0 | +| main.rs:112:11:112:11 | 2 | main.rs:112:5:112:7 | a.1 | | main.rs:113:10:113:10 | a | main.rs:114:10:114:10 | a | | main.rs:118:9:118:9 | [SSA] a | main.rs:119:14:119:14 | a | | main.rs:118:9:118:9 | a | main.rs:118:9:118:9 | [SSA] a | @@ -329,6 +329,31 @@ localStep | main.rs:304:22:304:22 | n | main.rs:304:22:304:22 | [SSA] n | | main.rs:304:29:304:35 | sink(...) | main.rs:302:5:305:5 | match s2 { ... } | storeStep +| main.rs:94:14:94:22 | source(...) | tuple.0 | main.rs:94:13:94:26 | TupleExpr | +| main.rs:94:25:94:25 | 2 | tuple.1 | main.rs:94:13:94:26 | TupleExpr | +| main.rs:100:14:100:14 | 2 | tuple.0 | main.rs:100:13:100:30 | TupleExpr | +| main.rs:100:17:100:26 | source(...) | tuple.1 | main.rs:100:13:100:30 | TupleExpr | +| main.rs:100:29:100:29 | 2 | tuple.2 | main.rs:100:13:100:30 | TupleExpr | +| main.rs:108:18:108:18 | 2 | tuple.0 | main.rs:108:17:108:31 | TupleExpr | +| main.rs:108:21:108:30 | source(...) | tuple.1 | main.rs:108:17:108:31 | TupleExpr | +| main.rs:118:14:118:14 | 3 | tuple.0 | main.rs:118:13:118:27 | TupleExpr | +| main.rs:118:17:118:26 | source(...) | tuple.1 | main.rs:118:13:118:27 | TupleExpr | +| main.rs:119:14:119:14 | a | tuple.0 | main.rs:119:13:119:18 | TupleExpr | +| main.rs:119:17:119:17 | 3 | tuple.1 | main.rs:119:13:119:18 | TupleExpr | +| main.rs:135:12:135:20 | source(...) | Point.x | main.rs:134:13:137:5 | Point {...} | +| main.rs:136:12:136:12 | 2 | Point.y | main.rs:134:13:137:5 | Point {...} | +| main.rs:144:12:144:20 | source(...) | Point.x | main.rs:143:17:146:5 | Point {...} | +| main.rs:145:12:145:12 | 2 | Point.y | main.rs:143:17:146:5 | Point {...} | +| main.rs:154:12:154:21 | source(...) | Point.x | main.rs:153:13:156:5 | Point {...} | +| main.rs:155:12:155:12 | 2 | Point.y | main.rs:153:13:156:5 | Point {...} | +| main.rs:169:16:172:9 | Point {...} | Point3D.plane | main.rs:168:13:174:5 | Point3D {...} | +| main.rs:170:16:170:16 | 2 | Point.x | main.rs:169:16:172:9 | Point {...} | +| main.rs:171:16:171:25 | source(...) | Point.y | main.rs:169:16:172:9 | Point {...} | +| main.rs:173:12:173:12 | 4 | Point3D.z | main.rs:168:13:174:5 | Point3D {...} | +| main.rs:182:16:185:9 | Point {...} | Point3D.plane | main.rs:181:13:187:5 | Point3D {...} | +| main.rs:183:16:183:16 | 2 | Point.x | main.rs:182:16:185:9 | Point {...} | +| main.rs:184:16:184:25 | source(...) | Point.y | main.rs:182:16:185:9 | Point {...} | +| main.rs:186:12:186:12 | 4 | Point3D.z | main.rs:181:13:187:5 | Point3D {...} | | main.rs:214:19:214:28 | source(...) | Some | main.rs:214:14:214:29 | Some(...) | | main.rs:215:19:215:19 | 2 | Some | main.rs:215:14:215:20 | Some(...) | | main.rs:232:29:232:38 | source(...) | A | main.rs:232:14:232:39 | ...::A(...) | @@ -338,6 +363,22 @@ storeStep | main.rs:312:27:312:27 | 0 | Some | main.rs:312:22:312:28 | Some(...) | readStep | main.rs:33:9:33:15 | TupleStructPat | Some | main.rs:33:14:33:14 | _ | +| main.rs:95:10:95:10 | a | tuple.0 | main.rs:95:10:95:12 | a.0 | +| main.rs:96:10:96:10 | a | tuple.1 | main.rs:96:10:96:12 | a.1 | +| main.rs:109:10:109:10 | a | tuple.0 | main.rs:109:10:109:12 | a.0 | +| main.rs:110:10:110:10 | a | tuple.1 | main.rs:110:10:110:12 | a.1 | +| main.rs:111:5:111:5 | a | tuple.0 | main.rs:111:5:111:7 | a.0 | +| main.rs:112:5:112:5 | a | tuple.1 | main.rs:112:5:112:7 | a.1 | +| main.rs:113:10:113:10 | a | tuple.0 | main.rs:113:10:113:12 | a.0 | +| main.rs:114:10:114:10 | a | tuple.1 | main.rs:114:10:114:12 | a.1 | +| main.rs:120:10:120:10 | b | tuple.0 | main.rs:120:10:120:12 | b.0 | +| main.rs:120:10:120:12 | b.0 | tuple.0 | main.rs:120:10:120:14 | ... .0 | +| main.rs:121:10:121:10 | b | tuple.0 | main.rs:121:10:121:12 | b.0 | +| main.rs:121:10:121:12 | b.0 | tuple.1 | main.rs:121:10:121:14 | ... .1 | +| main.rs:122:10:122:10 | b | tuple.1 | main.rs:122:10:122:12 | b.1 | +| main.rs:157:9:157:28 | Point {...} | Point.x | main.rs:157:20:157:20 | a | +| main.rs:157:9:157:28 | Point {...} | Point.y | main.rs:157:26:157:26 | b | +| main.rs:189:9:189:45 | Point3D {...} | Point3D.plane | main.rs:189:26:189:39 | Point {...} | | main.rs:217:9:217:15 | TupleStructPat | Some | main.rs:217:14:217:14 | n | | main.rs:221:9:221:15 | TupleStructPat | Some | main.rs:221:14:221:14 | n | | main.rs:235:9:235:25 | TupleStructPat | A | main.rs:235:24:235:24 | n | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index d9a10521997..24aadadc589 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -5,6 +5,22 @@ edges | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | provenance | | | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | provenance | | | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | provenance | | +| main.rs:94:13:94:26 | TupleExpr [tuple.0] | main.rs:95:10:95:10 | a [tuple.0] | provenance | | +| main.rs:94:14:94:22 | source(...) | main.rs:94:13:94:26 | TupleExpr [tuple.0] | provenance | | +| main.rs:95:10:95:10 | a [tuple.0] | main.rs:95:10:95:12 | a.0 | provenance | | +| main.rs:108:17:108:31 | TupleExpr [tuple.1] | main.rs:110:10:110:10 | a [tuple.1] | provenance | | +| main.rs:108:21:108:30 | source(...) | main.rs:108:17:108:31 | TupleExpr [tuple.1] | provenance | | +| main.rs:110:10:110:10 | a [tuple.1] | main.rs:110:10:110:12 | a.1 | provenance | | +| main.rs:118:13:118:27 | TupleExpr [tuple.1] | main.rs:119:14:119:14 | a [tuple.1] | provenance | | +| main.rs:118:17:118:26 | source(...) | main.rs:118:13:118:27 | TupleExpr [tuple.1] | provenance | | +| main.rs:119:13:119:18 | TupleExpr [tuple.0, tuple.1] | main.rs:121:10:121:10 | b [tuple.0, tuple.1] | provenance | | +| main.rs:119:14:119:14 | a [tuple.1] | main.rs:119:13:119:18 | TupleExpr [tuple.0, tuple.1] | provenance | | +| main.rs:121:10:121:10 | b [tuple.0, tuple.1] | main.rs:121:10:121:12 | b.0 [tuple.1] | provenance | | +| main.rs:121:10:121:12 | b.0 [tuple.1] | main.rs:121:10:121:14 | ... .1 | provenance | | +| main.rs:153:13:156:5 | Point {...} [Point.x] | main.rs:157:9:157:28 | Point {...} [Point.x] | provenance | | +| main.rs:154:12:154:21 | source(...) | main.rs:153:13:156:5 | Point {...} [Point.x] | provenance | | +| main.rs:157:9:157:28 | Point {...} [Point.x] | main.rs:157:20:157:20 | a | provenance | | +| main.rs:157:20:157:20 | a | main.rs:158:10:158:10 | a | provenance | | | main.rs:214:14:214:29 | Some(...) [Some] | main.rs:217:9:217:15 | TupleStructPat [Some] | provenance | | | main.rs:214:19:214:28 | source(...) | main.rs:214:14:214:29 | Some(...) [Some] | provenance | | | main.rs:217:9:217:15 | TupleStructPat [Some] | main.rs:217:14:217:14 | n | provenance | | @@ -35,6 +51,26 @@ nodes | main.rs:47:10:47:10 | b | semmle.label | b | | main.rs:53:9:53:17 | source(...) | semmle.label | source(...) | | main.rs:54:10:54:10 | i | semmle.label | i | +| main.rs:94:13:94:26 | TupleExpr [tuple.0] | semmle.label | TupleExpr [tuple.0] | +| main.rs:94:14:94:22 | source(...) | semmle.label | source(...) | +| main.rs:95:10:95:10 | a [tuple.0] | semmle.label | a [tuple.0] | +| main.rs:95:10:95:12 | a.0 | semmle.label | a.0 | +| main.rs:108:17:108:31 | TupleExpr [tuple.1] | semmle.label | TupleExpr [tuple.1] | +| main.rs:108:21:108:30 | source(...) | semmle.label | source(...) | +| main.rs:110:10:110:10 | a [tuple.1] | semmle.label | a [tuple.1] | +| main.rs:110:10:110:12 | a.1 | semmle.label | a.1 | +| main.rs:118:13:118:27 | TupleExpr [tuple.1] | semmle.label | TupleExpr [tuple.1] | +| main.rs:118:17:118:26 | source(...) | semmle.label | source(...) | +| main.rs:119:13:119:18 | TupleExpr [tuple.0, tuple.1] | semmle.label | TupleExpr [tuple.0, tuple.1] | +| main.rs:119:14:119:14 | a [tuple.1] | semmle.label | a [tuple.1] | +| main.rs:121:10:121:10 | b [tuple.0, tuple.1] | semmle.label | b [tuple.0, tuple.1] | +| main.rs:121:10:121:12 | b.0 [tuple.1] | semmle.label | b.0 [tuple.1] | +| main.rs:121:10:121:14 | ... .1 | semmle.label | ... .1 | +| main.rs:153:13:156:5 | Point {...} [Point.x] | semmle.label | Point {...} [Point.x] | +| main.rs:154:12:154:21 | source(...) | semmle.label | source(...) | +| main.rs:157:9:157:28 | Point {...} [Point.x] | semmle.label | Point {...} [Point.x] | +| main.rs:157:20:157:20 | a | semmle.label | a | +| main.rs:158:10:158:10 | a | semmle.label | a | | main.rs:214:14:214:29 | Some(...) [Some] | semmle.label | Some(...) [Some] | | main.rs:214:19:214:28 | source(...) | semmle.label | source(...) | | main.rs:217:9:217:15 | TupleStructPat [Some] | semmle.label | TupleStructPat [Some] | @@ -65,6 +101,10 @@ testFailures | main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | source(...) | source(...) | | main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) | source(...) | | main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) | source(...) | +| main.rs:95:10:95:12 | a.0 | main.rs:94:14:94:22 | source(...) | main.rs:95:10:95:12 | a.0 | $@ | main.rs:94:14:94:22 | source(...) | source(...) | +| main.rs:110:10:110:12 | a.1 | main.rs:108:21:108:30 | source(...) | main.rs:110:10:110:12 | a.1 | $@ | main.rs:108:21:108:30 | source(...) | source(...) | +| main.rs:121:10:121:14 | ... .1 | main.rs:118:17:118:26 | source(...) | main.rs:121:10:121:14 | ... .1 | $@ | main.rs:118:17:118:26 | source(...) | source(...) | +| main.rs:158:10:158:10 | a | main.rs:154:12:154:21 | source(...) | main.rs:158:10:158:10 | a | $@ | main.rs:154:12:154:21 | source(...) | source(...) | | main.rs:217:25:217:25 | n | main.rs:214:19:214:28 | source(...) | main.rs:217:25:217:25 | n | $@ | main.rs:214:19:214:28 | source(...) | source(...) | | main.rs:235:35:235:35 | n | main.rs:232:29:232:38 | source(...) | main.rs:235:35:235:35 | n | $@ | main.rs:232:29:232:38 | source(...) | source(...) | | main.rs:239:55:239:55 | n | main.rs:232:29:232:38 | source(...) | main.rs:239:55:239:55 | n | $@ | main.rs:232:29:232:38 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index 89482c86db4..7110d6072c1 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -92,7 +92,7 @@ fn box_deref() { fn tuple() { let a = (source(8), 2); - sink(a.0); // $ MISSING: hasValueFlow=8 + sink(a.0); // $ hasValueFlow=8 sink(a.1); } @@ -107,18 +107,18 @@ fn tuple_match() { fn tuple_mutation() { let mut a = (2, source(38)); sink(a.0); - sink(a.1); // $ MISSING: hasValueFlow=38 - a.1 = 2; + sink(a.1); // $ hasValueFlow=38 a.0 = source(70); + a.1 = 2; sink(a.0); // $ MISSING: hasValueFlow=70 sink(a.1); } fn tuple_nested() { - let a = (source(59), 3); + let a = (3, source(59)); let b = (a, 3); sink(b.0.0); - sink(b.0.1); // $ MISSING: hasValueFlow=59 + sink(b.0.1); // $ hasValueFlow=59 sink(b.1); } @@ -155,7 +155,7 @@ fn struct_pattern_match() { y: 2, }; let Point { x: a, y: b } = p; - sink(a); // $ MISSING: hasValueFlow=11 + sink(a); // $ hasValueFlow=11 sink(b); } From 41f21d429ba46b16aa3285f75482e5fbb1228a00 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 09:18:51 +0100 Subject: [PATCH 12/56] JS: Added test case which is not flagged but should be abusing new RegExp with global flag --- .../Security/CWE-116/IncompleteSanitization/tst.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js index dbd04664a52..1a10415a317 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js @@ -327,4 +327,8 @@ function incompleteComplexSanitizers() { if (str === "\"") return """; }) + '"'; -} \ No newline at end of file +} + +function typicalBadHtmlSanitizers(s) { + s().replace(new RegExp("[<>]", "g"),''); // NOT OK -- should be not okay, but is not flagged +} From 38be0e4c0a0b7368c8d3f43785f48fe257f6b702 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 09:20:34 +0100 Subject: [PATCH 13/56] JS: Now BadHtmlSanitizers also flags new RegExp as potential issue --- .../javascript/security/IncompleteBlacklistSanitizer.qll | 2 +- .../IncompleteBlacklistSanitizer.expected | 3 +++ .../query-tests/Security/CWE-116/IncompleteSanitization/tst.js | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll index 6b05e2c754d..5864d8ca7c8 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll @@ -74,7 +74,7 @@ private StringReplaceCall getAStringReplaceMethodCall(StringReplaceCall n) { module HtmlSanitization { private predicate fixedGlobalReplacement(StringReplaceCallSequence chain) { forall(StringReplaceCall member | member = chain.getAMember() | - member.isGlobal() and member.getArgument(0) instanceof DataFlow::RegExpLiteralNode + member.isGlobal() and member.getArgument(0) instanceof DataFlow::RegExpCreationNode ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected index 4223a4224d3..00d07f97657 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected @@ -65,3 +65,6 @@ | tst.js:305:10:305:34 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize double quotes | | tst.js:309:10:318:3 | s().rep ... ;";\\n\\t}) | This HTML sanitizer does not sanitize single quotes | | tst.js:320:9:329:3 | s().rep ... ;";\\n\\t}) | This HTML sanitizer does not sanitize single quotes | +| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize ampersands | +| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize double quotes | +| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize single quotes | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js index 1a10415a317..af75382662b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js @@ -330,5 +330,5 @@ function incompleteComplexSanitizers() { } function typicalBadHtmlSanitizers(s) { - s().replace(new RegExp("[<>]", "g"),''); // NOT OK -- should be not okay, but is not flagged + s().replace(new RegExp("[<>]", "g"),''); // NOT OK } From 89f3b6f8d34027d6ba35b0ab9816970134896ce0 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 09:35:27 +0100 Subject: [PATCH 14/56] JS: Added test case for bad sanitizer with unknown flags, currently not flagged. --- .../Security/CWE-116/IncompleteSanitization/tst.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js index af75382662b..d15351e2860 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js @@ -332,3 +332,7 @@ function incompleteComplexSanitizers() { function typicalBadHtmlSanitizers(s) { s().replace(new RegExp("[<>]", "g"),''); // NOT OK } + +function typicalBadHtmlSanitizers(s) { + s().replace(new RegExp("[<>]", unknown()),''); // NOT OK -- should be flagged, because it is st ill a bad sanitizer +} From 18c7b18f82c4fd1fb795e983f032c4fb0feb7f6f Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 09:37:57 +0100 Subject: [PATCH 15/56] JS: Now BadHtmlSanitizers new RegExp with unknown flags is also flagged. --- javascript/ql/lib/semmle/javascript/StandardLibrary.qll | 8 ++++++++ .../javascript/security/IncompleteBlacklistSanitizer.qll | 2 +- .../IncompleteBlacklistSanitizer.expected | 3 +++ .../Security/CWE-116/IncompleteSanitization/tst.js | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll index b40f10d9369..db21d883fc1 100644 --- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll @@ -117,6 +117,14 @@ class StringReplaceCall extends DataFlow::MethodCallNode { */ predicate isGlobal() { this.getRegExp().isGlobal() or this.getMethodName() = "replaceAll" } + /** + * Holds if this is a global replacement, that is, the first argument is a regular expression + * with the `g` flag, or this is a call to `.replaceAll()`. + */ + predicate maybeGlobal() { + RegExp::maybeGlobal(this.getRegExp().tryGetFlags()) or this.getMethodName() = "replaceAll" + } + /** * Holds if this call to `replace` replaces `old` with `new`. */ diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll index 5864d8ca7c8..13d5033458a 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll @@ -74,7 +74,7 @@ private StringReplaceCall getAStringReplaceMethodCall(StringReplaceCall n) { module HtmlSanitization { private predicate fixedGlobalReplacement(StringReplaceCallSequence chain) { forall(StringReplaceCall member | member = chain.getAMember() | - member.isGlobal() and member.getArgument(0) instanceof DataFlow::RegExpCreationNode + member.maybeGlobal() and member.getArgument(0) instanceof DataFlow::RegExpCreationNode ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected index 00d07f97657..379ffbdc9c3 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteBlacklistSanitizer.expected @@ -68,3 +68,6 @@ | tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize ampersands | | tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize double quotes | | tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize single quotes | +| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize ampersands | +| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize double quotes | +| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize single quotes | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js index d15351e2860..f2972f0be76 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/tst.js @@ -334,5 +334,5 @@ function typicalBadHtmlSanitizers(s) { } function typicalBadHtmlSanitizers(s) { - s().replace(new RegExp("[<>]", unknown()),''); // NOT OK -- should be flagged, because it is st ill a bad sanitizer + s().replace(new RegExp("[<>]", unknown()),''); // NOT OK } From 41fef0f2b331ecbc0a1fe043e084cb670475cee9 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 11:30:20 +0100 Subject: [PATCH 16/56] JS: Added test cases which cover new RegExp creation with replace on protytpe pulluting --- .../PrototypePollutingAssignment.expected | 20 +++++++++++++++++++ .../PrototypePollutingAssignment/tst.js | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected index 891aeff4221..bad75ffe924 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected @@ -190,6 +190,16 @@ nodes | tst.js:105:5:105:17 | object[taint] | | tst.js:105:5:105:17 | object[taint] | | tst.js:105:12:105:16 | taint | +| tst.js:130:5:130:53 | obj[req ... ), '')] | +| tst.js:130:5:130:53 | obj[req ... ), '')] | +| tst.js:130:9:130:19 | req.query.x | +| tst.js:130:9:130:19 | req.query.x | +| tst.js:130:9:130:52 | req.que ... '), '') | +| tst.js:131:5:131:65 | obj[req ... ), '')] | +| tst.js:131:5:131:65 | obj[req ... ), '')] | +| tst.js:131:9:131:19 | req.query.x | +| tst.js:131:9:131:19 | req.query.x | +| tst.js:131:9:131:64 | req.que ... )), '') | edges | lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | | lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | @@ -366,6 +376,14 @@ edges | tst.js:102:24:102:37 | req.query.data | tst.js:102:17:102:38 | String( ... y.data) | | tst.js:105:12:105:16 | taint | tst.js:105:5:105:17 | object[taint] | | tst.js:105:12:105:16 | taint | tst.js:105:5:105:17 | object[taint] | +| tst.js:130:9:130:19 | req.query.x | tst.js:130:9:130:52 | req.que ... '), '') | +| tst.js:130:9:130:19 | req.query.x | tst.js:130:9:130:52 | req.que ... '), '') | +| tst.js:130:9:130:52 | req.que ... '), '') | tst.js:130:5:130:53 | obj[req ... ), '')] | +| tst.js:130:9:130:52 | req.que ... '), '') | tst.js:130:5:130:53 | obj[req ... ), '')] | +| tst.js:131:9:131:19 | req.query.x | tst.js:131:9:131:64 | req.que ... )), '') | +| tst.js:131:9:131:19 | req.query.x | tst.js:131:9:131:64 | req.que ... )), '') | +| tst.js:131:9:131:64 | req.que ... )), '') | tst.js:131:5:131:65 | obj[req ... ), '')] | +| tst.js:131:9:131:64 | req.que ... )), '') | tst.js:131:5:131:65 | obj[req ... ), '')] | #select | lib.js:6:7:6:9 | obj | lib.js:1:43:1:46 | path | lib.js:6:7:6:9 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:1:43:1:46 | path | library input | | lib.js:15:3:15:14 | obj[path[0]] | lib.js:14:38:14:41 | path | lib.js:15:3:15:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:14:38:14:41 | path | library input | @@ -394,3 +412,5 @@ edges | tst.js:94:5:94:37 | obj[req ... ', '')] | tst.js:94:9:94:19 | req.query.x | tst.js:94:5:94:37 | obj[req ... ', '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:94:9:94:19 | req.query.x | user controlled input | | tst.js:97:5:97:46 | obj[req ... g, '')] | tst.js:97:9:97:19 | req.query.x | tst.js:97:5:97:46 | obj[req ... g, '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:97:9:97:19 | req.query.x | user controlled input | | tst.js:105:5:105:17 | object[taint] | tst.js:102:24:102:37 | req.query.data | tst.js:105:5:105:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:102:24:102:37 | req.query.data | user controlled input | +| tst.js:130:5:130:53 | obj[req ... ), '')] | tst.js:130:9:130:19 | req.query.x | tst.js:130:5:130:53 | obj[req ... ), '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:130:9:130:19 | req.query.x | user controlled input | +| tst.js:131:5:131:65 | obj[req ... ), '')] | tst.js:131:9:131:19 | req.query.x | tst.js:131:5:131:65 | obj[req ... ), '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:131:9:131:19 | req.query.x | user controlled input | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js index d301fe40bf6..1cc830d0d2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js @@ -123,3 +123,10 @@ app.get('/assign', (req, res) => { Object.assign(dest, plainObj[taint]); dest[taint] = taint; // OK - 'dest' is not Object.prototype itself (but possibly a copy) }); + +app.get('/foo', (req, res) => { + let obj = {}; + obj[req.query.x.replace(new RegExp('_', 'g'), '')].x = 'foo'; // OK + obj[req.query.x.replace(new RegExp('_', ''), '')].x = 'foo'; // NOT OK + obj[req.query.x.replace(new RegExp('_', unknownFlags()), '')].x = 'foo'; // OK -- Might be okay but it is currently flagged as a problem +}); From faef9dd8774358c6bdca232bbbb7220cb0556ae4 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 11:32:15 +0100 Subject: [PATCH 17/56] JS: protyte poluting now treats unknownFlags as potentially good sanitization. --- .../dataflow/PrototypePollutingAssignmentQuery.qll | 2 +- .../PrototypePollutingAssignment.expected | 10 ---------- .../CWE-915/PrototypePollutingAssignment/tst.js | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll index 0ba2f26b24c..197b8594244 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll @@ -46,7 +46,7 @@ class Configuration extends TaintTracking::Configuration { // Replacing with "_" is likely to be exploitable not replace.getRawReplacement().getStringValue() = "_" and ( - replace.isGlobal() + replace.maybeGlobal() or // Non-global replace with a non-empty string can also prevent __proto__ by // inserting a chunk of text that doesn't fit anywhere in __proto__ diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected index bad75ffe924..50262859441 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected @@ -195,11 +195,6 @@ nodes | tst.js:130:9:130:19 | req.query.x | | tst.js:130:9:130:19 | req.query.x | | tst.js:130:9:130:52 | req.que ... '), '') | -| tst.js:131:5:131:65 | obj[req ... ), '')] | -| tst.js:131:5:131:65 | obj[req ... ), '')] | -| tst.js:131:9:131:19 | req.query.x | -| tst.js:131:9:131:19 | req.query.x | -| tst.js:131:9:131:64 | req.que ... )), '') | edges | lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | | lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | @@ -380,10 +375,6 @@ edges | tst.js:130:9:130:19 | req.query.x | tst.js:130:9:130:52 | req.que ... '), '') | | tst.js:130:9:130:52 | req.que ... '), '') | tst.js:130:5:130:53 | obj[req ... ), '')] | | tst.js:130:9:130:52 | req.que ... '), '') | tst.js:130:5:130:53 | obj[req ... ), '')] | -| tst.js:131:9:131:19 | req.query.x | tst.js:131:9:131:64 | req.que ... )), '') | -| tst.js:131:9:131:19 | req.query.x | tst.js:131:9:131:64 | req.que ... )), '') | -| tst.js:131:9:131:64 | req.que ... )), '') | tst.js:131:5:131:65 | obj[req ... ), '')] | -| tst.js:131:9:131:64 | req.que ... )), '') | tst.js:131:5:131:65 | obj[req ... ), '')] | #select | lib.js:6:7:6:9 | obj | lib.js:1:43:1:46 | path | lib.js:6:7:6:9 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:1:43:1:46 | path | library input | | lib.js:15:3:15:14 | obj[path[0]] | lib.js:14:38:14:41 | path | lib.js:15:3:15:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:14:38:14:41 | path | library input | @@ -413,4 +404,3 @@ edges | tst.js:97:5:97:46 | obj[req ... g, '')] | tst.js:97:9:97:19 | req.query.x | tst.js:97:5:97:46 | obj[req ... g, '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:97:9:97:19 | req.query.x | user controlled input | | tst.js:105:5:105:17 | object[taint] | tst.js:102:24:102:37 | req.query.data | tst.js:105:5:105:17 | object[taint] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:102:24:102:37 | req.query.data | user controlled input | | tst.js:130:5:130:53 | obj[req ... ), '')] | tst.js:130:9:130:19 | req.query.x | tst.js:130:5:130:53 | obj[req ... ), '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:130:9:130:19 | req.query.x | user controlled input | -| tst.js:131:5:131:65 | obj[req ... ), '')] | tst.js:131:9:131:19 | req.query.x | tst.js:131:5:131:65 | obj[req ... ), '')] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | tst.js:131:9:131:19 | req.query.x | user controlled input | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js index 1cc830d0d2d..a622a891390 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/tst.js @@ -128,5 +128,5 @@ app.get('/foo', (req, res) => { let obj = {}; obj[req.query.x.replace(new RegExp('_', 'g'), '')].x = 'foo'; // OK obj[req.query.x.replace(new RegExp('_', ''), '')].x = 'foo'; // NOT OK - obj[req.query.x.replace(new RegExp('_', unknownFlags()), '')].x = 'foo'; // OK -- Might be okay but it is currently flagged as a problem + obj[req.query.x.replace(new RegExp('_', unknownFlags()), '')].x = 'foo'; // OK }); From 7db6f7c7215183cbee297797e246fb54b5b22ee2 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 12:27:11 +0100 Subject: [PATCH 18/56] JS: Added test cases with new RegExp for Tainted paths, currently works only with literals --- .../dataflow/TaintedPathCustomizations.qll | 6 +- .../CWE-022/TaintedPath/Consistency.expected | 1 + .../CWE-022/TaintedPath/TaintedPath.expected | 313 ++++++++++++++++++ .../CWE-022/TaintedPath/TaintedPath.js | 9 + 4 files changed, 326 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index c24ea7f6110..e6f1a5203d7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -221,10 +221,10 @@ module TaintedPath { this instanceof StringReplaceCall and input = this.getReceiver() and output = this and - not exists(RegExpLiteral literal, RegExpTerm term | - this.(StringReplaceCall).getRegExp().asExpr() = literal and + not exists(DataFlow::RegExpCreationNode regexp, RegExpTerm term | + this.(StringReplaceCall).getRegExp() = regexp and this.(StringReplaceCall).isGlobal() and - literal.getRoot() = term + regexp.getRoot() = term | term.getAMatchedString() = "/" or term.getAMatchedString() = "." or diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected index e69de29bb2d..81656a2af72 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected @@ -0,0 +1 @@ +| TaintedPath.js:207 | did not expect an alert, but found an alert for TaintedPath | OK -- Might be okay depending on what unknownFlags evaluates to. | | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index 0022ca69c6b..4fdd33dcbba 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1517,6 +1517,141 @@ nodes | TaintedPath.js:198:35:198:38 | path | | TaintedPath.js:198:35:198:38 | path | | TaintedPath.js:198:35:198:38 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:24:202:30 | req.url | +| TaintedPath.js:202:24:202:30 | req.url | +| TaintedPath.js:202:24:202:30 | req.url | +| TaintedPath.js:202:24:202:30 | req.url | +| TaintedPath.js:202:24:202:30 | req.url | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | @@ -6680,6 +6815,182 @@ edges | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:195:14:195:37 | url.par ... , true) | | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:195:14:195:37 | url.par ... , true) | | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:195:14:195:37 | url.par ... , true) | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:43 | url.par ... ).query | TaintedPath.js:202:14:202:48 | url.par ... ry.path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:14:202:48 | url.par ... ry.path | TaintedPath.js:202:7:202:48 | path | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:202:14:202:37 | url.par ... , true) | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | +| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | @@ -10499,6 +10810,8 @@ edges | TaintedPath.js:196:31:196:34 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:196:31:196:34 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:197:45:197:48 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:197:45:197:48 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:198:35:198:38 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:198:35:198:38 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | +| TaintedPath.js:206:29:206:85 | path.re ... '), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:206:29:206:85 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | +| TaintedPath.js:207:29:207:97 | path.re ... )), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:207:29:207:97 | path.re ... )), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | examples/TaintedPath.js:8:28:8:34 | req.url | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | This path depends on a $@. | examples/TaintedPath.js:8:28:8:34 | req.url | user-provided value | | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on a $@. | express.js:8:20:8:32 | req.query.bar | user-provided value | | handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on a $@. | handlebars.js:29:46:29:60 | req.params.path | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js index d28549da0ec..13948fc431a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js @@ -197,3 +197,12 @@ var server = http.createServer(function(req, res) { cp.execFileSync("foobar", ["args"], {cwd: path}); // NOT OK cp.execFileSync("foobar", {cwd: path}); // NOT OK }); + +var server = http.createServer(function(req, res) { + let path = url.parse(req.url, true).query.path; + + // Removal of forward-slash or dots. + res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", 'g'), ''))); // OK + res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", ''), ''))); // NOT OK. + res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", unknownFlags()), ''))); // OK -- Might be okay depending on what unknownFlags evaluates to. +}); From eca7a8861555695c7330c7d0cd48f9e234e049c7 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 12:41:59 +0100 Subject: [PATCH 19/56] JS: Fixed docs description --- javascript/ql/lib/semmle/javascript/StandardLibrary.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll index db21d883fc1..e886ff50eb4 100644 --- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll @@ -119,7 +119,7 @@ class StringReplaceCall extends DataFlow::MethodCallNode { /** * Holds if this is a global replacement, that is, the first argument is a regular expression - * with the `g` flag, or this is a call to `.replaceAll()`. + * with the `g` flag or unknown flags, or this is a call to `.replaceAll()`. */ predicate maybeGlobal() { RegExp::maybeGlobal(this.getRegExp().tryGetFlags()) or this.getMethodName() = "replaceAll" From 23b18aeca9618acc31ffb996f2deb77268247896 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 14:20:04 +0100 Subject: [PATCH 20/56] JS: Now unknown flags are not flagged in taint paths --- .../dataflow/TaintedPathCustomizations.qll | 2 +- .../CWE-022/TaintedPath/Consistency.expected | 1 - .../CWE-022/TaintedPath/TaintedPath.expected | 82 ------------------- 3 files changed, 1 insertion(+), 84 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index e6f1a5203d7..f2dd4a95cf0 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -223,7 +223,7 @@ module TaintedPath { output = this and not exists(DataFlow::RegExpCreationNode regexp, RegExpTerm term | this.(StringReplaceCall).getRegExp() = regexp and - this.(StringReplaceCall).isGlobal() and + this.(StringReplaceCall).maybeGlobal() and regexp.getRoot() = term | term.getAMatchedString() = "/" or diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected index 81656a2af72..e69de29bb2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected @@ -1 +0,0 @@ -| TaintedPath.js:207 | did not expect an alert, but found an alert for TaintedPath | OK -- Might be okay depending on what unknownFlags evaluates to. | | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index 4fdd33dcbba..5fa027c40da 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1619,39 +1619,6 @@ nodes | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | @@ -6831,22 +6798,6 @@ edges | TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | | TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | | TaintedPath.js:202:7:202:48 | path | TaintedPath.js:206:29:206:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | -| TaintedPath.js:202:7:202:48 | path | TaintedPath.js:207:29:207:32 | path | | TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | | TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | | TaintedPath.js:202:14:202:37 | url.par ... , true) | TaintedPath.js:202:14:202:43 | url.par ... ).query | @@ -6959,38 +6910,6 @@ edges | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | -| TaintedPath.js:207:29:207:32 | path | TaintedPath.js:207:29:207:97 | path.re ... )), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | @@ -10811,7 +10730,6 @@ edges | TaintedPath.js:197:45:197:48 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:197:45:197:48 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:198:35:198:38 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:198:35:198:38 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:206:29:206:85 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | -| TaintedPath.js:207:29:207:97 | path.re ... )), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:207:29:207:97 | path.re ... )), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | examples/TaintedPath.js:8:28:8:34 | req.url | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | This path depends on a $@. | examples/TaintedPath.js:8:28:8:34 | req.url | user-provided value | | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on a $@. | express.js:8:20:8:32 | req.query.bar | user-provided value | | handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on a $@. | handlebars.js:29:46:29:60 | req.params.path | user-provided value | From 155f1fca85d146acb44fe8cb7d0d91d1b53c78f9 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 15:22:32 +0100 Subject: [PATCH 21/56] JS: Added test cases for unsafe shell command sanitization with RegExpr Object, instead of literal --- .../Security/CWE-078/Consistency.expected | 1 + .../UnsafeShellCommandConstruction.expected | 36 +++++++++++++++++++ .../UnsafeShellCommandConstruction/lib/lib.js | 11 ++++++ 3 files changed, 48 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected index e69de29bb2d..5844d8d221d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected @@ -0,0 +1 @@ +| UnsafeShellCommandConstruction/lib/lib.js:640 | did not expect an alert, but found an alert for UnsafeShellCommandConstruction | OK -- Currently this is flagged as a bad sanitization, but it is not certain that it is bad. | ComandInjection | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected index b4022c8550c..83c4a471854 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected @@ -319,6 +319,22 @@ nodes | lib/lib.js:626:29:626:32 | name | | lib/lib.js:629:25:629:28 | name | | lib/lib.js:629:25:629:28 | name | +| lib/lib.js:632:38:632:41 | name | +| lib/lib.js:632:38:632:41 | name | +| lib/lib.js:633:6:633:68 | sanitized | +| lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | +| lib/lib.js:633:24:633:27 | name | +| lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | +| lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | +| lib/lib.js:634:22:634:30 | sanitized | +| lib/lib.js:634:22:634:30 | sanitized | +| lib/lib.js:639:6:639:84 | sanitized | +| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | +| lib/lib.js:639:24:639:27 | name | +| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | +| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | +| lib/lib.js:640:22:640:30 | sanitized | +| lib/lib.js:640:22:640:30 | sanitized | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -749,6 +765,22 @@ edges | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | +| lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:27 | name | +| lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:27 | name | +| lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:27 | name | +| lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:27 | name | +| lib/lib.js:633:6:633:68 | sanitized | lib/lib.js:634:22:634:30 | sanitized | +| lib/lib.js:633:6:633:68 | sanitized | lib/lib.js:634:22:634:30 | sanitized | +| lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | lib/lib.js:633:6:633:68 | sanitized | +| lib/lib.js:633:24:633:27 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | +| lib/lib.js:633:24:633:27 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | +| lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | +| lib/lib.js:639:6:639:84 | sanitized | lib/lib.js:640:22:640:30 | sanitized | +| lib/lib.js:639:6:639:84 | sanitized | lib/lib.js:640:22:640:30 | sanitized | +| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | lib/lib.js:639:6:639:84 | sanitized | +| lib/lib.js:639:24:639:27 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | +| lib/lib.js:639:24:639:27 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | +| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -879,6 +911,10 @@ edges | lib/lib.js:609:10:609:25 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:609:22:609:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:609:2:609:26 | cp.exec ... + name) | shell command | | lib/lib.js:626:17:626:32 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:626:29:626:32 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:626:9:626:33 | cp.exec ... + name) | shell command | | lib/lib.js:629:13:629:28 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:629:5:629:29 | cp.exec ... + name) | shell command | +| lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:634:2:634:31 | cp.exec ... itized) | shell command | +| lib/lib.js:634:10:634:30 | "rm -rf ... nitized | lib/lib.js:632:38:632:41 | name | lib/lib.js:634:22:634:30 | sanitized | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:634:2:634:31 | cp.exec ... itized) | shell command | +| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:640:2:640:31 | cp.exec ... itized) | shell command | +| lib/lib.js:640:10:640:30 | "rm -rf ... nitized | lib/lib.js:632:38:632:41 | name | lib/lib.js:640:22:640:30 | sanitized | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:640:2:640:31 | cp.exec ... itized) | shell command | | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command | | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4:26 | cp.exec ... + name) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js index 504de998c1c..d3190ceb646 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js @@ -628,3 +628,14 @@ module.exports.veryIndeirect = function (name) { cp.exec("rm -rf " + name); // NOT OK } + +module.exports.sanitizer = function (name) { + var sanitized = "'" + name.replace(new RegExp("\'"), "'\\''") + "'" + cp.exec("rm -rf " + sanitized); // NOT OK + + var sanitized = "'" + name.replace(new RegExp("\'", 'g'), "'\\''") + "'" + cp.exec("rm -rf " + sanitized); // OK + + var sanitized = "'" + name.replace(new RegExp("\'", unknownFlags()), "'\\''") + "'" + cp.exec("rm -rf " + sanitized); // OK -- Currently this is flagged as a bad sanitization, but it is not certain that it is bad. +} From a0df33c3ac53b0e2722e661bc2a35e2f6e90b864 Mon Sep 17 00:00:00 2001 From: Napalys Date: Tue, 26 Nov 2024 15:27:33 +0100 Subject: [PATCH 22/56] JS: UnsafeShellCommand Using unknown flags in the RegExp object is no longer flagged as bad sanitization to reduce false positives. --- ...feShellCommandConstructionCustomizations.qll | 2 +- .../Security/CWE-078/Consistency.expected | 1 - .../UnsafeShellCommandConstruction.expected | 17 ----------------- .../UnsafeShellCommandConstruction/lib/lib.js | 2 +- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index 77625874df9..8e753a5ef63 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -245,7 +245,7 @@ module UnsafeShellCommandConstruction { class ReplaceQuotesSanitizer extends Sanitizer, StringReplaceCall { ReplaceQuotesSanitizer() { this.getAReplacedString() = "'" and - this.isGlobal() and + this.maybeGlobal() and this.getRawReplacement().mayHaveStringValue(["'\\''", ""]) } } diff --git a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected index 5844d8d221d..e69de29bb2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/Consistency.expected @@ -1 +0,0 @@ -| UnsafeShellCommandConstruction/lib/lib.js:640 | did not expect an alert, but found an alert for UnsafeShellCommandConstruction | OK -- Currently this is flagged as a bad sanitization, but it is not certain that it is bad. | ComandInjection | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected index 83c4a471854..f2fa354a305 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/UnsafeShellCommandConstruction.expected @@ -328,13 +328,6 @@ nodes | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | | lib/lib.js:634:22:634:30 | sanitized | | lib/lib.js:634:22:634:30 | sanitized | -| lib/lib.js:639:6:639:84 | sanitized | -| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | -| lib/lib.js:639:24:639:27 | name | -| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | -| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | -| lib/lib.js:640:22:640:30 | sanitized | -| lib/lib.js:640:22:640:30 | sanitized | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -767,20 +760,12 @@ edges | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | | lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:27 | name | | lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:27 | name | -| lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:27 | name | -| lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:27 | name | | lib/lib.js:633:6:633:68 | sanitized | lib/lib.js:634:22:634:30 | sanitized | | lib/lib.js:633:6:633:68 | sanitized | lib/lib.js:634:22:634:30 | sanitized | | lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | lib/lib.js:633:6:633:68 | sanitized | | lib/lib.js:633:24:633:27 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | | lib/lib.js:633:24:633:27 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | -| lib/lib.js:639:6:639:84 | sanitized | lib/lib.js:640:22:640:30 | sanitized | -| lib/lib.js:639:6:639:84 | sanitized | lib/lib.js:640:22:640:30 | sanitized | -| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | lib/lib.js:639:6:639:84 | sanitized | -| lib/lib.js:639:24:639:27 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | -| lib/lib.js:639:24:639:27 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | -| lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | @@ -913,8 +898,6 @@ edges | lib/lib.js:629:13:629:28 | "rm -rf " + name | lib/lib.js:608:42:608:45 | name | lib/lib.js:629:25:629:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:608:42:608:45 | name | library input | lib/lib.js:629:5:629:29 | cp.exec ... + name) | shell command | | lib/lib.js:633:18:633:68 | "'" + n ... ) + "'" | lib/lib.js:632:38:632:41 | name | lib/lib.js:633:24:633:62 | name.re ... '\\\\''") | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:634:2:634:31 | cp.exec ... itized) | shell command | | lib/lib.js:634:10:634:30 | "rm -rf ... nitized | lib/lib.js:632:38:632:41 | name | lib/lib.js:634:22:634:30 | sanitized | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:634:2:634:31 | cp.exec ... itized) | shell command | -| lib/lib.js:639:18:639:84 | "'" + n ... ) + "'" | lib/lib.js:632:38:632:41 | name | lib/lib.js:639:24:639:78 | name.re ... '\\\\''") | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:640:2:640:31 | cp.exec ... itized) | shell command | -| lib/lib.js:640:10:640:30 | "rm -rf ... nitized | lib/lib.js:632:38:632:41 | name | lib/lib.js:640:22:640:30 | sanitized | This string concatenation which depends on $@ is later used in a $@. | lib/lib.js:632:38:632:41 | name | library input | lib/lib.js:640:2:640:31 | cp.exec ... itized) | shell command | | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command | | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | This string concatenation which depends on $@ is later used in a $@. | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4:26 | cp.exec ... + name) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js index d3190ceb646..09488f0a887 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction/lib/lib.js @@ -637,5 +637,5 @@ module.exports.sanitizer = function (name) { cp.exec("rm -rf " + sanitized); // OK var sanitized = "'" + name.replace(new RegExp("\'", unknownFlags()), "'\\''") + "'" - cp.exec("rm -rf " + sanitized); // OK -- Currently this is flagged as a bad sanitization, but it is not certain that it is bad. + cp.exec("rm -rf " + sanitized); // OK -- Most likely should be okay and not flagged to reduce false positives. } From aa557cf950fa1204208b7673d2069e19fb859e72 Mon Sep 17 00:00:00 2001 From: Napalys Date: Wed, 27 Nov 2024 08:29:02 +0100 Subject: [PATCH 23/56] JS: Added tests for DotRemovingReplaceCall with RegExp Object. --- .../CWE-022/TaintedPath/Consistency.expected | 1 + .../CWE-022/TaintedPath/TaintedPath.expected | 119 ++++++++++++++++++ .../CWE-022/TaintedPath/TaintedPath.js | 13 ++ 3 files changed, 133 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected index e69de29bb2d..8396f55ff16 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected @@ -0,0 +1 @@ +| TaintedPath.js:213 | expected an alert, but found none | NOT OK (can be absolute) | | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index 5fa027c40da..c196425a5ca 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1619,6 +1619,60 @@ nodes | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | @@ -6910,6 +6964,70 @@ edges | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | +| TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | | examples/TaintedPath.js:8:7:8:52 | filePath | examples/TaintedPath.js:11:36:11:43 | filePath | @@ -10730,6 +10848,7 @@ edges | TaintedPath.js:197:45:197:48 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:197:45:197:48 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:198:35:198:38 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:198:35:198:38 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:206:29:206:85 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | +| TaintedPath.js:216:31:216:69 | path.re ... '), '') | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:216:31:216:69 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:211:24:211:30 | req.url | user-provided value | | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | examples/TaintedPath.js:8:28:8:34 | req.url | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | This path depends on a $@. | examples/TaintedPath.js:8:28:8:34 | req.url | user-provided value | | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on a $@. | express.js:8:20:8:32 | req.query.bar | user-provided value | | handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on a $@. | handlebars.js:29:46:29:60 | req.params.path | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js index 13948fc431a..924aec029e9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js @@ -206,3 +206,16 @@ var server = http.createServer(function(req, res) { res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", ''), ''))); // NOT OK. res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", unknownFlags()), ''))); // OK -- Might be okay depending on what unknownFlags evaluates to. }); + +var server = http.createServer(function(req, res) { + let path = url.parse(req.url, true).query.path; + + res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // NOT OK (can be absolute) -- Currently not flagged because it is not a literal + + if (!pathModule.isAbsolute(path)) { + res.write(fs.readFileSync(path.replace(new RegExp("[.]", ''), ''))); // NOT OK + res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // OK + res.write(fs.readFileSync(path.replace(new RegExp("[.]", unknownFlags()), ''))); // OK + } +}); + From 875478c1c6c9a01587f35f2777648d8bef55baf4 Mon Sep 17 00:00:00 2001 From: Napalys Date: Wed, 27 Nov 2024 08:55:21 +0100 Subject: [PATCH 24/56] JS: Fixed path query not flagging new RegExp with DotRemovingReplaceCall --- .../dataflow/TaintedPathCustomizations.qll | 6 +- .../CWE-022/TaintedPath/Consistency.expected | 1 - .../CWE-022/TaintedPath/TaintedPath.expected | 110 ++++++++++++++++++ .../CWE-022/TaintedPath/TaintedPath.js | 2 +- 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index f2dd4a95cf0..8798c926086 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -305,9 +305,9 @@ module TaintedPath { input = this.getReceiver() and output = this and this.isGlobal() and - exists(RegExpLiteral literal, RegExpTerm term | - this.getRegExp().asExpr() = literal and - literal.getRoot() = term and + exists(DataFlow::RegExpCreationNode regexp, RegExpTerm term | + this.getRegExp() = regexp and + regexp.getRoot() = term and not term.getAMatchedString() = "/" | term.getAMatchedString() = "." or diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected index 8396f55ff16..e69de29bb2d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/Consistency.expected @@ -1 +0,0 @@ -| TaintedPath.js:213 | expected an alert, but found none | NOT OK (can be absolute) | | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index c196425a5ca..6a45147a4e2 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1627,6 +1627,22 @@ nodes | TaintedPath.js:211:7:211:48 | path | | TaintedPath.js:211:7:211:48 | path | | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | | TaintedPath.js:211:14:211:37 | url.par ... , true) | | TaintedPath.js:211:14:211:37 | url.par ... , true) | | TaintedPath.js:211:14:211:37 | url.par ... , true) | @@ -1643,6 +1659,22 @@ nodes | TaintedPath.js:211:14:211:43 | url.par ... ).query | | TaintedPath.js:211:14:211:43 | url.par ... ).query | | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | @@ -1656,6 +1688,19 @@ nodes | TaintedPath.js:211:24:211:30 | req.url | | TaintedPath.js:211:24:211:30 | req.url | | TaintedPath.js:211:24:211:30 | req.url | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | | TaintedPath.js:216:31:216:34 | path | | TaintedPath.js:216:31:216:34 | path | | TaintedPath.js:216:31:216:34 | path | @@ -6964,6 +7009,14 @@ edges | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | | TaintedPath.js:206:29:206:32 | path | TaintedPath.js:206:29:206:85 | path.re ... '), '') | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | +| TaintedPath.js:211:7:211:48 | path | TaintedPath.js:213:29:213:32 | path | | TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | | TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | | TaintedPath.js:211:7:211:48 | path | TaintedPath.js:216:31:216:34 | path | @@ -6980,6 +7033,14 @@ edges | TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | | TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | | TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | +| TaintedPath.js:211:14:211:37 | url.par ... , true) | TaintedPath.js:211:14:211:43 | url.par ... ).query | | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | @@ -6988,6 +7049,22 @@ edges | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | | TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:43 | url.par ... ).query | TaintedPath.js:211:14:211:48 | url.par ... ry.path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | +| TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | | TaintedPath.js:211:14:211:48 | url.par ... ry.path | TaintedPath.js:211:7:211:48 | path | @@ -7012,6 +7089,38 @@ edges | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:211:14:211:37 | url.par ... , true) | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | +| TaintedPath.js:213:29:213:32 | path | TaintedPath.js:213:29:213:68 | path.re ... '), '') | | TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | | TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | | TaintedPath.js:216:31:216:34 | path | TaintedPath.js:216:31:216:69 | path.re ... '), '') | @@ -10848,6 +10957,7 @@ edges | TaintedPath.js:197:45:197:48 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:197:45:197:48 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:198:35:198:38 | path | TaintedPath.js:195:24:195:30 | req.url | TaintedPath.js:198:35:198:38 | path | This path depends on a $@. | TaintedPath.js:195:24:195:30 | req.url | user-provided value | | TaintedPath.js:206:29:206:85 | path.re ... '), '') | TaintedPath.js:202:24:202:30 | req.url | TaintedPath.js:206:29:206:85 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:202:24:202:30 | req.url | user-provided value | +| TaintedPath.js:213:29:213:68 | path.re ... '), '') | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:213:29:213:68 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:211:24:211:30 | req.url | user-provided value | | TaintedPath.js:216:31:216:69 | path.re ... '), '') | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:216:31:216:69 | path.re ... '), '') | This path depends on a $@. | TaintedPath.js:211:24:211:30 | req.url | user-provided value | | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | examples/TaintedPath.js:8:28:8:34 | req.url | examples/TaintedPath.js:11:29:11:43 | ROOT + filePath | This path depends on a $@. | examples/TaintedPath.js:8:28:8:34 | req.url | user-provided value | | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on a $@. | express.js:8:20:8:32 | req.query.bar | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js index 924aec029e9..fd768fecfff 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js @@ -210,7 +210,7 @@ var server = http.createServer(function(req, res) { var server = http.createServer(function(req, res) { let path = url.parse(req.url, true).query.path; - res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // NOT OK (can be absolute) -- Currently not flagged because it is not a literal + res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // NOT OK (can be absolute) if (!pathModule.isAbsolute(path)) { res.write(fs.readFileSync(path.replace(new RegExp("[.]", ''), ''))); // NOT OK From 9c2366a660654de149b26ec03a3b1cd5cd474abe Mon Sep 17 00:00:00 2001 From: Napalys Date: Wed, 27 Nov 2024 09:42:43 +0100 Subject: [PATCH 25/56] JS: Added tests for ReDos with unknownFlags, everything seems to be good --- .../CWE-400/ReDoS/PolynomialBackTracking.expected | 3 +++ .../CWE-400/ReDoS/PolynomialReDoS.expected | 15 +++++++++++++++ .../Security/CWE-400/ReDoS/polynomial-redos.js | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected index 9a03bdcd34e..106b143111f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected @@ -130,6 +130,9 @@ | polynomial-redos.js:133:22:133:23 | f+ | Strings starting with 'f' and with many repetitions of 'f' can start matching anywhere after the start of the preceeding ff+G | | polynomial-redos.js:136:25:136:26 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I | | polynomial-redos.js:138:322:138:323 | .* | Strings starting with 'AAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' can start matching anywhere after the start of the preceeding (AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)C.*X | +| polynomial-redos.js:140:33:140:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I | +| polynomial-redos.js:141:33:141:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I | +| polynomial-redos.js:142:33:142:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I | | regexplib/address.js:27:3:27:5 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:27:48:27:50 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:27:93:27:95 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected index 4c534fffe13..f9504944160 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected @@ -249,6 +249,12 @@ nodes | polynomial-redos.js:136:5:136:13 | modified3 | | polynomial-redos.js:138:5:138:11 | tainted | | polynomial-redos.js:138:5:138:11 | tainted | +| polynomial-redos.js:140:2:140:10 | modified3 | +| polynomial-redos.js:140:2:140:10 | modified3 | +| polynomial-redos.js:141:2:141:10 | modified3 | +| polynomial-redos.js:141:2:141:10 | modified3 | +| polynomial-redos.js:142:2:142:10 | modified3 | +| polynomial-redos.js:142:2:142:10 | modified3 | edges | lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | | lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | @@ -489,6 +495,12 @@ edges | polynomial-redos.js:132:18:132:50 | tainted ... g, "e") | polynomial-redos.js:132:6:132:50 | modified2 | | polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:136:5:136:13 | modified3 | | polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:136:5:136:13 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:140:2:140:10 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:140:2:140:10 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:141:2:141:10 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:141:2:141:10 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:142:2:142:10 | modified3 | +| polynomial-redos.js:135:9:135:47 | modified3 | polynomial-redos.js:142:2:142:10 | modified3 | | polynomial-redos.js:135:21:135:27 | tainted | polynomial-redos.js:135:21:135:47 | tainted ... /g, "") | | polynomial-redos.js:135:21:135:47 | tainted ... /g, "") | polynomial-redos.js:135:9:135:47 | modified3 | #select @@ -590,3 +602,6 @@ edges | polynomial-redos.js:133:2:133:32 | modifie ... g, "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:133:2:133:10 | modified2 | This $@ that depends on $@ may run slow on strings starting with 'f' and with many repetitions of 'f'. | polynomial-redos.js:133:22:133:23 | f+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:136:5:136:35 | modifie ... g, "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:136:5:136:13 | modified3 | This $@ that depends on $@ may run slow on strings starting with 'h' and with many repetitions of 'h'. | polynomial-redos.js:136:25:136:26 | h+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:138:5:138:326 | tainted ... )C.*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:138:5:138:11 | tainted | This $@ that depends on $@ may run slow on strings starting with 'AAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC'. | polynomial-redos.js:138:322:138:323 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:140:2:140:48 | modifie ... ), "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:140:2:140:10 | modified3 | This $@ that depends on $@ may run slow on strings starting with 'h' and with many repetitions of 'h'. | polynomial-redos.js:140:33:140:34 | h+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:141:2:141:59 | modifie ... ), "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:141:2:141:10 | modified3 | This $@ that depends on $@ may run slow on strings starting with 'h' and with many repetitions of 'h'. | polynomial-redos.js:141:33:141:34 | h+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:142:2:142:47 | modifie ... ), "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:142:2:142:10 | modified3 | This $@ that depends on $@ may run slow on strings starting with 'h' and with many repetitions of 'h'. | polynomial-redos.js:142:33:142:34 | h+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js index fc0ddde66b2..860472428ff 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js @@ -136,4 +136,8 @@ app.use(function(req, res) { modified3.replace(/hh+I/g, "b"); // NOT OK tainted.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*X/); // NOT OK + + modified3.replace(new RegExp("hh+I", "g"), "b"); // NOT OK + modified3.replace(new RegExp("hh+I", unknownFlags()), "b"); // NOT OK + modified3.replace(new RegExp("hh+I", ""), "b"); // NOT OK }); From 76318035ffd61035f5a448f2d73aae5985645ca4 Mon Sep 17 00:00:00 2001 From: Napalys Date: Wed, 27 Nov 2024 10:53:43 +0100 Subject: [PATCH 26/56] JS: Add test cases for RegExp object usage in replace within incomplete sanitization --- ...ompleteMultiCharacterSanitization.expected | 1 + .../CWE-116/IncompleteSanitization/tst.js | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected index 32400608814..96a48fec6cb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/IncompleteSanitization/IncompleteMultiCharacterSanitization.expected @@ -39,3 +39,4 @@ | tst-multi-character-sanitization.js:145:13:145:90 | content ... /g, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:145:30:145:30 | < |