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

Skip to content

Commit b662699

Browse files
committed
JS: bugfix in indexOf-based include test
1 parent d603824 commit b662699

7 files changed

Lines changed: 72 additions & 2 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,15 @@ module StringOps {
250250
polarity = true and
251251
greater = indexOf and
252252
(
253-
lesser.getIntValue() >= 0
253+
lesser.getIntValue() = 0 and astNode.isInclusive()
254254
or
255255
lesser.getIntValue() = -1 and not astNode.isInclusive()
256256
)
257257
or
258258
polarity = false and
259259
lesser = indexOf and
260260
(
261-
greater.getIntValue() = -1
261+
greater.getIntValue() = -1 and astNode.isInclusive()
262262
or
263263
greater.getIntValue() = 0 and not astNode.isInclusive()
264264
)

javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,31 @@ module TaintTracking {
688688
override predicate appliesTo(Configuration cfg) { any() }
689689
}
690690

691+
/**
692+
* A check of form `x.indexOf(y) > 0` or similar, which sanitizes `y` in the "then" branch.
693+
*
694+
* The more typical case of `x.indexOf(y) >= 0` is covered by `StringInclusionSanitizer`.
695+
*/
696+
class PositiveIndexOfSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
697+
MethodCallExpr indexOf;
698+
override RelationalComparison astNode;
699+
700+
PositiveIndexOfSanitizer() {
701+
indexOf.getMethodName() = "indexOf" and
702+
exists (int bound |
703+
astNode.getGreaterOperand() = indexOf and
704+
astNode.getLesserOperand().getIntValue() = bound and
705+
bound >= 0)
706+
}
707+
708+
override predicate sanitizes(boolean outcome, Expr e) {
709+
outcome = true and
710+
e = indexOf.getArgument(0)
711+
}
712+
713+
override predicate appliesTo(Configuration cfg) { any() }
714+
}
715+
691716
/** A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch. */
692717
class ConstantComparison extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
693718
Expr x;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
| tst.js:4:7:4:19 | A.includes(B) | tst.js:4:7:4:7 | A | tst.js:4:18:4:18 | B | true |
2+
| tst.js:5:7:5:22 | _.includes(A, B) | tst.js:5:18:5:18 | A | tst.js:5:21:5:21 | B | true |
3+
| tst.js:6:7:6:25 | A.indexOf(B) !== -1 | tst.js:6:7:6:7 | A | tst.js:6:17:6:17 | B | true |
4+
| tst.js:7:7:7:23 | A.indexOf(B) >= 0 | tst.js:7:7:7:7 | A | tst.js:7:17:7:17 | B | true |
5+
| tst.js:8:7:8:19 | ~A.indexOf(B) | tst.js:8:8:8:8 | A | tst.js:8:18:8:18 | B | true |
6+
| tst.js:11:7:11:25 | A.indexOf(B) === -1 | tst.js:11:7:11:7 | A | tst.js:11:17:11:17 | B | false |
7+
| tst.js:12:7:12:22 | A.indexOf(B) < 0 | tst.js:12:7:12:7 | A | tst.js:12:17:12:17 | B | false |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from StringOps::Includes include
4+
select include, include.getBaseString(), include.getSubstring(), include.getPolarity()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as _ from 'lodash';
2+
3+
function test() {
4+
if (A.includes(B)) {}
5+
if (_.includes(A, B)) {}
6+
if (A.indexOf(B) !== -1) {}
7+
if (A.indexOf(B) >= 0) {}
8+
if (~A.indexOf(B)) {}
9+
10+
// negated
11+
if (A.indexOf(B) === -1) {}
12+
if (A.indexOf(B) < 0) {}
13+
14+
// non-examples
15+
if (A.indexOf(B) === 0) {}
16+
if (A.indexOf(B) !== 0) {}
17+
if (A.indexOf(B) > 0) {}
18+
}

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| constructor-calls.js:10:16:10:23 | source() | constructor-calls.js:30:8:30:19 | d_safe.taint |
66
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:17:8:17:14 | c.param |
77
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:25:8:25:14 | d.param |
8+
| indexOf.js:4:11:4:18 | source() | indexOf.js:9:10:9:10 | x |
89
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:17:14:17:14 | x |
910
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:20:14:20:14 | y |
1011
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value |
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
let whitelist = ['a', 'b', 'c'];
2+
3+
function test() {
4+
let x = source();
5+
6+
if (whitelist.indexOf(x) < -1) {
7+
// unreachable
8+
} else {
9+
sink(x); // NOT OK
10+
}
11+
12+
if (whitelist.indexOf(x) > 1) {
13+
sink(x) // OK
14+
}
15+
}

0 commit comments

Comments
 (0)