mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge pull request #7723 from joefarebrother/redos
Java: Add ReDoS queries
This commit is contained in:
@@ -73,6 +73,11 @@ jdk/StringMatch.java:
|
||||
# 5| 0: [MethodAccess] matches(...)
|
||||
# 5| -1: [VarAccess] STR
|
||||
# 5| 0: [StringLiteral] "[a-z]+"
|
||||
# 5| 0: [RegExpPlus] [a-z]+
|
||||
# 5| 0: [RegExpCharacterClass] [a-z]
|
||||
# 5| 0: [RegExpCharacterRange] a-z
|
||||
# 5| 0: [RegExpConstant | RegExpNormalChar] a
|
||||
# 5| 1: [RegExpConstant | RegExpNormalChar] z
|
||||
# 8| 5: [Method] b
|
||||
# 8| 3: [TypeAccess] void
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
|
||||
@@ -101,4 +101,4 @@ public class Test {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
207
java/ql/test/library-tests/regex/parser/RegexParseTests.expected
Normal file
207
java/ql/test/library-tests/regex/parser/RegexParseTests.expected
Normal file
@@ -0,0 +1,207 @@
|
||||
parseFailures
|
||||
#select
|
||||
| Test.java:5:10:5:17 | [A-Z\\d] | [RegExpCharacterClass] |
|
||||
| Test.java:5:10:5:19 | [A-Z\\d]++ | [RegExpPlus] |
|
||||
| Test.java:5:11:5:11 | A | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:5:11:5:13 | A-Z | [RegExpCharacterRange] |
|
||||
| Test.java:5:13:5:13 | Z | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:5:14:5:16 | \\d | [RegExpCharacterClassEscape] |
|
||||
| Test.java:6:10:6:42 | \\Q hello world [ *** \\Q ) ( \\E | [RegExpConstant,RegExpQuote] |
|
||||
| Test.java:6:10:6:43 | \\Q hello world [ *** \\Q ) ( \\E+ | [RegExpPlus] |
|
||||
| Test.java:7:10:7:23 | [\\Q hi ] \\E] | [RegExpCharacterClass] |
|
||||
| Test.java:7:10:7:24 | [\\Q hi ] \\E]+ | [RegExpPlus] |
|
||||
| Test.java:7:11:7:22 | \\Q hi ] \\E | [RegExpConstant,RegExpQuote] |
|
||||
| Test.java:8:10:8:12 | []] | [RegExpCharacterClass] |
|
||||
| Test.java:8:10:8:13 | []]+ | [RegExpPlus] |
|
||||
| Test.java:8:11:8:11 | ] | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:9:10:9:13 | [^]] | [RegExpCharacterClass] |
|
||||
| Test.java:9:10:9:14 | [^]]+ | [RegExpPlus] |
|
||||
| Test.java:9:12:9:12 | ] | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:10:10:20 | [abc[defg]] | [RegExpCharacterClass] |
|
||||
| Test.java:10:10:10:21 | [abc[defg]]+ | [RegExpPlus] |
|
||||
| Test.java:10:11:10:11 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:12:10:12 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:13:10:13 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:14:10:14 | [ | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:15:10:15 | d | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:16:10:16 | e | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:17:10:17 | f | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:18:10:18 | g | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:10:19:10:19 | ] | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:10:11:57 | [abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]] | [RegExpCharacterClass] |
|
||||
| Test.java:11:10:11:69 | [abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]]\\b7\\b{g}8+ | [RegExpSequence] |
|
||||
| Test.java:11:11:11:11 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:12:11:12 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:13:11:13 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:14:11:14 | & | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:15:11:15 | & | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:16:11:16 | [ | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:17:11:19 | \\W | [RegExpCharacterClassEscape] |
|
||||
| Test.java:11:20:11:29 | \\p{Lower} | [RegExpCharacterClassEscape] |
|
||||
| Test.java:11:30:11:39 | \\P{Space} | [RegExpCharacterClassEscape] |
|
||||
| Test.java:11:40:11:55 | \\N{degree sign} | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:11:56:11:56 | ] | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:58:11:60 | \\b | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:11:61:11:61 | 7 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:62:11:67 | \\b{g} | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:11:68:11:68 | 8 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:11:68:11:69 | 8+ | [RegExpPlus] |
|
||||
| Test.java:12:10:12:13 | \\cA | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:12:10:12:14 | \\cA+ | [RegExpPlus] |
|
||||
| Test.java:13:10:13:13 | \\c( | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:13:10:13:14 | \\c(+ | [RegExpPlus] |
|
||||
| Test.java:14:10:14:14 | \\c\\ | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:14:10:14:19 | \\c\\(ab)+ | [RegExpSequence] |
|
||||
| Test.java:14:15:14:18 | (ab) | [RegExpGroup] |
|
||||
| Test.java:14:15:14:19 | (ab)+ | [RegExpPlus] |
|
||||
| Test.java:14:16:14:16 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:14:16:14:17 | ab | [RegExpSequence] |
|
||||
| Test.java:14:17:14:17 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:10:15:15 | (?>hi) | [RegExpGroup] |
|
||||
| Test.java:15:10:15:45 | (?>hi)(?<name>hell*?o*+)123\\k<name> | [RegExpSequence] |
|
||||
| Test.java:15:13:15:13 | h | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:13:15:14 | hi | [RegExpSequence] |
|
||||
| Test.java:15:14:15:14 | i | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:16:15:33 | (?<name>hell*?o*+) | [RegExpGroup] |
|
||||
| Test.java:15:24:15:24 | h | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:24:15:32 | hell*?o*+ | [RegExpSequence] |
|
||||
| Test.java:15:25:15:25 | e | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:26:15:26 | l | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:27:15:27 | l | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:27:15:29 | l*? | [RegExpStar] |
|
||||
| Test.java:15:30:15:30 | o | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:30:15:32 | o*+ | [RegExpStar] |
|
||||
| Test.java:15:34:15:34 | 1 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:35:15:35 | 2 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:36:15:36 | 3 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:15:37:15:45 | \\k<name> | [RegExpBackRef] |
|
||||
| Test.java:16:10:16:10 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:10:16:11 | a+ | [RegExpPlus] |
|
||||
| Test.java:16:10:16:108 | a+b*c?d{2}e{3,4}f{,5}g{6,}h+?i*?j??k{7}?l{8,9}?m{,10}?n{11,}?o++p*+q?+r{12}+s{13,14}+t{,15}+u{16,}+ | [RegExpSequence] |
|
||||
| Test.java:16:12:16:12 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:12:16:13 | b* | [RegExpStar] |
|
||||
| Test.java:16:14:16:14 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:14:16:15 | c? | [RegExpOpt] |
|
||||
| Test.java:16:16:16:16 | d | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:16:16:19 | d{2} | [RegExpRange] |
|
||||
| Test.java:16:20:16:20 | e | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:20:16:25 | e{3,4} | [RegExpRange] |
|
||||
| Test.java:16:26:16:26 | f | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:26:16:30 | f{,5} | [RegExpRange] |
|
||||
| Test.java:16:31:16:31 | g | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:31:16:35 | g{6,} | [RegExpRange] |
|
||||
| Test.java:16:36:16:36 | h | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:36:16:38 | h+? | [RegExpPlus] |
|
||||
| Test.java:16:39:16:39 | i | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:39:16:41 | i*? | [RegExpStar] |
|
||||
| Test.java:16:42:16:42 | j | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:42:16:44 | j?? | [RegExpOpt] |
|
||||
| Test.java:16:45:16:45 | k | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:45:16:49 | k{7}? | [RegExpQuantifier] |
|
||||
| Test.java:16:50:16:50 | l | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:50:16:56 | l{8,9}? | [RegExpQuantifier] |
|
||||
| Test.java:16:57:16:57 | m | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:57:16:63 | m{,10}? | [RegExpQuantifier] |
|
||||
| Test.java:16:64:16:64 | n | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:64:16:70 | n{11,}? | [RegExpQuantifier] |
|
||||
| Test.java:16:71:16:71 | o | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:71:16:73 | o++ | [RegExpPlus] |
|
||||
| Test.java:16:74:16:74 | p | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:74:16:76 | p*+ | [RegExpStar] |
|
||||
| Test.java:16:77:16:77 | q | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:77:16:79 | q?+ | [RegExpOpt] |
|
||||
| Test.java:16:80:16:80 | r | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:80:16:85 | r{12}+ | [RegExpQuantifier] |
|
||||
| Test.java:16:86:16:86 | s | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:86:16:94 | s{13,14}+ | [RegExpQuantifier] |
|
||||
| Test.java:16:95:16:95 | t | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:95:16:101 | t{,15}+ | [RegExpQuantifier] |
|
||||
| Test.java:16:102:16:102 | u | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:16:102:16:108 | u{16,}+ | [RegExpQuantifier] |
|
||||
| Test.java:17:10:17:13 | (?i) | [RegExpZeroWidthMatch] |
|
||||
| Test.java:17:10:17:36 | (?i)(?=a)(?!b)(?<=c)(?<!d)+ | [RegExpSequence] |
|
||||
| Test.java:17:14:17:18 | (?=a) | [RegExpPositiveLookahead] |
|
||||
| Test.java:17:17:17:17 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:17:19:17:23 | (?!b) | [RegExpNegativeLookahead] |
|
||||
| Test.java:17:22:17:22 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:17:24:17:29 | (?<=c) | [RegExpPositiveLookbehind] |
|
||||
| Test.java:17:28:17:28 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:17:30:17:35 | (?<!d) | [RegExpNegativeLookbehind] |
|
||||
| Test.java:17:30:17:36 | (?<!d)+ | [RegExpPlus] |
|
||||
| Test.java:17:34:17:34 | d | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:10:18:10 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:10:18:25 | a\|\|b\|c(d\|e\|)f\|g+ | [RegExpAlt] |
|
||||
| Test.java:18:12:18:25 | \|b\|c(d\|e\|)f\|g+ | [RegExpAlt] |
|
||||
| Test.java:18:13:18:13 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:15:18:15 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:15:18:22 | c(d\|e\|)f | [RegExpSequence] |
|
||||
| Test.java:18:16:18:21 | (d\|e\|) | [RegExpGroup] |
|
||||
| Test.java:18:17:18:17 | d | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:17:18:20 | d\|e\| | [RegExpAlt] |
|
||||
| Test.java:18:19:18:19 | e | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:22:18:22 | f | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:24:18:24 | g | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:18:24:18:25 | g+ | [RegExpPlus] |
|
||||
| Test.java:19:10:19:13 | \\01 | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:19:10:19:38 | \\018\\033\\0377\\0777\u1337+ | [RegExpSequence] |
|
||||
| Test.java:19:14:19:14 | 8 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:19:15:19:19 | \\033 | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:19:20:19:25 | \\0377 | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:19:26:19:30 | \\077 | [RegExpConstant,RegExpEscape] |
|
||||
| Test.java:19:31:19:31 | 7 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:19:32:19:37 | \u1337 | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:19:32:19:38 | \u1337+ | [RegExpPlus] |
|
||||
| Test.java:20:10:20:12 | [\|] | [RegExpCharacterClass] |
|
||||
| Test.java:20:10:20:13 | [\|]+ | [RegExpPlus] |
|
||||
| Test.java:20:11:20:11 | \| | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:10:21:37 | (a(a(a(a(a(a((((c))))a)))))) | [RegExpGroup] |
|
||||
| Test.java:21:10:21:68 | (a(a(a(a(a(a((((c))))a))))))((((((b(((((d)))))b)b)b)b)b)b)+ | [RegExpSequence] |
|
||||
| Test.java:21:11:21:11 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:11:21:36 | a(a(a(a(a(a((((c))))a))))) | [RegExpSequence] |
|
||||
| Test.java:21:12:21:36 | (a(a(a(a(a((((c))))a))))) | [RegExpGroup] |
|
||||
| Test.java:21:13:21:13 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:13:21:35 | a(a(a(a(a((((c))))a)))) | [RegExpSequence] |
|
||||
| Test.java:21:14:21:35 | (a(a(a(a((((c))))a)))) | [RegExpGroup] |
|
||||
| Test.java:21:15:21:15 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:15:21:34 | a(a(a(a((((c))))a))) | [RegExpSequence] |
|
||||
| Test.java:21:16:21:34 | (a(a(a((((c))))a))) | [RegExpGroup] |
|
||||
| Test.java:21:17:21:17 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:17:21:33 | a(a(a((((c))))a)) | [RegExpSequence] |
|
||||
| Test.java:21:18:21:33 | (a(a((((c))))a)) | [RegExpGroup] |
|
||||
| Test.java:21:19:21:19 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:19:21:32 | a(a((((c))))a) | [RegExpSequence] |
|
||||
| Test.java:21:20:21:32 | (a((((c))))a) | [RegExpGroup] |
|
||||
| Test.java:21:21:21:21 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:21:21:31 | a((((c))))a | [RegExpSequence] |
|
||||
| Test.java:21:22:21:30 | ((((c)))) | [RegExpGroup] |
|
||||
| Test.java:21:23:21:29 | (((c))) | [RegExpGroup] |
|
||||
| Test.java:21:24:21:28 | ((c)) | [RegExpGroup] |
|
||||
| Test.java:21:25:21:27 | (c) | [RegExpGroup] |
|
||||
| Test.java:21:26:21:26 | c | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:31:21:31 | a | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:38:21:67 | ((((((b(((((d)))))b)b)b)b)b)b) | [RegExpGroup] |
|
||||
| Test.java:21:38:21:68 | ((((((b(((((d)))))b)b)b)b)b)b)+ | [RegExpPlus] |
|
||||
| Test.java:21:39:21:65 | (((((b(((((d)))))b)b)b)b)b) | [RegExpGroup] |
|
||||
| Test.java:21:39:21:66 | (((((b(((((d)))))b)b)b)b)b)b | [RegExpSequence] |
|
||||
| Test.java:21:40:21:63 | ((((b(((((d)))))b)b)b)b) | [RegExpGroup] |
|
||||
| Test.java:21:40:21:64 | ((((b(((((d)))))b)b)b)b)b | [RegExpSequence] |
|
||||
| Test.java:21:41:21:61 | (((b(((((d)))))b)b)b) | [RegExpGroup] |
|
||||
| Test.java:21:41:21:62 | (((b(((((d)))))b)b)b)b | [RegExpSequence] |
|
||||
| Test.java:21:42:21:59 | ((b(((((d)))))b)b) | [RegExpGroup] |
|
||||
| Test.java:21:42:21:60 | ((b(((((d)))))b)b)b | [RegExpSequence] |
|
||||
| Test.java:21:43:21:57 | (b(((((d)))))b) | [RegExpGroup] |
|
||||
| Test.java:21:43:21:58 | (b(((((d)))))b)b | [RegExpSequence] |
|
||||
| Test.java:21:44:21:44 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:44:21:56 | b(((((d)))))b | [RegExpSequence] |
|
||||
| Test.java:21:45:21:55 | (((((d))))) | [RegExpGroup] |
|
||||
| Test.java:21:46:21:54 | ((((d)))) | [RegExpGroup] |
|
||||
| Test.java:21:47:21:53 | (((d))) | [RegExpGroup] |
|
||||
| Test.java:21:48:21:52 | ((d)) | [RegExpGroup] |
|
||||
| Test.java:21:49:21:51 | (d) | [RegExpGroup] |
|
||||
| Test.java:21:50:21:50 | d | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:56:21:56 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:58:21:58 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:60:21:60 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:62:21:62 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:64:21:64 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
| Test.java:21:66:21:66 | b | [RegExpConstant,RegExpNormalChar] |
|
||||
10
java/ql/test/library-tests/regex/parser/RegexParseTests.ql
Normal file
10
java/ql/test/library-tests/regex/parser/RegexParseTests.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import java
|
||||
import semmle.code.java.regex.RegexTreeView
|
||||
import semmle.code.java.regex.regex
|
||||
|
||||
string getQLClases(RegExpTerm t) { result = "[" + strictconcat(t.getPrimaryQLClass(), ",") + "]" }
|
||||
|
||||
query predicate parseFailures(Regex r, int i) { r.failedToParse(i) }
|
||||
|
||||
from RegExpTerm t
|
||||
select t, getQLClases(t)
|
||||
29
java/ql/test/library-tests/regex/parser/Test.java
Normal file
29
java/ql/test/library-tests/regex/parser/Test.java
Normal file
@@ -0,0 +1,29 @@
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class Test {
|
||||
static String[] regs = {
|
||||
"[A-Z\\d]++",
|
||||
"\\Q hello world [ *** \\Q ) ( \\E+",
|
||||
"[\\Q hi ] \\E]+",
|
||||
"[]]+",
|
||||
"[^]]+",
|
||||
"[abc[defg]]+",
|
||||
"[abc&&[\\W\\p{Lower}\\P{Space}\\N{degree sign}]]\\b7\\b{g}8+",
|
||||
"\\cA+",
|
||||
"\\c(+",
|
||||
"\\c\\(ab)+",
|
||||
"(?>hi)(?<name>hell*?o*+)123\\k<name>",
|
||||
"a+b*c?d{2}e{3,4}f{,5}g{6,}h+?i*?j??k{7}?l{8,9}?m{,10}?n{11,}?o++p*+q?+r{12}+s{13,14}+t{,15}+u{16,}+",
|
||||
"(?i)(?=a)(?!b)(?<=c)(?<!d)+",
|
||||
"a||b|c(d|e|)f|g+",
|
||||
"\\018\\033\\0377\\0777\u1337+",
|
||||
"[|]+",
|
||||
"(a(a(a(a(a(a((((c))))a))))))((((((b(((((d)))))b)b)b)b)b)b)+"
|
||||
};
|
||||
|
||||
void test() {
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
Pattern.compile(regs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
439
java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java
Normal file
439
java/ql/test/query-tests/security/CWE-730/ExpRedosTest.java
Normal file
@@ -0,0 +1,439 @@
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class ExpRedosTest {
|
||||
static String[] regs = {
|
||||
|
||||
// NOT GOOD; attack: "_" + "__".repeat(100)
|
||||
// Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
||||
// under the MIT license; see file marked-LICENSE.
|
||||
"^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
// Adapted from marked (https://github.com/markedjs/marked), which is licensed
|
||||
// under the MIT license; see file marked-LICENSE.
|
||||
"^\\b_((?:__|[^_])+?)_\\b|^\\*((?:\\*\\*|[^*])+?)\\*(?!\\*)",
|
||||
|
||||
// GOOD - there is no witness in the end that could cause the regexp to not match
|
||||
// Adapted from brace-expansion (https://github.com/juliangruber/brace-expansion),
|
||||
// which is licensed under the MIT license; see file brace-expansion-LICENSE.
|
||||
"(.*,)+.+",
|
||||
|
||||
// NOT GOOD; attack: " '" + "\\\\".repeat(100)
|
||||
// Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
||||
// which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
||||
"^(?:\\s+(?:\"(?:[^\"\\\\]|\\\\\\\\|\\\\.)+\"|'(?:[^'\\\\]|\\\\\\\\|\\\\.)+'|\\((?:[^)\\\\]|\\\\\\\\|\\\\.)+\\)))?", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
// Adapted from lulucms2 (https://github.com/yiifans/lulucms2).
|
||||
"\\(\\*(?:[\\s\\S]*?\\(\\*[\\s\\S]*?\\*\\))*[\\s\\S]*?\\*\\)",
|
||||
|
||||
// GOOD
|
||||
// Adapted from jest (https://github.com/facebook/jest), which is licensed
|
||||
// under the MIT license; see file jest-LICENSE.
|
||||
"^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*",
|
||||
|
||||
// NOT GOOD, variant of good3; attack: "a|\n:|\n" + "||\n".repeat(100)
|
||||
"^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)a", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD; attack: "/" + "\\/a".repeat(100)
|
||||
// Adapted from ANodeBlog (https://github.com/gefangshuai/ANodeBlog),
|
||||
// which is licensed under the Apache License 2.0; see file ANodeBlog-LICENSE.
|
||||
"\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD; attack: "##".repeat(100) + "\na"
|
||||
// Adapted from CodeMirror (https://github.com/codemirror/codemirror),
|
||||
// which is licensed under the MIT license; see file CodeMirror-LICENSE.
|
||||
"^([\\s\\[\\{\\(]|#.*)*$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(\\r\\n|\\r|\\n)+",
|
||||
|
||||
// BAD - PoC: `node -e "/((?:[^\"\']|\".*?\"|\'.*?\')*?)([(,)]|$)/.test(\"'''''''''''''''''''''''''''''''''''''''''''''\\\"\");"`. It's complicated though, because the regexp still matches something, it just matches the empty-string after the attack string.
|
||||
|
||||
// NOT GOOD; attack: "a" + "[]".repeat(100) + ".b\n"
|
||||
// Adapted from Knockout (https://github.com/knockout/knockout), which is
|
||||
// licensed under the MIT license; see file knockout-LICENSE
|
||||
"^[\\_$a-z][\\_$a-z0-9]*(\\[.*?\\])*(\\.[\\_$a-z][\\_$a-z0-9]*(\\[.*?\\])*)*$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a|.)*",
|
||||
|
||||
// Testing the NFA - only some of the below are detected.
|
||||
"^([a-z]+)+$", // $ hasExpRedos
|
||||
"^([a-z]*)*$", // $ hasExpRedos
|
||||
"^([a-zA-Z0-9])(([\\\\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$", // $ hasExpRedos
|
||||
"^(([a-z])+.)+[A-Z]([a-z])+$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD; attack: "[" + "][".repeat(100) + "]!"
|
||||
// Adapted from Prototype.js (https://github.com/prototypejs/prototype), which
|
||||
// is licensed under the MIT license; see file Prototype.js-LICENSE.
|
||||
"(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD; attack: "'" + "\\a".repeat(100) + '"'
|
||||
// Adapted from Prism (https://github.com/PrismJS/prism), which is licensed
|
||||
// under the MIT license; see file Prism-LICENSE.
|
||||
"(\"|')(\\\\?.)*?\\1", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(b|a?b)*c", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(a|aa?)*b", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(.|\\n)*!",
|
||||
|
||||
// NOT GOOD; attack: "\n".repeat(100) + "."
|
||||
"(?s)(.|\\n)*!", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"([\\w.]+)*",
|
||||
|
||||
// NOT GOOD
|
||||
"(a|aa?)*b", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(([\\s\\S]|[^a])*)\"", // $ hasExpRedos
|
||||
|
||||
// GOOD - there is no witness in the end that could cause the regexp to not match
|
||||
"([^\"']+)*",
|
||||
|
||||
// NOT GOOD
|
||||
"((.|[^a])*)\"", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"((a|[^a])*)\"",
|
||||
|
||||
// NOT GOOD
|
||||
"((b|[^a])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((G|[^a])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(([0-9]|[^a])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(?:=(?:([!#\\$%&'\\*\\+\\-\\.\\^_`\\|~0-9A-Za-z]+)|\"((?:\\\\[\\x00-\\x7f]|[^\\x00-\\x08\\x0a-\\x1f\\x7f\"])*)\"))?", // $ MISSING: hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"\"((?:\\\\[\\x00-\\x7f]|[^\\x00-\\x08\\x0a-\\x1f\\x7f\"])*)\"", // $ MISSING: hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"\"((?:\\\\[\\x00-\\x7f]|[^\\x00-\\x08\\x0a-\\x1f\\x7f\"\\\\])*)\"",
|
||||
|
||||
// NOT GOOD
|
||||
"(([a-z]|[d-h])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(([^a-z]|[^0-9])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\d|[0-9])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\s|\\s)*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\w|G)*)\"", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"((\\s|\\d)*)\"",
|
||||
|
||||
// NOT GOOD
|
||||
"((\\d|\\w)*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\d|5)*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\s|[\\f])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD - but not detected (likely because \v is a character class in Java rather than a specific character in other langs)
|
||||
"((\\s|[\\v]|\\\\v)*)\"", // $ MISSING: hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\f|[\\f])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\W|\\D)*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\S|\\w)*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((\\S|[\\w])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((1s|[\\da-z])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((0|[\\d])*)\"", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(([\\d]+)*)\"", // $ hasExpRedos
|
||||
|
||||
// GOOD - there is no witness in the end that could cause the regexp to not match
|
||||
"(\\d+(X\\d+)?)+",
|
||||
|
||||
// GOOD - there is no witness in the end that could cause the regexp to not match
|
||||
"([0-9]+(X[0-9]*)?)*",
|
||||
|
||||
// GOOD
|
||||
"^([^>]+)*(>|$)",
|
||||
|
||||
// NOT GOOD
|
||||
"^([^>a]+)*(>|$)", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(\\n\\s*)+$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"^(?:\\s+|#.*|\\(\\?#[^)]*\\))*(?:[?*+]|\\{\\d+(?:,\\d*)?})", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"\\{\\[\\s*([a-zA-Z]+)\\(([a-zA-Z]+)\\)((\\s*([a-zA-Z]+)\\: ?([ a-zA-Z{}]+),?)+)*\\s*\\]\\}", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(a+|b+|c+)*c", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(((a+a?)*)+b+)", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(a+)+bbbb", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a+)+aaaaa*a+",
|
||||
|
||||
// NOT GOOD
|
||||
"(a+)+aaaaa$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(\\n+)+\\n\\n",
|
||||
|
||||
// NOT GOOD
|
||||
"(\\n+)+\\n\\n$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"([^X]+)*$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(([^X]b)+)*$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(([^X]b)+)*($|[^X]b)",
|
||||
|
||||
// NOT GOOD
|
||||
"(([^X]b)+)*($|[^X]c)", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"((ab)+)*ababab",
|
||||
|
||||
// GOOD
|
||||
"((ab)+)*abab(ab)*(ab)+",
|
||||
|
||||
// GOOD
|
||||
"((ab)+)*",
|
||||
|
||||
// NOT GOOD
|
||||
"((ab)+)*$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"((ab)+)*[a1][b1][a2][b2][a3][b3]",
|
||||
|
||||
// NOT GOOD
|
||||
"([\\n\\s]+)*(.)", // $ hasExpRedos
|
||||
|
||||
// GOOD - any witness passes through the accept state.
|
||||
"(A*A*X)*",
|
||||
|
||||
// GOOD
|
||||
"([^\\\\\\]]+)*",
|
||||
|
||||
// NOT GOOD
|
||||
"(\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\w*foobarbaz\\s*foobarbaz\\d*foobarbaz\\w*)+-", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(.thisisagoddamnlongstringforstresstestingthequery|\\sthisisagoddamnlongstringforstresstestingthequery)*-", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(thisisagoddamnlongstringforstresstestingthequery|this\\w+query)*-", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(thisisagoddamnlongstringforstresstestingthequery|imanotherbutunrelatedstringcomparedtotheotherstring)*-",
|
||||
|
||||
// GOOD (but false positive caused by the extractor converting all four unpaired surrogates to \uFFFD)
|
||||
"foo([\uDC66\uDC67]|[\uDC68\uDC69])*foo", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// GOOD (but false positive caused by the extractor converting all four unpaired surrogates to \uFFFD)
|
||||
"foo((\uDC66|\uDC67)|(\uDC68|\uDC69))*foo", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// NOT GOOD (but cannot currently construct a prefix)
|
||||
"a{2,3}(b+)+X", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD (and a good prefix test)
|
||||
"^<(\\w+)((?:\\s+\\w+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)>", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a+)*[\\s\\S][\\s\\S][\\s\\S]?",
|
||||
|
||||
// GOOD - but we fail to see that repeating the attack string ends in the "accept any" state (due to not parsing the range `[\s\S]{2,3}`).
|
||||
"(a+)*[\\s\\S]{2,3}", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// GOOD - but we spuriously conclude that a rejecting suffix exists (due to not parsing the range `[\s\S]{2,}` when constructing the NFA).
|
||||
"(a+)*([\\s\\S]{2,}|X)$", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a+)*([\\s\\S]*|X)$",
|
||||
|
||||
// NOT GOOD
|
||||
"((a+)*$|[\\s\\S]+)", // $ hasExpRedos
|
||||
|
||||
// GOOD - but still flagged. The only change compared to the above is the order of alternatives, which we don't model.
|
||||
"([\\s\\S]+|(a+)*$)", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"((;|^)a+)+$",
|
||||
|
||||
// NOT GOOD (a good prefix test)
|
||||
"(^|;)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(e+)+f", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"^ab(c+)+$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(\\d(\\s+)*){20}", // $ hasExpRedos
|
||||
|
||||
// GOOD - but we spuriously conclude that a rejecting suffix exists.
|
||||
"(([^/]|X)+)(\\/[\\s\\S]*)*$", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// GOOD - but we spuriously conclude that a rejecting suffix exists.
|
||||
"^((x([^Y]+)?)*(Y|$))", // $ SPURIOUS: hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(a*)+b", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"foo([\\w-]*)+bar", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"((ab)*)+c", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(a?a?)*b", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a?)*b",
|
||||
|
||||
// NOT GOOD - but not detected
|
||||
"(c?a?)*b", // $ MISSING: hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"(?:a|a?)+b", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD - but not detected.
|
||||
"(a?b?)*$", // $ MISSING: hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"PRE(([a-c]|[c-d])T(e?e?e?e?|X))+(cTcT|cTXcTX$)", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"^((a)+\\w)+$", // $ hasExpRedos
|
||||
|
||||
// NOT GOOD
|
||||
"^(b+.)+$", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"a*b",
|
||||
|
||||
// All 4 bad combinations of nested * and +
|
||||
"(a*)*b", // $ hasExpRedos
|
||||
"(a+)*b", // $ hasExpRedos
|
||||
"(a*)+b", // $ hasExpRedos
|
||||
"(a+)+b", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"(a|b)+",
|
||||
"(?:[\\s;,\"'<>(){}|\\[\\]@=+*]|:(?![/\\\\]))+",
|
||||
|
||||
"^((?:a{|-)|\\w\\{)+X$", // $ hasParseFailure
|
||||
"^((?:a{0|-)|\\w\\{\\d)+X$", // $ hasParseFailure
|
||||
"^((?:a{0,|-)|\\w\\{\\d,)+X$", // $ hasParseFailure
|
||||
"^((?:a{0,2|-)|\\w\\{\\d,\\d)+X$", // $ hasParseFailure
|
||||
|
||||
// GOOD
|
||||
"^((?:a{0,2}|-)|\\w\\{\\d,\\d\\})+X$",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\u0061|a)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\u0061|b)+Y",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\x61|a)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\x61|b)+Y",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\x{061}|a)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\x{061}|b)+Y",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\p{Digit}|7)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\p{Digit}|b)+Y",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\P{Digit}|b)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\P{Digit}|7)+Y",
|
||||
|
||||
// NOT GOOD
|
||||
"X(\\p{IsDigit}|7)*Y", // $ hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\p{IsDigit}|b)+Y",
|
||||
|
||||
// NOT GOOD - but not detected
|
||||
"X(\\p{Alpha}|a)*Y", // $ MISSING: hasExpRedos
|
||||
|
||||
// GOOD
|
||||
"X(\\p{Alpha}|7)+Y",
|
||||
|
||||
// GOOD
|
||||
"(\"[^\"]*?\"|[^\"\\s]+)+(?=\\s*|\\s*$)",
|
||||
|
||||
// BAD
|
||||
"/(\"[^\"]*?\"|[^\"\\s]+)+(?=\\s*|\\s*$)X", // $ hasExpRedos
|
||||
"/(\"[^\"]*?\"|[^\"\\s]+)+(?=X)", // $ hasExpRedos
|
||||
|
||||
// BAD
|
||||
"\\A(\\d|0)*x", // $ hasExpRedos
|
||||
"(\\d|0)*\\Z", // $ hasExpRedos
|
||||
"\\b(\\d|0)*x", // $ hasExpRedos
|
||||
|
||||
// GOOD - possessive quantifiers don't backtrack
|
||||
"(a*+)*+b",
|
||||
"(a*)*+b",
|
||||
"(a*+)*b",
|
||||
|
||||
// BAD
|
||||
"(a*)*b", // $ hasExpRedos
|
||||
|
||||
// BAD - but not detected due to the way possessive quantifiers are approximated
|
||||
"((aa|a*+)b)*c" // $ MISSING: hasExpRedos
|
||||
};
|
||||
|
||||
void test() {
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
Pattern.compile(regs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
84
java/ql/test/query-tests/security/CWE-730/PolyRedosTest.java
Normal file
84
java/ql/test/query-tests/security/CWE-730/PolyRedosTest.java
Normal file
@@ -0,0 +1,84 @@
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.function.Predicate;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
class PolyRedosTest {
|
||||
void test(HttpServletRequest request) {
|
||||
String tainted = request.getParameter("inp");
|
||||
String reg = "0\\.\\d+E?\\d+!";
|
||||
Predicate<String> dummyPred = (s -> s.length() % 7 == 0);
|
||||
|
||||
tainted.matches(reg); // $ hasPolyRedos
|
||||
tainted.split(reg); // $ hasPolyRedos
|
||||
tainted.split(reg, 7); // $ hasPolyRedos
|
||||
tainted.replaceAll(reg, "a"); // $ hasPolyRedos
|
||||
tainted.replaceFirst(reg, "a"); // $ hasPolyRedos
|
||||
Pattern.matches(reg, tainted); // $ hasPolyRedos
|
||||
Pattern.compile(reg).matcher(tainted).matches(); // $ hasPolyRedos
|
||||
Pattern.compile(reg).split(tainted); // $ hasPolyRedos
|
||||
Pattern.compile(reg, Pattern.DOTALL).split(tainted); // $ hasPolyRedos
|
||||
Pattern.compile(reg).split(tainted, 7); // $ hasPolyRedos
|
||||
Pattern.compile(reg).splitAsStream(tainted); // $ hasPolyRedos
|
||||
Pattern.compile(reg).asPredicate().test(tainted); // $ hasPolyRedos
|
||||
Pattern.compile(reg).asMatchPredicate().negate().and(dummyPred).or(dummyPred).test(tainted); // $ hasPolyRedos
|
||||
Predicate.not(dummyPred.and(dummyPred.or(Pattern.compile(reg).asPredicate()))).test(tainted); // $ hasPolyRedos
|
||||
|
||||
Splitter.on(Pattern.compile(reg)).split(tainted); // $ hasPolyRedos
|
||||
Splitter.on(reg).split(tainted);
|
||||
Splitter.onPattern(reg).split(tainted); // $ hasPolyRedos
|
||||
Splitter.onPattern(reg).splitToList(tainted); // $ hasPolyRedos
|
||||
Splitter.onPattern(reg).limit(7).omitEmptyStrings().trimResults().split(tainted); // $ hasPolyRedos
|
||||
Splitter.onPattern(reg).withKeyValueSeparator(" => ").split(tainted); // $ hasPolyRedos
|
||||
Splitter.on(";").withKeyValueSeparator(reg).split(tainted);
|
||||
Splitter.on(";").withKeyValueSeparator(Splitter.onPattern(reg)).split(tainted); // $ hasPolyRedos
|
||||
|
||||
}
|
||||
|
||||
void test2(HttpServletRequest request) {
|
||||
String tainted = request.getParameter("inp");
|
||||
|
||||
Pattern p1 = Pattern.compile(".*a");
|
||||
Pattern p2 = Pattern.compile(".*b");
|
||||
|
||||
p1.matcher(tainted).matches();
|
||||
p2.matcher(tainted).find(); // $ hasPolyRedos
|
||||
}
|
||||
|
||||
void test3(HttpServletRequest request) {
|
||||
String tainted = request.getParameter("inp");
|
||||
|
||||
Pattern p1 = Pattern.compile("ab*b*");
|
||||
Pattern p2 = Pattern.compile("cd*d*");
|
||||
|
||||
p1.matcher(tainted).matches(); // $ hasPolyRedos
|
||||
p2.matcher(tainted).find();
|
||||
}
|
||||
|
||||
void test4(HttpServletRequest request) {
|
||||
String tainted = request.getParameter("inp");
|
||||
|
||||
tainted.matches(".*a");
|
||||
tainted.replaceAll(".*b", "c"); // $ hasPolyRedos
|
||||
}
|
||||
|
||||
static Pattern p3 = Pattern.compile(".*a");
|
||||
static Pattern p4 = Pattern.compile(".*b");
|
||||
|
||||
|
||||
void test5(HttpServletRequest request) {
|
||||
String tainted = request.getParameter("inp");
|
||||
|
||||
p3.asMatchPredicate().test(tainted);
|
||||
p4.asPredicate().test(tainted); // $ hasPolyRedos
|
||||
}
|
||||
|
||||
void test6(HttpServletRequest request) {
|
||||
Pattern p = Pattern.compile("^a*a*$");
|
||||
|
||||
p.matcher(request.getParameter("inp")).matches(); // $ hasPolyRedos
|
||||
p.matcher(request.getHeader("If-None-Match")).matches();
|
||||
p.matcher(request.getRequestURI()).matches();
|
||||
p.matcher(request.getCookies()[0].getName()).matches();
|
||||
}
|
||||
}
|
||||
19
java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql
Normal file
19
java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql
Normal file
@@ -0,0 +1,19 @@
|
||||
import java
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import semmle.code.java.security.performance.PolynomialReDoSQuery
|
||||
|
||||
class HasPolyRedos extends InlineExpectationsTest {
|
||||
HasPolyRedos() { this = "HasPolyRedos" }
|
||||
|
||||
override string getARelevantTag() { result = "hasPolyRedos" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasPolyRedos" and
|
||||
exists(DataFlow::PathNode source, DataFlow::PathNode sink, PolynomialBackTrackingTerm regexp |
|
||||
hasPolynomialReDoSResult(source, sink, regexp) and
|
||||
location = sink.getNode().getLocation() and
|
||||
element = sink.getNode().toString() and
|
||||
value = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
29
java/ql/test/query-tests/security/CWE-730/ReDoS.ql
Normal file
29
java/ql/test/query-tests/security/CWE-730/ReDoS.ql
Normal file
@@ -0,0 +1,29 @@
|
||||
import java
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import semmle.code.java.security.performance.ExponentialBackTracking
|
||||
import semmle.code.java.regex.regex
|
||||
|
||||
class HasExpRedos extends InlineExpectationsTest {
|
||||
HasExpRedos() { this = "HasExpRedos" }
|
||||
|
||||
override string getARelevantTag() { result = ["hasExpRedos", "hasParseFailure"] }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
tag = "hasExpRedos" and
|
||||
exists(RegExpTerm t, string pump, State s, string prefixMsg |
|
||||
hasReDoSResult(t, pump, s, prefixMsg) and
|
||||
not t.getRegex().getAMode() = "VERBOSE" and
|
||||
value = "" and
|
||||
location = t.getLocation() and
|
||||
element = t.toString()
|
||||
)
|
||||
or
|
||||
tag = "hasParseFailure" and
|
||||
exists(Regex r |
|
||||
r.failedToParse(_) and
|
||||
value = "" and
|
||||
location = r.getLocation() and
|
||||
element = r.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
1
java/ql/test/query-tests/security/CWE-730/options
Normal file
1
java/ql/test/query-tests/security/CWE-730/options
Normal file
@@ -0,0 +1 @@
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/guava-30.0
|
||||
53
java/ql/test/stubs/guava-30.0/com/google/common/base/CharMatcher.java
generated
Normal file
53
java/ql/test/stubs/guava-30.0/com/google/common/base/CharMatcher.java
generated
Normal file
@@ -0,0 +1,53 @@
|
||||
// Generated automatically from com.google.common.base.CharMatcher for testing purposes
|
||||
|
||||
package com.google.common.base;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
abstract public class CharMatcher implements Predicate<Character>
|
||||
{
|
||||
protected CharMatcher(){}
|
||||
public CharMatcher and(CharMatcher p0){ return null; }
|
||||
public CharMatcher negate(){ return null; }
|
||||
public CharMatcher or(CharMatcher p0){ return null; }
|
||||
public CharMatcher precomputed(){ return null; }
|
||||
public String collapseFrom(CharSequence p0, char p1){ return null; }
|
||||
public String removeFrom(CharSequence p0){ return null; }
|
||||
public String replaceFrom(CharSequence p0, CharSequence p1){ return null; }
|
||||
public String replaceFrom(CharSequence p0, char p1){ return null; }
|
||||
public String retainFrom(CharSequence p0){ return null; }
|
||||
public String toString(){ return null; }
|
||||
public String trimAndCollapseFrom(CharSequence p0, char p1){ return null; }
|
||||
public String trimFrom(CharSequence p0){ return null; }
|
||||
public String trimLeadingFrom(CharSequence p0){ return null; }
|
||||
public String trimTrailingFrom(CharSequence p0){ return null; }
|
||||
public abstract boolean matches(char p0);
|
||||
public boolean apply(Character p0){ return false; }
|
||||
public boolean matchesAllOf(CharSequence p0){ return false; }
|
||||
public boolean matchesAnyOf(CharSequence p0){ return false; }
|
||||
public boolean matchesNoneOf(CharSequence p0){ return false; }
|
||||
public int countIn(CharSequence p0){ return 0; }
|
||||
public int indexIn(CharSequence p0){ return 0; }
|
||||
public int indexIn(CharSequence p0, int p1){ return 0; }
|
||||
public int lastIndexIn(CharSequence p0){ return 0; }
|
||||
public static CharMatcher any(){ return null; }
|
||||
public static CharMatcher anyOf(CharSequence p0){ return null; }
|
||||
public static CharMatcher ascii(){ return null; }
|
||||
public static CharMatcher breakingWhitespace(){ return null; }
|
||||
public static CharMatcher digit(){ return null; }
|
||||
public static CharMatcher forPredicate(Predicate<? super Character> p0){ return null; }
|
||||
public static CharMatcher inRange(char p0, char p1){ return null; }
|
||||
public static CharMatcher invisible(){ return null; }
|
||||
public static CharMatcher is(char p0){ return null; }
|
||||
public static CharMatcher isNot(char p0){ return null; }
|
||||
public static CharMatcher javaDigit(){ return null; }
|
||||
public static CharMatcher javaIsoControl(){ return null; }
|
||||
public static CharMatcher javaLetter(){ return null; }
|
||||
public static CharMatcher javaLetterOrDigit(){ return null; }
|
||||
public static CharMatcher javaLowerCase(){ return null; }
|
||||
public static CharMatcher javaUpperCase(){ return null; }
|
||||
public static CharMatcher none(){ return null; }
|
||||
public static CharMatcher noneOf(CharSequence p0){ return null; }
|
||||
public static CharMatcher singleWidth(){ return null; }
|
||||
public static CharMatcher whitespace(){ return null; }
|
||||
}
|
||||
@@ -1,48 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
// Generated automatically from com.google.common.base.Splitter for testing purposes
|
||||
|
||||
package com.google.common.base;
|
||||
|
||||
import java.util.Iterator;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class Splitter {
|
||||
|
||||
public static Splitter on(final String separator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Splitter omitEmptyStrings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Iterable<String> split(final CharSequence sequence) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> splitToList(CharSequence sequence) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public MapSplitter withKeyValueSeparator(String separator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final class MapSplitter {
|
||||
public Map<String, String> split(CharSequence sequence) {
|
||||
return null;
|
||||
public class Splitter
|
||||
{
|
||||
protected Splitter() {}
|
||||
public Iterable<String> split(CharSequence p0){ return null; }
|
||||
public List<String> splitToList(CharSequence p0){ return null; }
|
||||
public Splitter limit(int p0){ return null; }
|
||||
public Splitter omitEmptyStrings(){ return null; }
|
||||
public Splitter trimResults(){ return null; }
|
||||
public Splitter trimResults(CharMatcher p0){ return null; }
|
||||
public Splitter.MapSplitter withKeyValueSeparator(Splitter p0){ return null; }
|
||||
public Splitter.MapSplitter withKeyValueSeparator(String p0){ return null; }
|
||||
public Splitter.MapSplitter withKeyValueSeparator(char p0){ return null; }
|
||||
public Stream<String> splitToStream(CharSequence p0){ return null; }
|
||||
public static Splitter fixedLength(int p0){ return null; }
|
||||
public static Splitter on(CharMatcher p0){ return null; }
|
||||
public static Splitter on(Pattern p0){ return null; }
|
||||
public static Splitter on(String p0){ return null; }
|
||||
public static Splitter on(char p0){ return null; }
|
||||
public static Splitter onPattern(String p0){ return null; }
|
||||
static public class MapSplitter
|
||||
{
|
||||
protected MapSplitter() {}
|
||||
public Map<String, String> split(CharSequence p0){ return null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user