diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 70f27ccb12d..e264a78f230 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -148,7 +148,11 @@ private string getASrcFolderName() { result = ["ts", "js", "src", "lib"] } class MainModulePath extends PathExpr, @json_string { PackageJson pkg; - MainModulePath() { this = pkg.getPropValue(["main", "module"]) } + MainModulePath() { + this = pkg.getPropValue(["main", "module"]) + or + this = getAJsonChild*(pkg.getPropValue("exports")) + } /** Gets the `package.json` file in which this path occurs. */ PackageJson getPackageJson() { result = pkg } @@ -164,6 +168,9 @@ class MainModulePath extends PathExpr, @json_string { } } +/** Gets the value of a property from the JSON object `obj`. */ +private JsonValue getAJsonChild(JsonObject obj) { result = obj.getPropValue(_) } + module MainModulePath { MainModulePath of(PackageJson pkg) { result.getPackageJson() = pkg } } diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected index 96919f8717d..7df8bece899 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialBackTracking.expected @@ -38,6 +38,8 @@ | lib/snapdragon.js:15:26:15:27 | a* | Strings starting with 'a' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding aa*$ | | lib/snapdragon.js:23:22:23:23 | a* | Strings starting with 'a' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding aa*$ | | lib/subLib4/factory.js:8:3:8:4 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g | +| lib/subLib5/feature.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | +| lib/subLib5/main.js:2:3:2:4 | a* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding a*b | | lib/sublib/factory.js:13:14:13:15 | f* | Strings with many repetitions of 'f' can start matching anywhere after the start of the preceeding f*g | | polynomial-redos.js:7:24:7:26 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:8:17:8:18 | * | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding *, * | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected index dccfcc03ed3..d03213a37d0 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Performance/ReDoS/PolynomialReDoS.expected @@ -51,6 +51,14 @@ nodes | lib/subLib4/factory.js:7:27:7:30 | name | | lib/subLib4/factory.js:8:13:8:16 | name | | lib/subLib4/factory.js:8:13:8:16 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | +| lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/main.js:1:28:1:31 | name | +| lib/subLib5/main.js:1:28:1:31 | name | +| lib/subLib5/main.js:2:13:2:16 | name | +| lib/subLib5/main.js:2:13:2:16 | name | | lib/sublib/factory.js:12:26:12:29 | name | | lib/sublib/factory.js:12:26:12:29 | name | | lib/sublib/factory.js:13:24:13:27 | name | @@ -256,6 +264,14 @@ edges | lib/subLib4/factory.js:7:27:7:30 | name | lib/subLib4/factory.js:8:13:8:16 | name | | lib/subLib4/factory.js:7:27:7:30 | name | lib/subLib4/factory.js:8:13:8:16 | name | | lib/subLib4/factory.js:7:27:7:30 | name | lib/subLib4/factory.js:8:13:8:16 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/feature.js:1:28:1:31 | name | lib/subLib5/feature.js:2:13:2:16 | name | +| lib/subLib5/main.js:1:28:1:31 | name | lib/subLib5/main.js:2:13:2:16 | name | +| lib/subLib5/main.js:1:28:1:31 | name | lib/subLib5/main.js:2:13:2:16 | name | +| lib/subLib5/main.js:1:28:1:31 | name | lib/subLib5/main.js:2:13:2:16 | name | +| lib/subLib5/main.js:1:28:1:31 | name | lib/subLib5/main.js:2:13:2:16 | name | | lib/sublib/factory.js:12:26:12:29 | name | lib/sublib/factory.js:13:24:13:27 | name | | lib/sublib/factory.js:12:26:12:29 | name | lib/sublib/factory.js:13:24:13:27 | name | | lib/sublib/factory.js:12:26:12:29 | name | lib/sublib/factory.js:13:24:13:27 | name | @@ -418,6 +434,8 @@ edges | lib/snapdragon.js:15:13:15:30 | this.match(/aa*$/) | lib/snapdragon.js:12:34:12:38 | input | lib/snapdragon.js:15:13:15:16 | this | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | lib/snapdragon.js:15:26:15:27 | a* | regular expression | lib/snapdragon.js:12:34:12:38 | input | library input | | lib/snapdragon.js:23:5:23:26 | node.va ... /aa*$/) | lib/snapdragon.js:20:34:20:38 | input | lib/snapdragon.js:23:5:23:12 | node.val | This $@ that depends on $@ may run slow on strings starting with 'a' and with many repetitions of 'a'. | lib/snapdragon.js:23:22:23:23 | a* | regular expression | lib/snapdragon.js:20:34:20:38 | input | library input | | lib/subLib4/factory.js:8:2:8:17 | /f*g/.test(name) | lib/subLib4/factory.js:7:27:7:30 | name | lib/subLib4/factory.js:8:13:8:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/subLib4/factory.js:8:3:8:4 | f* | regular expression | lib/subLib4/factory.js:7:27:7:30 | name | library input | +| lib/subLib5/feature.js:2:2:2:17 | /a*b/.test(name) | lib/subLib5/feature.js:1:28:1:31 | name | lib/subLib5/feature.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/subLib5/feature.js:2:3:2:4 | a* | regular expression | lib/subLib5/feature.js:1:28:1:31 | name | library input | +| lib/subLib5/main.js:2:2:2:17 | /a*b/.test(name) | lib/subLib5/main.js:1:28:1:31 | name | lib/subLib5/main.js:2:13:2:16 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'a'. | lib/subLib5/main.js:2:3:2:4 | a* | regular expression | lib/subLib5/main.js:1:28:1:31 | name | library input | | lib/sublib/factory.js:13:13:13:28 | /f*g/.test(name) | lib/sublib/factory.js:12:26:12:29 | name | lib/sublib/factory.js:13:24:13:27 | name | This $@ that depends on $@ may run slow on strings with many repetitions of 'f'. | lib/sublib/factory.js:13:14:13:15 | f* | regular expression | lib/sublib/factory.js:12:26:12:29 | name | library input | | polynomial-redos.js:7:2:7:34 | tainted ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:7:2:7:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:7:24:7:26 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:8:2:8:23 | tainted ... *, */) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:8:2:8:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | polynomial-redos.js:8:17:8:18 | * | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/feature.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/feature.js new file mode 100644 index 00000000000..4326227e86b --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/feature.js @@ -0,0 +1,3 @@ +module.exports = function (name) { + /a*b/.test(name); // NOT OK +}; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/main.js b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/main.js new file mode 100644 index 00000000000..4326227e86b --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/main.js @@ -0,0 +1,3 @@ +module.exports = function (name) { + /a*b/.test(name); // NOT OK +}; diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/package.json b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/package.json new file mode 100644 index 00000000000..f10fc5e5788 --- /dev/null +++ b/javascript/ql/test/query-tests/Performance/ReDoS/lib/subLib5/package.json @@ -0,0 +1,11 @@ +{ + "name": "my-sub-lib", + "version": "0.0.7", + "main": "./main.js", + "exports": { + ".": "./main.js", + "./feature": { + "default": "./feature.js" + } + } +}