Skip to content

Commit 7fa41c4

Browse files
authored
Merge pull request #18794 from erik-krogh/v-flag
JS: Add support for the regex V flag
2 parents a90bd68 + 6ebffd5 commit 7fa41c4

File tree

8 files changed

+20
-3
lines changed

8 files changed

+20
-3
lines changed

javascript/extractor/src/com/semmle/jcorn/Parser.java

+1
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ private Token readRegexp() {
788788
String validFlags = "gim";
789789
if (this.options.ecmaVersion() >= 6) validFlags = "gimuy";
790790
if (this.options.ecmaVersion() >= 9) validFlags = "gimsuy";
791+
if (this.options.ecmaVersion() >= 15) validFlags = "gimsuyv";
791792
if (!mods.matches("^[" + validFlags + "]*$"))
792793
this.raise(start, "Invalid regular expression flag");
793794
if (mods.indexOf('u') >= 0) {

javascript/extractor/src/com/semmle/js/extractor/ExtractorConfig.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ public static enum ECMAVersion {
4141
ECMA2017(2017, 8),
4242
ECMA2018(2018, 9),
4343
ECMA2019(2019, 10),
44-
ECMA2020(2020, 11);
44+
ECMA2020(2020, 11),
45+
ECMA2024(2024, 15);
4546

4647
private final int version;
4748
public final int legacyVersion;
@@ -232,7 +233,7 @@ public Set<String> getPredefinedGlobals() {
232233
private VirtualSourceRoot virtualSourceRoot;
233234

234235
public ExtractorConfig(boolean experimental) {
235-
this.ecmaVersion = experimental ? ECMAVersion.ECMA2020 : ECMAVersion.ECMA2019;
236+
this.ecmaVersion = experimental ? ECMAVersion.ECMA2024 : ECMAVersion.ECMA2019;
236237
this.platform = Platform.AUTO;
237238
this.jsx = true;
238239
this.sourceType = SourceType.AUTO;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added support for regular expressions using the `v` flag.

javascript/ql/lib/semmle/javascript/Expr.qll

+3
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent {
481481
/** Holds if this regular expression has an `s` flag. */
482482
predicate isDotAll() { RegExp::isDotAll(this.getFlags()) }
483483

484+
/** Holds if this regular expression has an `v` flag. */
485+
predicate isUnicodeSets() { RegExp::isUnicodeSets(this.getFlags()) }
486+
484487
override string getAPrimaryQlClass() { result = "RegExpLiteral" }
485488
}
486489

javascript/ql/lib/semmle/javascript/Regexp.qll

+4
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,10 @@ module RegExp {
11621162
bindingset[flags]
11631163
predicate isDotAll(string flags) { flags.matches("%s%") }
11641164

1165+
/** Holds if `flags` includes the `v` flag. */
1166+
bindingset[flags]
1167+
predicate isUnicodeSets(string flags) { flags.matches("%v%") }
1168+
11651169
/** Holds if `flags` includes the `m` flag or is the unknown flag `?`. */
11661170
bindingset[flags]
11671171
predicate maybeMultiline(string flags) { flags = unknownFlag() or isMultiline(flags) }

javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected

+1
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,4 @@
538538
| tst.js:407:128:407:129 | * | Strings starting with '0/*' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* |
539539
| tst.js:409:23:409:29 | [\\w.-]* | Strings starting with '//' and with many repetitions of '//' can start matching anywhere after the start of the preceeding (\\/(?:\\/[\\w.-]*)*){0,1}:([\\w.-]+) |
540540
| tst.js:411:15:411:19 | a{1,} | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding (a{1,})* |
541+
| tst.js:417:20:417:25 | (aa?)* | Strings with many repetitions of 'aa' can start matching anywhere after the start of the preceeding (aa?)*b |

javascript/ql/test/query-tests/Security/CWE-400/ReDoS/ReDoS.expected

+1
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,4 @@
201201
| tst.js:411:15:411:19 | a{1,} | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
202202
| tst.js:413:25:413:35 | (\\u0000\|.)+ | This part of the regular expression may cause exponential backtracking on strings starting with '\\n\\u0000' and containing many repetitions of '\\u0000'. |
203203
| tst.js:415:44:415:57 | (\ud83d\ude80\|.)+ | This part of the regular expression may cause exponential backtracking on strings starting with '\\n\\u{1f680}' and containing many repetitions of '\\u{1f680}'. |
204+
| tst.js:417:22:417:23 | a? | This part of the regular expression may cause exponential backtracking on strings starting with 'a' and containing many repetitions of 'aa'. |

javascript/ql/test/query-tests/Security/CWE-400/ReDoS/tst.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -412,4 +412,6 @@ var bad99 = /(a{1,})*b/;
412412

413413
var unicode = /^\n\u0000(\u0000|.)+$/;
414414

415-
var largeUnicode = new RegExp("^\n\u{1F680}(\u{1F680}|.)+X$");
415+
var largeUnicode = new RegExp("^\n\u{1F680}(\u{1F680}|.)+X$");
416+
417+
var unicodeSets = /(aa?)*b/v;

0 commit comments

Comments
 (0)