Skip to content

Commit 8c3e778

Browse files
committed
Java: Port regex mode flag character fix from Python.
1 parent 657642a commit 8c3e778

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

java/ql/lib/semmle/code/java/regex/regex.qll

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -473,27 +473,46 @@ abstract class RegexString extends StringLiteral {
473473
}
474474

475475
/**
476-
* Holds if a parse mode starts between `start` and `end`.
476+
* Holds if the initial part of a parse mode, not containing any
477+
* mode characters is between `start` and `end`.
477478
*/
478-
private predicate flagGroupStart(int start, int end) {
479+
private predicate flagGroupStartNoModes(int start, int end) {
479480
this.isGroupStart(start) and
480481
this.getChar(start + 1) = "?" and
481482
this.getChar(start + 2) in ["i", "m", "s", "u", "x", "U"] and
482483
end = start + 2
483484
}
484485

485486
/**
486-
* Holds if a parse mode group is between `start` and `end`, and includes the
487-
* mode flag `c`. For example the following span, with mode flag `i`:
487+
* Holds if `pos` contains a mode character from the
488+
* flag group starting at `start`.
489+
*/
490+
private predicate modeCharacter(int start, int pos) {
491+
this.flagGroupStartNoModes(start, pos)
492+
or
493+
this.modeCharacter(start, pos - 1) and
494+
this.getChar(pos) in ["i", "m", "s", "u", "x", "U"]
495+
}
496+
497+
/**
498+
* Holds if a parse mode group is between `start` and `end`.
499+
*/
500+
private predicate flagGroupStart(int start, int end) {
501+
this.flagGroupStartNoModes(start, _) and
502+
end = max(int i | this.modeCharacter(start, i) | i + 1)
503+
}
504+
505+
/**
506+
* Holds if a parse mode group of this regex includes the mode flag `c`.
507+
* For example the following parse mode group, with mode flag `i`:
488508
* ```
489509
* (?i)
490510
* ```
491511
*/
492-
private predicate flagGroup(int start, int end, string c) {
493-
exists(int inStart, int inEnd |
494-
this.flagGroupStart(start, inStart) and
495-
this.groupContents(start, end, inStart, inEnd) and
496-
this.getChar([inStart .. inEnd - 1]) = c
512+
private predicate flag(string c) {
513+
exists(int pos |
514+
this.modeCharacter(_, pos) and
515+
this.getChar(pos) = c
497516
)
498517
}
499518

@@ -502,7 +521,7 @@ abstract class RegexString extends StringLiteral {
502521
* it is defined by a prefix.
503522
*/
504523
string getModeFromPrefix() {
505-
exists(string c | this.flagGroup(_, _, c) |
524+
exists(string c | this.flag(c) |
506525
c = "i" and result = "IGNORECASE"
507526
or
508527
c = "m" and result = "MULTILINE"

java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ class ExpRedosTest {
434434
"((aa|a*+)b)*c", // $ MISSING: hasExpRedos
435435

436436
// BAD - testsing
437-
"(?is)(a|aa?)*b" // $ hasExpRedos hasPrefixMsg="starting with 'is' and " hasPump=a
437+
"(?is)(a|aa?)*b" // $ hasExpRedos hasPrefixMsg= hasPump=a
438438
};
439439

440440
void test() {

0 commit comments

Comments
 (0)