JS: use RegExpLiteral as a SourceNode

This commit is contained in:
Esben Sparre Andreasen
2019-03-22 08:02:39 +01:00
parent 7923c9d77c
commit 364ba1b4ac
8 changed files with 16 additions and 5 deletions

View File

@@ -18,7 +18,7 @@ import javascript
*/
predicate matchesString(Expr e, string s) {
exists(RegExpLiteral rl |
rl = e and
rl.flow().(DataFlow::SourceNode).flowsToExpr(e) and
not rl.isIgnoreCase() and
regExpMatchesString(rl.getRoot(), s)
)

View File

@@ -70,7 +70,7 @@ class Replacement extends DataFlow::Node {
Replacement() {
exists(DataFlow::MethodCallNode mcn | this = mcn |
mcn.getMethodName() = "replace" and
mcn.getArgument(0).asExpr() = pattern and
pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0))and
mcn.getNumArgument() = 2 and
pattern.isGlobal()
)

View File

@@ -59,7 +59,7 @@ predicate isSimple(RegExpTerm t) {
*/
predicate isBackslashEscape(MethodCallExpr mce, RegExpLiteral re) {
mce.getMethodName() = "replace" and
re = mce.getArgument(0) and
re.flow().(DataFlow::SourceNode).flowsToExpr(mce.getArgument(0)) and
re.isGlobal() and
exists(string new | new = mce.getArgument(1).getStringValue() |
// `new` is `\$&`, `\$1` or similar
@@ -104,7 +104,7 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
from MethodCallExpr repl, Expr old, string msg
where
repl.getMethodName() = "replace" and
old = repl.getArgument(0) and
(old = repl.getArgument(0) or old.flow().(DataFlow::SourceNode).flowsToExpr(repl.getArgument(0))) and
(
not old.(RegExpLiteral).isGlobal() and
msg = "This replaces only the first occurrence of " + old + "." and

View File

@@ -100,7 +100,7 @@ module ClientSideUrlRedirect {
or
exists(MethodCallExpr mce |
queryAccess.asExpr() = mce and
mce.calls(any(RegExpLiteral re), "exec") and
mce = any(RegExpLiteral re).flow().(DataFlow::SourceNode).getAMethodCall("exec").asExpr() and
nd.asExpr() = mce.getArgument(0)
)
}

View File

@@ -1,4 +1,5 @@
| IdentityReplacement.js:1:27:1:30 | /"/g | This replaces '"' with itself. |
| IdentityReplacement.js:4:14:4:21 | indirect | This replaces '"' with itself. |
| tst.js:1:13:1:16 | "\\\\" | This replaces '\\' with itself. |
| tst.js:2:13:2:18 | /(\\\\)/ | This replaces '\\' with itself. |
| tst.js:3:13:3:17 | /["]/ | This replaces '"' with itself. |

View File

@@ -4,3 +4,4 @@
| tst.js:47:7:47:30 | s.repla ... g, "&") | This replacement may produce '&' characters that are double-unescaped $@. | tst.js:48:7:48:32 | s.repla ... , "\\"") | here |
| tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here |
| tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here |
| tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here |

View File

@@ -15,3 +15,4 @@
| tst.js:61:10:61:18 | s.replace | This replaces only the first occurrence of "'" + "". |
| tst.js:65:10:65:18 | s.replace | This replaces only the first occurrence of "'". |
| tst.js:69:10:69:18 | s.replace | This replaces only the first occurrence of "'" + "". |
| tst.js:169:9:169:17 | s.replace | This replaces only the first occurrence of /'/. |

View File

@@ -38,6 +38,10 @@ nodes
| tst.js:2:19:2:72 | /.*redi ... ref)[1] |
| tst.js:2:47:2:63 | document.location |
| tst.js:2:47:2:68 | documen ... on.href |
| tst.js:6:20:6:56 | indirec ... n.href) |
| tst.js:6:20:6:59 | indirec ... ref)[1] |
| tst.js:6:34:6:50 | document.location |
| tst.js:6:34:6:55 | documen ... on.href |
edges
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
@@ -69,6 +73,9 @@ edges
| tst.js:2:19:2:69 | /.*redi ... n.href) | tst.js:2:19:2:72 | /.*redi ... ref)[1] |
| tst.js:2:47:2:63 | document.location | tst.js:2:47:2:68 | documen ... on.href |
| tst.js:2:47:2:68 | documen ... on.href | tst.js:2:19:2:69 | /.*redi ... n.href) |
| tst.js:6:20:6:56 | indirec ... n.href) | tst.js:6:20:6:59 | indirec ... ref)[1] |
| tst.js:6:34:6:50 | document.location | tst.js:6:34:6:55 | documen ... on.href |
| tst.js:6:34:6:55 | documen ... on.href | tst.js:6:20:6:56 | indirec ... n.href) |
#select
| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
@@ -84,3 +91,4 @@ edges
| tst10.js:11:17:11:50 | '//foo' ... .search | tst10.js:11:27:11:43 | document.location | tst10.js:11:17:11:50 | '//foo' ... .search | Untrusted URL redirection due to $@. | tst10.js:11:27:11:43 | document.location | user-provided value |
| tst10.js:14:17:14:56 | 'https: ... .search | tst10.js:14:33:14:49 | document.location | tst10.js:14:17:14:56 | 'https: ... .search | Untrusted URL redirection due to $@. | tst10.js:14:33:14:49 | document.location | user-provided value |
| tst.js:2:19:2:72 | /.*redi ... ref)[1] | tst.js:2:47:2:63 | document.location | tst.js:2:19:2:72 | /.*redi ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:2:47:2:63 | document.location | user-provided value |
| tst.js:6:20:6:59 | indirec ... ref)[1] | tst.js:6:34:6:50 | document.location | tst.js:6:20:6:59 | indirec ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:6:34:6:50 | document.location | user-provided value |