JS: recognize A.substr(0, B.length) == B

This commit is contained in:
Asger F
2019-01-08 17:57:24 +00:00
parent f9951f67fe
commit cf3dfcae21
3 changed files with 40 additions and 0 deletions

View File

@@ -147,6 +147,37 @@ module StringOps {
}
}
/**
* A comparison of form `x.substring(0, y.length) === y`.
*/
private class StartsWith_Substring extends StartsWith, DataFlow::ValueNode {
override EqualityTest astNode;
DataFlow::MethodCallNode call;
DataFlow::Node substring;
StartsWith_Substring() {
astNode.hasOperands(call.asExpr(), substring.asExpr()) and
(call.getMethodName() = "substring" or call.getMethodName() = "substr") and
call.getNumArgument() = 2 and
(
substring.getALocalSource().getAPropertyRead("length").flowsTo(call.getArgument(1))
or
substring.asExpr().getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
)
}
override DataFlow::Node getBaseString() {
result = call.getReceiver()
}
override DataFlow::Node getSubstring() {
result = substring
}
override boolean getPolarity() {
result = astNode.getPolarity()
}
}
/**
* A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`.

View File

@@ -8,3 +8,7 @@
| tst.js:12:9:12:20 | A.indexOf(B) | tst.js:12:9:12:9 | A | tst.js:12:19:12:19 | B | false |
| tst.js:13:10:13:21 | A.indexOf(B) | tst.js:13:10:13:10 | A | tst.js:13:20:13:20 | B | false |
| tst.js:14:11:14:22 | A.indexOf(B) | tst.js:14:11:14:11 | A | tst.js:14:21:14:21 | B | false |
| tst.js:15:9:15:38 | A.subst ... ) === B | tst.js:15:9:15:9 | A | tst.js:15:38:15:38 | B | true |
| tst.js:16:9:16:38 | A.subst ... ) !== B | tst.js:16:9:16:9 | A | tst.js:16:38:16:38 | B | false |
| tst.js:17:9:17:35 | A.subst ... ) === B | tst.js:17:9:17:9 | A | tst.js:17:35:17:35 | B | true |
| tst.js:18:9:18:36 | A.subst ... "web/" | tst.js:18:9:18:9 | A | tst.js:18:31:18:36 | "web/" | true |

View File

@@ -12,6 +12,10 @@ function f(A, B) {
if (A.indexOf(B)) {} // !startsWith
if (!A.indexOf(B)) {} // startsWith
if (!!A.indexOf(B)) {} // !startsWith
if (A.substring(0, B.length) === B) {}
if (A.substring(0, B.length) !== B) {}
if (A.substr(0, B.length) === B) {}
if (A.substring(0, 4) === "web/") {}
// non-examples
if (_.startsWith(A, B, 2)) {}
@@ -22,4 +26,5 @@ function f(A, B) {
if (A.indexOf(B, 2) === 0) {}
if (A.indexOf(B, 2)) {}
if (~A.indexOf(B)) {} // checks for existence, not startsWith
if (A.substring(B.length) === 0) {}
}