Skip to content

Commit 352924f

Browse files
committed
JS: Handle a few other stringification contexts
1 parent 33ab7db commit 352924f

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,23 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
14321432
c = ContentSet::arrayElementLowerBound(pos.asPositionalLowerBound())
14331433
)
14341434
)
1435+
or
1436+
// Implicitly read array elements before stringification
1437+
stringifiedNode(node1) and
1438+
node2 = node1 and
1439+
c = ContentSet::arrayElement()
1440+
}
1441+
1442+
private predicate stringifiedNode(Node node) {
1443+
exists(Expr e | node = TValueNode(e) |
1444+
e = any(AddExpr add).getAnOperand() and
1445+
not e instanceof StringLiteral
1446+
or
1447+
e = any(TemplateLiteral t).getAnElement() and
1448+
not e instanceof TemplateElement
1449+
)
1450+
or
1451+
node = DataFlow::globalVarRef("String").getAnInvocation().getArgument(0)
14351452
}
14361453

14371454
/** Gets the post-update node for which `node` is the corresponding pre-update node. */

javascript/ql/test/library-tests/TripleDot/arrays.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ function implicitToString() {
2525
const array = [source('implicitToString.1')];
2626
array.push(source('implicitToString.2'))
2727

28-
sink(array + "foo"); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
29-
sink("foo" + array); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
30-
sink("" + array); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
31-
sink(array + 1); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
32-
sink(1 + array); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
33-
sink(unknown() + array); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
34-
sink(array + unknown()); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
35-
36-
sink(`${array}`); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
37-
sink(`${array} foo`); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
38-
39-
sink(String(array)); // $ MISSING: hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
28+
sink(array + "foo"); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
29+
sink("foo" + array); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
30+
sink("" + array); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
31+
sink(array + 1); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
32+
sink(1 + array); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
33+
sink(unknown() + array); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
34+
sink(array + unknown()); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
35+
36+
sink(`${array}`); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
37+
sink(`${array} foo`); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
38+
39+
sink(String(array)); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
4040

4141
sink(array.toString()); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2
4242
sink(array.toString("utf8")); // $ hasTaintFlow=implicitToString.1 hasTaintFlow=implicitToString.2

0 commit comments

Comments
 (0)