Skip to content

Commit 091c6c0

Browse files
authored
Merge pull request github#2856 from esbena/js/fix-RegExp-getPredecessor-getSuccessor
Approved by max-schaefer
2 parents 97035ae + e8938fb commit 091c6c0

File tree

6 files changed

+123
-14
lines changed

6 files changed

+123
-14
lines changed

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

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,25 +75,22 @@ class RegExpTerm extends Locatable, @regexpterm {
7575

7676
/** Gets the regular expression term that is matched (textually) before this one, if any. */
7777
RegExpTerm getPredecessor() {
78-
exists(RegExpSequence seq, int i |
79-
seq.getChild(i) = this and
80-
seq.getChild(i - 1) = result
78+
exists(RegExpTerm parent | parent = getParent() |
79+
result = parent.(RegExpSequence).previousElement(this)
80+
or
81+
not exists(parent.(RegExpSequence).previousElement(this)) and
82+
not parent instanceof RegExpSubPattern and
83+
result = parent.getPredecessor()
8184
)
82-
or
83-
result = getParent().(RegExpTerm).getPredecessor()
8485
}
8586

8687
/** Gets the regular expression term that is matched (textually) after this one, if any. */
8788
RegExpTerm getSuccessor() {
88-
exists(RegExpSequence seq, int i |
89-
seq.getChild(i) = this and
90-
seq.getChild(i + 1) = result
91-
)
92-
or
93-
exists(RegExpTerm parent |
94-
parent = getParent() and
95-
not parent instanceof RegExpSubPattern
96-
|
89+
exists(RegExpTerm parent | parent = getParent() |
90+
result = parent.(RegExpSequence).nextElement(this)
91+
or
92+
not exists(parent.(RegExpSequence).nextElement(this)) and
93+
not parent instanceof RegExpSubPattern and
9794
result = parent.getSuccessor()
9895
)
9996
}
@@ -313,6 +310,19 @@ class RegExpSequence extends RegExpTerm, @regexp_seq {
313310
or
314311
result = getChild(i).getConstantValue() + getConstantValue(i+1)
315312
}
313+
314+
/** Gets the element preceding `element` in this sequence. */
315+
RegExpTerm previousElement(RegExpTerm element) {
316+
element = nextElement(result)
317+
}
318+
319+
/** Gets the element following `element` in this sequence. */
320+
RegExpTerm nextElement(RegExpTerm element) {
321+
exists(int i |
322+
element = this.getChild(i) and
323+
result = this.getChild(i + 1)
324+
)
325+
}
316326
}
317327

318328
/**
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
| tst.js:2:2:2:2 | a | tst.js:2:3:2:5 | (b) |
2+
| tst.js:2:2:2:2 | a | tst.js:2:4:2:4 | b |
3+
| tst.js:3:2:3:3 | ab | tst.js:3:4:3:6 | (c) |
4+
| tst.js:3:2:3:3 | ab | tst.js:3:5:3:5 | c |
5+
| tst.js:4:2:4:2 | a | tst.js:4:3:4:6 | (bc) |
6+
| tst.js:4:2:4:2 | a | tst.js:4:4:4:5 | bc |
7+
| tst.js:5:2:5:2 | a | tst.js:5:3:5:8 | (b[c]) |
8+
| tst.js:5:2:5:2 | a | tst.js:5:4:5:4 | b |
9+
| tst.js:5:2:5:2 | a | tst.js:5:4:5:7 | b[c] |
10+
| tst.js:5:4:5:4 | b | tst.js:5:5:5:7 | [c] |
11+
| tst.js:5:4:5:4 | b | tst.js:5:6:5:6 | c |
12+
| tst.js:6:2:6:2 | a | tst.js:6:3:6:9 | (b\|[b]) |
13+
| tst.js:6:2:6:2 | a | tst.js:6:4:6:4 | b |
14+
| tst.js:6:2:6:2 | a | tst.js:6:4:6:8 | b\|[b] |
15+
| tst.js:6:2:6:2 | a | tst.js:6:6:6:8 | [b] |
16+
| tst.js:6:2:6:2 | a | tst.js:6:7:6:7 | b |
17+
| tst.js:7:2:7:2 | a | tst.js:7:3:7:10 | ([b][c]) |
18+
| tst.js:7:2:7:2 | a | tst.js:7:4:7:6 | [b] |
19+
| tst.js:7:2:7:2 | a | tst.js:7:4:7:9 | [b][c] |
20+
| tst.js:7:2:7:2 | a | tst.js:7:5:7:5 | b |
21+
| tst.js:7:4:7:6 | [b] | tst.js:7:7:7:9 | [c] |
22+
| tst.js:7:4:7:6 | [b] | tst.js:7:8:7:8 | c |
23+
| tst.js:8:2:8:2 | a | tst.js:8:3:8:13 | (b\|[b]\|[b]) |
24+
| tst.js:8:2:8:2 | a | tst.js:8:4:8:4 | b |
25+
| tst.js:8:2:8:2 | a | tst.js:8:4:8:12 | b\|[b]\|[b] |
26+
| tst.js:8:2:8:2 | a | tst.js:8:6:8:8 | [b] |
27+
| tst.js:8:2:8:2 | a | tst.js:8:7:8:7 | b |
28+
| tst.js:8:2:8:2 | a | tst.js:8:10:8:12 | [b] |
29+
| tst.js:8:2:8:2 | a | tst.js:8:11:8:11 | b |
30+
| tst.js:11:2:11:4 | (a) | tst.js:11:5:11:5 | b |
31+
| tst.js:12:2:12:4 | (a) | tst.js:12:5:12:6 | bc |
32+
| tst.js:13:2:13:5 | (ab) | tst.js:13:6:13:6 | c |
33+
| tst.js:14:2:14:7 | ([a]b) | tst.js:14:8:14:8 | c |
34+
| tst.js:14:3:14:5 | [a] | tst.js:14:6:14:6 | b |
35+
| tst.js:16:2:16:9 | ([a][b]) | tst.js:16:10:16:10 | c |
36+
| tst.js:16:3:16:5 | [a] | tst.js:16:6:16:8 | [b] |
37+
| tst.js:16:3:16:5 | [a] | tst.js:16:7:16:7 | b |
38+
| tst.js:17:2:17:12 | ([a]\|[a]\|a) | tst.js:17:13:17:13 | b |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import javascript
2+
3+
from RegExpTerm pred, RegExpTerm succ
4+
where pred = succ.getPredecessor()
5+
select pred, succ
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
| tst.js:2:2:2:2 | a | tst.js:2:3:2:5 | (b) |
2+
| tst.js:3:2:3:3 | ab | tst.js:3:4:3:6 | (c) |
3+
| tst.js:4:2:4:2 | a | tst.js:4:3:4:6 | (bc) |
4+
| tst.js:5:2:5:2 | a | tst.js:5:3:5:8 | (b[c]) |
5+
| tst.js:5:4:5:4 | b | tst.js:5:5:5:7 | [c] |
6+
| tst.js:6:2:6:2 | a | tst.js:6:3:6:9 | (b\|[b]) |
7+
| tst.js:7:2:7:2 | a | tst.js:7:3:7:10 | ([b][c]) |
8+
| tst.js:7:4:7:6 | [b] | tst.js:7:7:7:9 | [c] |
9+
| tst.js:7:5:7:5 | b | tst.js:7:7:7:9 | [c] |
10+
| tst.js:8:2:8:2 | a | tst.js:8:3:8:13 | (b\|[b]\|[b]) |
11+
| tst.js:11:2:11:4 | (a) | tst.js:11:5:11:5 | b |
12+
| tst.js:11:3:11:3 | a | tst.js:11:5:11:5 | b |
13+
| tst.js:12:2:12:4 | (a) | tst.js:12:5:12:6 | bc |
14+
| tst.js:12:3:12:3 | a | tst.js:12:5:12:6 | bc |
15+
| tst.js:13:2:13:5 | (ab) | tst.js:13:6:13:6 | c |
16+
| tst.js:13:3:13:4 | ab | tst.js:13:6:13:6 | c |
17+
| tst.js:14:2:14:7 | ([a]b) | tst.js:14:8:14:8 | c |
18+
| tst.js:14:3:14:5 | [a] | tst.js:14:6:14:6 | b |
19+
| tst.js:14:3:14:6 | [a]b | tst.js:14:8:14:8 | c |
20+
| tst.js:14:4:14:4 | a | tst.js:14:6:14:6 | b |
21+
| tst.js:14:6:14:6 | b | tst.js:14:8:14:8 | c |
22+
| tst.js:16:2:16:9 | ([a][b]) | tst.js:16:10:16:10 | c |
23+
| tst.js:16:3:16:5 | [a] | tst.js:16:6:16:8 | [b] |
24+
| tst.js:16:3:16:8 | [a][b] | tst.js:16:10:16:10 | c |
25+
| tst.js:16:4:16:4 | a | tst.js:16:6:16:8 | [b] |
26+
| tst.js:16:6:16:8 | [b] | tst.js:16:10:16:10 | c |
27+
| tst.js:16:7:16:7 | b | tst.js:16:10:16:10 | c |
28+
| tst.js:17:2:17:12 | ([a]\|[a]\|a) | tst.js:17:13:17:13 | b |
29+
| tst.js:17:3:17:5 | [a] | tst.js:17:13:17:13 | b |
30+
| tst.js:17:3:17:11 | [a]\|[a]\|a | tst.js:17:13:17:13 | b |
31+
| tst.js:17:4:17:4 | a | tst.js:17:13:17:13 | b |
32+
| tst.js:17:7:17:9 | [a] | tst.js:17:13:17:13 | b |
33+
| tst.js:17:8:17:8 | a | tst.js:17:13:17:13 | b |
34+
| tst.js:17:11:17:11 | a | tst.js:17:13:17:13 | b |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import javascript
2+
3+
from RegExpTerm pred, RegExpTerm succ
4+
where succ = pred.getSuccessor()
5+
select pred, succ
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/ab/;
2+
/a(b)/;
3+
/ab(c)/;
4+
/a(bc)/;
5+
/a(b[c])/;
6+
/a(b|[b])/;
7+
/a([b][c])/;
8+
/a(b|[b]|[b])/;
9+
10+
/ab/;
11+
/(a)b/;
12+
/(a)bc/;
13+
/(ab)c/;
14+
/([a]b)c/;
15+
/([a]|a)|b/;
16+
/([a][b])c/;
17+
/([a]|[a]|a)b/;

0 commit comments

Comments
 (0)