Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 28649da

Browse files
Add parser tests; fix some parser issues.
[temporarily renamed existing regex/Test.java during rebasing to avoid conflict]
1 parent 8e19182 commit 28649da

5 files changed

Lines changed: 212 additions & 118 deletions

File tree

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

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ abstract class RegexString extends Expr {
2121
private predicate char_set_end0(int pos) {
2222
this.nonEscapedCharAt(pos) = "]" and
2323
/* special case: `[]]` and `[^]]` are valid char classes. */
24-
not this.char_set_start0(_, pos - 1)
24+
not this.char_set_start0(_, pos)
2525
}
2626

2727
/**
@@ -283,7 +283,7 @@ abstract class RegexString extends Expr {
283283
*/
284284
predicate escapedCharacter(int start, int end) {
285285
this.escapingChar(start) and
286-
not this.numbered_backreference(start, _, _) and
286+
not this.backreference(start, _) and
287287
(
288288
// hex value \xhh
289289
this.getChar(start + 1) = "x" and
@@ -362,7 +362,8 @@ abstract class RegexString extends Expr {
362362
predicate character(int start, int end) {
363363
(
364364
this.simpleCharacter(start, end) and
365-
not exists(int x, int y | this.escapedCharacter(x, y) and x <= start and y >= end)
365+
not exists(int x, int y | this.escapedCharacter(x, y) and x <= start and y >= end) and
366+
not exists(int x, int y | this.quote(x, y) and x <= start and y >= end)
366367
or
367368
this.escapedCharacter(start, end)
368369
) and
@@ -486,8 +487,6 @@ abstract class RegexString extends Expr {
486487
or
487488
this.named_group_start(start, end)
488489
or
489-
this.named_backreference_start(start, end)
490-
or
491490
this.lookahead_assertion_start(start, end)
492491
or
493492
this.negative_lookahead_assertion_start(start, end)
@@ -526,16 +525,6 @@ abstract class RegexString extends Expr {
526525
)
527526
}
528527

529-
private predicate named_backreference_start(int start, int end) {
530-
this.isGroupStart(start) and
531-
this.getChar(start + 1) = "?" and
532-
this.getChar(start + 2) = "k" and
533-
this.getChar(start + 3) = "=" and
534-
// Should this be looking for unescaped ")"?
535-
// TODO: test this
536-
end = min(int i | i > start + 4 and this.getChar(i) = "?")
537-
}
538-
539528
private predicate flag_group_start(int start, int end, string c) {
540529
this.isGroupStart(start) and
541530
this.getChar(start + 1) = "?" and
@@ -609,9 +598,11 @@ abstract class RegexString extends Expr {
609598
}
610599

611600
private predicate named_backreference(int start, int end, string name) {
612-
this.named_backreference_start(start, start + 4) and
613-
end = min(int i | i > start + 4 and this.getChar(i) = ")") + 1 and
614-
name = this.getText().substring(start + 4, end - 2)
601+
this.escapingChar(start) and
602+
this.getChar(start + 1) = "k" and
603+
this.getChar(start + 2) = "<" and
604+
end = min(int i | i > start + 2 and this.getChar(i) = ">") + 1 and
605+
name = this.getText().substring(start + 3, end - 2)
615606
}
616607

617608
private predicate numbered_backreference(int start, int end, int value) {
@@ -660,6 +651,8 @@ abstract class RegexString extends Expr {
660651
this.charSet(start, end)
661652
or
662653
this.backreference(start, end)
654+
or
655+
this.quote(start, end)
663656
}
664657

665658
private predicate qualifier(int start, int end, boolean maybe_empty, boolean may_repeat_forever) {
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
parseFailures
2+
#select
3+
| Test.java:5:10:5:16 | [A-Z\\d] | [RegExpCharacterClass] |
4+
| Test.java:5:10:5:18 | [A-Z\\d]++ | [RegExpPlus] |
5+
| Test.java:5:11:5:11 | A | [RegExpConstant,RegExpNormalChar] |
6+
| Test.java:5:11:5:13 | A-Z | [RegExpCharacterRange] |
7+
| Test.java:5:13:5:13 | Z | [RegExpConstant,RegExpNormalChar] |
8+
| Test.java:5:14:5:15 | \\d | [RegExpCharacterClassEscape] |
9+
| Test.java:6:10:6:39 | \\Q hello world [ *** \\Q ) ( \\E | [RegExpConstant,RegExpQuote] |
10+
| Test.java:7:10:7:21 | [\\Q hi ] \\E] | [RegExpCharacterClass] |
11+
| Test.java:7:11:7:20 | \\Q hi ] \\E | [RegExpConstant,RegExpQuote] |
12+
| Test.java:8:10:8:12 | []] | [RegExpCharacterClass] |
13+
| Test.java:8:11:8:11 | ] | [RegExpConstant,RegExpNormalChar] |
14+
| Test.java:9:10:9:13 | [^]] | [RegExpCharacterClass] |
15+
| Test.java:9:12:9:12 | ] | [RegExpConstant,RegExpNormalChar] |
16+
| Test.java:10:10:10:20 | [abc[defg]] | [RegExpCharacterClass] |
17+
| Test.java:10:11:10:11 | a | [RegExpConstant,RegExpNormalChar] |
18+
| Test.java:10:12:10:12 | b | [RegExpConstant,RegExpNormalChar] |
19+
| Test.java:10:13:10:13 | c | [RegExpConstant,RegExpNormalChar] |
20+
| Test.java:10:14:10:14 | [ | [RegExpConstant,RegExpNormalChar] |
21+
| Test.java:10:15:10:15 | d | [RegExpConstant,RegExpNormalChar] |
22+
| Test.java:10:16:10:16 | e | [RegExpConstant,RegExpNormalChar] |
23+
| Test.java:10:17:10:17 | f | [RegExpConstant,RegExpNormalChar] |
24+
| Test.java:10:18:10:18 | g | [RegExpConstant,RegExpNormalChar] |
25+
| Test.java:10:19:10:19 | ] | [RegExpConstant,RegExpNormalChar] |
26+
| Test.java:11:10:11:53 | [abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]] | [RegExpCharacterClass] |
27+
| Test.java:11:10:11:62 | [abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]]\\b7\\b{g}8 | [RegExpSequence] |
28+
| Test.java:11:11:11:11 | a | [RegExpConstant,RegExpNormalChar] |
29+
| Test.java:11:12:11:12 | b | [RegExpConstant,RegExpNormalChar] |
30+
| Test.java:11:13:11:13 | c | [RegExpConstant,RegExpNormalChar] |
31+
| Test.java:11:14:11:14 | & | [RegExpConstant,RegExpNormalChar] |
32+
| Test.java:11:15:11:15 | & | [RegExpConstant,RegExpNormalChar] |
33+
| Test.java:11:16:11:16 | [ | [RegExpConstant,RegExpNormalChar] |
34+
| Test.java:11:17:11:18 | \\W | [RegExpCharacterClassEscape] |
35+
| Test.java:11:19:11:27 | \\p{Lower} | [RegExpCharacterClassEscape] |
36+
| Test.java:11:28:11:36 | \\P{Space} | [RegExpCharacterClassEscape] |
37+
| Test.java:11:37:11:51 | \\N{degree sign} | [RegExpConstant,RegExpEscape] |
38+
| Test.java:11:52:11:52 | ] | [RegExpConstant,RegExpNormalChar] |
39+
| Test.java:11:54:11:55 | \\b | [RegExpConstant,RegExpEscape] |
40+
| Test.java:11:56:11:56 | 7 | [RegExpConstant,RegExpNormalChar] |
41+
| Test.java:11:57:11:61 | \\b{g} | [RegExpConstant,RegExpEscape] |
42+
| Test.java:11:62:11:62 | 8 | [RegExpConstant,RegExpNormalChar] |
43+
| Test.java:12:10:12:12 | \\cA | [RegExpConstant,RegExpEscape] |
44+
| Test.java:13:10:13:12 | \\c( | [RegExpConstant,RegExpEscape] |
45+
| Test.java:14:10:14:12 | \\c\\ | [RegExpConstant,RegExpEscape] |
46+
| Test.java:14:10:14:16 | \\c\\(ab) | [RegExpSequence] |
47+
| Test.java:14:13:14:16 | (ab) | [RegExpGroup] |
48+
| Test.java:14:14:14:14 | a | [RegExpConstant,RegExpNormalChar] |
49+
| Test.java:14:14:14:15 | ab | [RegExpSequence] |
50+
| Test.java:14:15:14:15 | b | [RegExpConstant,RegExpNormalChar] |
51+
| Test.java:15:10:15:15 | (?>hi) | [RegExpGroup] |
52+
| Test.java:15:10:15:44 | (?>hi)(?<name>hell*?o*+)123\\k<name> | [RegExpSequence] |
53+
| Test.java:15:13:15:13 | h | [RegExpConstant,RegExpNormalChar] |
54+
| Test.java:15:13:15:14 | hi | [RegExpSequence] |
55+
| Test.java:15:14:15:14 | i | [RegExpConstant,RegExpNormalChar] |
56+
| Test.java:15:16:15:33 | (?<name>hell*?o*+) | [RegExpGroup] |
57+
| Test.java:15:24:15:24 | h | [RegExpConstant,RegExpNormalChar] |
58+
| Test.java:15:24:15:32 | hell*?o*+ | [RegExpSequence] |
59+
| Test.java:15:25:15:25 | e | [RegExpConstant,RegExpNormalChar] |
60+
| Test.java:15:26:15:26 | l | [RegExpConstant,RegExpNormalChar] |
61+
| Test.java:15:27:15:27 | l | [RegExpConstant,RegExpNormalChar] |
62+
| Test.java:15:27:15:29 | l*? | [RegExpStar] |
63+
| Test.java:15:30:15:30 | o | [RegExpConstant,RegExpNormalChar] |
64+
| Test.java:15:30:15:32 | o*+ | [RegExpStar] |
65+
| Test.java:15:34:15:34 | 1 | [RegExpConstant,RegExpNormalChar] |
66+
| Test.java:15:35:15:35 | 2 | [RegExpConstant,RegExpNormalChar] |
67+
| Test.java:15:36:15:36 | 3 | [RegExpConstant,RegExpNormalChar] |
68+
| Test.java:15:37:15:44 | \\k<name> | [RegExpBackRef] |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import java
2+
import semmle.code.java.regex.RegexTreeView
3+
import semmle.code.java.regex.regex
4+
5+
string getQLClases(RegExpTerm t) { result = "[" + strictconcat(t.getPrimaryQLClass(), ",") + "]" }
6+
7+
query predicate parseFailures(Regex r, int i) { r.failedToParse(i) }
8+
9+
from RegExpTerm t
10+
select t, getQLClases(t)
Lines changed: 19 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,23 @@
1-
package generatedtest;
2-
3-
import java.util.regex.Matcher;
41
import java.util.regex.Pattern;
52

6-
// Test case generated by GenerateFlowTestCase.ql
7-
public class Test {
8-
9-
private final String str_pattern = "\\$\\{(.*)\\}";
10-
private final Pattern pattern = Pattern.compile(str_pattern);
11-
12-
Object source() { return null; }
13-
void sink(Object o) { }
14-
15-
public void test() throws Exception {
16-
17-
{
18-
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
19-
String out = null;
20-
String in = (String) source();
21-
Matcher m = pattern.matcher(in);
22-
out = m.group("foo");
23-
sink(out); // $ hasTaintFlow
24-
}
25-
{
26-
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
27-
String out = null;
28-
String in = (String) source();
29-
Matcher m = pattern.matcher(in);
30-
out = m.group();
31-
sink(out); // $ hasTaintFlow
32-
}
33-
{
34-
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
35-
String out = null;
36-
String in = (String) source();
37-
Matcher m = pattern.matcher(in);
38-
out = m.group(0);
39-
sink(out); // $ hasTaintFlow
40-
}
41-
{
42-
// "java.util.regex;Matcher;false;replaceAll;;;Argument[-1];ReturnValue;taint"
43-
String out = null;
44-
String in = (String) source();
45-
Matcher m = pattern.matcher(in);
46-
out = m.replaceAll("foo");
47-
sink(out); // $ hasTaintFlow
48-
}
49-
{
50-
// "java.util.regex;Matcher;false;replaceAll;;;Argument[0];ReturnValue;taint"
51-
String out = null;
52-
String in = (String) source();
53-
Matcher m = pattern.matcher("foo");
54-
out = m.replaceAll(in);
55-
sink(out); // $ hasTaintFlow
3+
class Test {
4+
static String[] regs = {
5+
"[A-Z\\d]++",
6+
"\\Q hello world [ *** \\Q ) ( \\E",
7+
"[\\Q hi ] \\E]",
8+
"[]]",
9+
"[^]]",
10+
"[abc[defg]]",
11+
"[abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]]\\b7\\b{g}8",
12+
"\\cA",
13+
"\\c(",
14+
"\\c\\(ab)",
15+
"(?>hi)(?<name>hell*?o*+)123\\k<name>"
16+
};
17+
18+
void test() {
19+
for (int i = 0; i < regs.length; i++) {
20+
Pattern.compile(regs[i]);
21+
}
5622
}
57-
{
58-
// "java.util.regex;Matcher;false;replaceFirst;;;Argument[-1];ReturnValue;taint"
59-
String out = null;
60-
String in = (String) source();
61-
Matcher m = pattern.matcher(in);
62-
out = m.replaceFirst("foo");
63-
sink(out); // $ hasTaintFlow
64-
}
65-
{
66-
// "java.util.regex;Matcher;false;replaceFirst;;;Argument[0];ReturnValue;taint"
67-
String out = null;
68-
String in = (String) source();
69-
Matcher m = pattern.matcher("foo");
70-
out = m.replaceFirst(in);
71-
sink(out); // $ hasTaintFlow
72-
}
73-
{
74-
// "java.util.regex;Pattern;false;matcher;;;Argument[0];ReturnValue;taint"
75-
Matcher out = null;
76-
CharSequence in = (CharSequence)source();
77-
out = pattern.matcher(in);
78-
sink(out); // $ hasTaintFlow
79-
}
80-
{
81-
// "java.util.regex;Pattern;false;quote;;;Argument[0];ReturnValue;taint"
82-
String out = null;
83-
String in = (String)source();
84-
out = Pattern.quote(in);
85-
sink(out); // $ hasTaintFlow
86-
}
87-
{
88-
// "java.util.regex;Pattern;false;split;;;Argument[0];ReturnValue;taint"
89-
String[] out = null;
90-
CharSequence in = (CharSequence)source();
91-
out = pattern.split(in);
92-
sink(out); // $ hasTaintFlow
93-
}
94-
{
95-
// "java.util.regex;Pattern;false;split;;;Argument[0];ReturnValue;taint"
96-
String[] out = null;
97-
CharSequence in = (CharSequence)source();
98-
out = pattern.split(in, 0);
99-
sink(out); // $ hasTaintFlow
100-
}
101-
102-
}
103-
10423
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package generatedtest;
2+
3+
import java.util.regex.Matcher;
4+
import java.util.regex.Pattern;
5+
6+
// Test case generated by GenerateFlowTestCase.ql
7+
public class Test {
8+
9+
private final String str_pattern = "\\$\\{(.*)\\}";
10+
private final Pattern pattern = Pattern.compile(str_pattern);
11+
12+
Object source() { return null; }
13+
void sink(Object o) { }
14+
15+
public void test() throws Exception {
16+
17+
{
18+
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
19+
String out = null;
20+
String in = (String) source();
21+
Matcher m = pattern.matcher(in);
22+
out = m.group("foo");
23+
sink(out); // $ hasTaintFlow
24+
}
25+
{
26+
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
27+
String out = null;
28+
String in = (String) source();
29+
Matcher m = pattern.matcher(in);
30+
out = m.group();
31+
sink(out); // $ hasTaintFlow
32+
}
33+
{
34+
// "java.util.regex;Matcher;false;group;;;Argument[-1];ReturnValue;taint"
35+
String out = null;
36+
String in = (String) source();
37+
Matcher m = pattern.matcher(in);
38+
out = m.group(0);
39+
sink(out); // $ hasTaintFlow
40+
}
41+
{
42+
// "java.util.regex;Matcher;false;replaceAll;;;Argument[-1];ReturnValue;taint"
43+
String out = null;
44+
String in = (String) source();
45+
Matcher m = pattern.matcher(in);
46+
out = m.replaceAll("foo");
47+
sink(out); // $ hasTaintFlow
48+
}
49+
{
50+
// "java.util.regex;Matcher;false;replaceAll;;;Argument[0];ReturnValue;taint"
51+
String out = null;
52+
String in = (String) source();
53+
Matcher m = pattern.matcher("foo");
54+
out = m.replaceAll(in);
55+
sink(out); // $ hasTaintFlow
56+
}
57+
{
58+
// "java.util.regex;Matcher;false;replaceFirst;;;Argument[-1];ReturnValue;taint"
59+
String out = null;
60+
String in = (String) source();
61+
Matcher m = pattern.matcher(in);
62+
out = m.replaceFirst("foo");
63+
sink(out); // $ hasTaintFlow
64+
}
65+
{
66+
// "java.util.regex;Matcher;false;replaceFirst;;;Argument[0];ReturnValue;taint"
67+
String out = null;
68+
String in = (String) source();
69+
Matcher m = pattern.matcher("foo");
70+
out = m.replaceFirst(in);
71+
sink(out); // $ hasTaintFlow
72+
}
73+
{
74+
// "java.util.regex;Pattern;false;matcher;;;Argument[0];ReturnValue;taint"
75+
Matcher out = null;
76+
CharSequence in = (CharSequence)source();
77+
out = pattern.matcher(in);
78+
sink(out); // $ hasTaintFlow
79+
}
80+
{
81+
// "java.util.regex;Pattern;false;quote;;;Argument[0];ReturnValue;taint"
82+
String out = null;
83+
String in = (String)source();
84+
out = Pattern.quote(in);
85+
sink(out); // $ hasTaintFlow
86+
}
87+
{
88+
// "java.util.regex;Pattern;false;split;;;Argument[0];ReturnValue;taint"
89+
String[] out = null;
90+
CharSequence in = (CharSequence)source();
91+
out = pattern.split(in);
92+
sink(out); // $ hasTaintFlow
93+
}
94+
{
95+
// "java.util.regex;Pattern;false;split;;;Argument[0];ReturnValue;taint"
96+
String[] out = null;
97+
CharSequence in = (CharSequence)source();
98+
out = pattern.split(in, 0);
99+
sink(out); // $ hasTaintFlow
100+
}
101+
102+
}
103+
104+
}

0 commit comments

Comments
 (0)