Skip to content

Commit 5e0f21a

Browse files
authored
Merge pull request github#2854 from max-schaefer/js/regexp-bounded-quantifier-fix
Approved by esbena
2 parents 9e3ed21 + 4346691 commit 5e0f21a

File tree

7 files changed

+45
-6
lines changed

7 files changed

+45
-6
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class Main {
3737
* A version identifier that should be updated every time the extractor changes in such a way that
3838
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
3939
*/
40-
public static final String EXTRACTOR_VERSION = "2020-02-05";
40+
public static final String EXTRACTOR_VERSION = "2020-02-14";
4141

4242
public static final Pattern NEWLINE = Pattern.compile("\n");
4343

javascript/extractor/src/com/semmle/js/parser/RegExpParser.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,19 @@ private RegExpTerm parseQuantifierOpt(SourceLocation loc, RegExpTerm atom) {
281281
if (this.match("+")) return this.finishTerm(new Plus(loc, atom, !this.match("?")));
282282
if (this.match("?")) return this.finishTerm(new Opt(loc, atom, !this.match("?")));
283283
if (this.match("{")) {
284-
Double lo = toNumber(this.readDigits(false)), hi = null;
285-
if (this.match(",") && !this.lookahead("}")) hi = toNumber(this.readDigits(false));
284+
Double lo = toNumber(this.readDigits(false)), hi;
285+
if (this.match(",")) {
286+
if (!this.lookahead("}")) {
287+
// atom{lo, hi}
288+
hi = toNumber(this.readDigits(false));
289+
} else {
290+
// atom{lo,}
291+
hi = null;
292+
}
293+
} else {
294+
// atom{lo}
295+
hi = lo;
296+
}
286297
this.expectRBrace();
287298
return this.finishTerm(new Range(loc, atom, !this.match("?"), lo, hi));
288299
}

javascript/extractor/tests/exprs/output/trap/regexp.js.trap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ locations_default(#20376,#10000,15,2,15,5)
10881088
hasLocation(#20375,#20376)
10891089
isGreedy(#20375)
10901090
rangeQuantifierLowerBound(#20375,1)
1091+
rangeQuantifierUpperBound(#20375,1)
10911092
#20377=*
10921093
regexpterm(#20377,14,#20375,0,"a")
10931094
#20378=@"loc,{#10000},15,2,15,2"
@@ -1157,6 +1158,7 @@ regexpterm(#20393,11,#20392,0,"a{1}?")
11571158
locations_default(#20394,#10000,18,2,18,6)
11581159
hasLocation(#20393,#20394)
11591160
rangeQuantifierLowerBound(#20393,1)
1161+
rangeQuantifierUpperBound(#20393,1)
11601162
#20395=*
11611163
regexpterm(#20395,14,#20393,0,"a")
11621164
#20396=@"loc,{#10000},18,2,18,2"
@@ -1670,6 +1672,7 @@ locations_default(#20543,#10000,37,2,37,3)
16701672
hasLocation(#20542,#20543)
16711673
isGreedy(#20542)
16721674
rangeQuantifierLowerBound(#20542,0)
1675+
rangeQuantifierUpperBound(#20542,0)
16731676
#20544=*
16741677
regexpterm(#20544,14,#20542,0,"a")
16751678
#20545=@"loc,{#10000},37,2,37,2"
@@ -1708,6 +1711,7 @@ locations_default(#20555,#10000,38,2,38,3)
17081711
hasLocation(#20554,#20555)
17091712
isGreedy(#20554)
17101713
rangeQuantifierLowerBound(#20554,0)
1714+
rangeQuantifierUpperBound(#20554,0)
17111715
#20556=*
17121716
regexpterm(#20556,14,#20554,0,"a")
17131717
#20557=@"loc,{#10000},38,2,38,2"
@@ -1754,6 +1758,7 @@ locations_default(#20569,#10000,39,2,39,4)
17541758
hasLocation(#20568,#20569)
17551759
isGreedy(#20568)
17561760
rangeQuantifierLowerBound(#20568,2)
1761+
rangeQuantifierUpperBound(#20568,2)
17571762
#20570=*
17581763
regexpterm(#20570,14,#20568,0,"a")
17591764
#20571=@"loc,{#10000},39,2,39,2"

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,17 +506,25 @@ class RegExpOpt extends RegExpQuantifier, @regexp_opt {
506506
/**
507507
* A range-quantified term
508508
*
509-
* Example:
509+
* Examples:
510510
*
511511
* ```
512512
* \w{2,4}
513+
* \w{2,}
514+
* \w{2}
513515
* ```
514516
*/
515517
class RegExpRange extends RegExpQuantifier, @regexp_range {
516-
/** Gets the lower bound of the range, if any. */
518+
/** Gets the lower bound of the range. */
517519
int getLowerBound() { rangeQuantifierLowerBound(this, result) }
518520

519-
/** Gets the upper bound of the range, if any. */
521+
/**
522+
* Gets the upper bound of the range, if any.
523+
*
524+
* If there is no upper bound, any number of repetitions is allowed.
525+
* For a term of the form `r{lo}`, both the lower and the upper bound
526+
* are `lo`.
527+
*/
520528
int getUpperBound() { rangeQuantifierUpperBound(this, result) }
521529

522530
override predicate isNullable() {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| tst.js:1:2:1:5 | a{1} | 1 | 1 |
2+
| tst.js:2:2:2:6 | a{1,} | 1 | <none> |
3+
| tst.js:3:2:3:7 | a{1,5} | 1 | 5 |
4+
| tst.js:4:2:4:6 | a{,5} | 0 | 5 |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import javascript
2+
3+
from RegExpRange rr, string lb, string ub
4+
where
5+
lb = rr.getLowerBound().toString() and
6+
if exists(rr.getUpperBound()) then ub = rr.getUpperBound().toString() else ub = "<none>"
7+
select rr, lb, ub
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/a{1}/;
2+
/a{1,}/;
3+
/a{1,5}/;
4+
/a{,5}/;

0 commit comments

Comments
 (0)