Skip to content

Commit 73e08eb

Browse files
authored
Merge pull request #2468 from max-schaefer/js/regexp-predecessor
Approved by asgerf
2 parents d22df24 + a788bf8 commit 73e08eb

File tree

5 files changed

+14
-12
lines changed

5 files changed

+14
-12
lines changed

change-notes/1.24/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@
2525

2626
## Changes to libraries
2727

28+
* The predicates `RegExpTerm.getSuccessor` and `RegExpTerm.getPredecessor` have been changed to reflect textual, not operational, matching order. This only makes a difference in lookbehind assertions, which are operationally matched backwards. Previously, `getSuccessor` would mimick this, so in an assertion `(?<=ab)` the term `b` would be considered the predecessor, not the successor, of `a`. Textually, however, `a` is still matched before `b`, and this is the order we now follow.

javascript/ql/src/semmle/javascript/Regexp.qll

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ class RegExpTerm extends Locatable, @regexpterm {
7373
/** Holds if this regular expression term can match the empty string. */
7474
predicate isNullable() { none() } // Overridden in subclasses.
7575

76-
/** Gets the regular expression term that is matched before this one, if any. */
76+
/** Gets the regular expression term that is matched (textually) before this one, if any. */
7777
RegExpTerm getPredecessor() {
7878
exists(RegExpSequence seq, int i |
7979
seq.getChild(i) = this and
80-
seq.getChild(i - getDirection()) = result
80+
seq.getChild(i - 1) = result
8181
)
8282
or
8383
result = getParent().(RegExpTerm).getPredecessor()
8484
}
8585

86-
/** Gets the regular expression term that is matched after this one, if any. */
86+
/** Gets the regular expression term that is matched (textually) after this one, if any. */
8787
RegExpTerm getSuccessor() {
8888
exists(RegExpSequence seq, int i |
8989
seq.getChild(i) = this and
90-
seq.getChild(i + getDirection()) = result
90+
seq.getChild(i + 1) = result
9191
)
9292
or
9393
exists(RegExpTerm parent |
@@ -98,12 +98,6 @@ class RegExpTerm extends Locatable, @regexpterm {
9898
)
9999
}
100100

101-
/**
102-
* Gets the matching direction of this term: `1` if it is in a forward-matching
103-
* context, `-1` if it is in a backward-matching context.
104-
*/
105-
private int getDirection() { if isInBackwardMatchingContext() then result = -1 else result = 1 }
106-
107101
/**
108102
* Holds if this regular term is in a forward-matching context, that is,
109103
* it has no enclosing lookbehind assertions.

javascript/ql/test/query-tests/RegExp/UnmatchableCaret/tst.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@
2626
/^(^y|^z)(u$|v$)$/;
2727

2828
// OK
29-
/x*^y/;
29+
/x*^y/;
30+
31+
// OK
32+
/(?<=(^|\/)(\.|\.\.))$/;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
| tst.js:2:10:2:10 | $ | This assertion can never match. |
22
| tst.js:11:3:11:3 | $ | This assertion can never match. |
33
| tst.js:20:3:20:3 | $ | This assertion can never match. |
4+
| tst.js:38:6:38:6 | $ | This assertion can never match. |

javascript/ql/test/query-tests/RegExp/UnmatchableDollar/tst.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,7 @@
3232
/x(?!y+$).*y.*/;
3333

3434
// OK
35-
/x(?=[yz]+$).*yz.*/;
35+
/x(?=[yz]+$).*yz.*/;
36+
37+
// NOT OK
38+
/(?<=$x)yz/;

0 commit comments

Comments
 (0)