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

Skip to content

Commit cf3dfca

Browse files
committed
JS: recognize A.substr(0, B.length) == B
1 parent f9951f6 commit cf3dfca

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

javascript/ql/src/semmle/javascript/StringOps.qll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,37 @@ module StringOps {
147147
}
148148
}
149149

150+
/**
151+
* A comparison of form `x.substring(0, y.length) === y`.
152+
*/
153+
private class StartsWith_Substring extends StartsWith, DataFlow::ValueNode {
154+
override EqualityTest astNode;
155+
DataFlow::MethodCallNode call;
156+
DataFlow::Node substring;
157+
158+
StartsWith_Substring() {
159+
astNode.hasOperands(call.asExpr(), substring.asExpr()) and
160+
(call.getMethodName() = "substring" or call.getMethodName() = "substr") and
161+
call.getNumArgument() = 2 and
162+
(
163+
substring.getALocalSource().getAPropertyRead("length").flowsTo(call.getArgument(1))
164+
or
165+
substring.asExpr().getStringValue().length() = call.getArgument(1).asExpr().getIntValue()
166+
)
167+
}
168+
169+
override DataFlow::Node getBaseString() {
170+
result = call.getReceiver()
171+
}
172+
173+
override DataFlow::Node getSubstring() {
174+
result = substring
175+
}
176+
177+
override boolean getPolarity() {
178+
result = astNode.getPolarity()
179+
}
180+
}
150181

151182
/**
152183
* A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`.

javascript/ql/test/library-tests/StringOps/StartsWith/StartsWith.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
| tst.js:12:9:12:20 | A.indexOf(B) | tst.js:12:9:12:9 | A | tst.js:12:19:12:19 | B | false |
99
| tst.js:13:10:13:21 | A.indexOf(B) | tst.js:13:10:13:10 | A | tst.js:13:20:13:20 | B | false |
1010
| tst.js:14:11:14:22 | A.indexOf(B) | tst.js:14:11:14:11 | A | tst.js:14:21:14:21 | B | false |
11+
| tst.js:15:9:15:38 | A.subst ... ) === B | tst.js:15:9:15:9 | A | tst.js:15:38:15:38 | B | true |
12+
| tst.js:16:9:16:38 | A.subst ... ) !== B | tst.js:16:9:16:9 | A | tst.js:16:38:16:38 | B | false |
13+
| tst.js:17:9:17:35 | A.subst ... ) === B | tst.js:17:9:17:9 | A | tst.js:17:35:17:35 | B | true |
14+
| tst.js:18:9:18:36 | A.subst ... "web/" | tst.js:18:9:18:9 | A | tst.js:18:31:18:36 | "web/" | true |

javascript/ql/test/library-tests/StringOps/StartsWith/tst.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ function f(A, B) {
1212
if (A.indexOf(B)) {} // !startsWith
1313
if (!A.indexOf(B)) {} // startsWith
1414
if (!!A.indexOf(B)) {} // !startsWith
15+
if (A.substring(0, B.length) === B) {}
16+
if (A.substring(0, B.length) !== B) {}
17+
if (A.substr(0, B.length) === B) {}
18+
if (A.substring(0, 4) === "web/") {}
1519

1620
// non-examples
1721
if (_.startsWith(A, B, 2)) {}
@@ -22,4 +26,5 @@ function f(A, B) {
2226
if (A.indexOf(B, 2) === 0) {}
2327
if (A.indexOf(B, 2)) {}
2428
if (~A.indexOf(B)) {} // checks for existence, not startsWith
29+
if (A.substring(B.length) === 0) {}
2530
}

0 commit comments

Comments
 (0)