2424private import javascript
2525private import semmle.javascript.dataflow.internal.DataFlowNode
2626private import semmle.javascript.dataflow.FlowSummary
27+ private import Arrays
2728private import FlowSummaryUtil
2829
2930class At extends SummarizedCallable {
@@ -41,15 +42,18 @@ class At extends SummarizedCallable {
4142}
4243
4344class Concat extends SummarizedCallable {
44- Concat ( ) { this = "Array#concat / String#concat" }
45+ Concat ( ) { this = "Array#concat / String#concat / Buffer.concat " }
4546
4647 override InstanceCall getACallSimple ( ) { result .getMethodName ( ) = "concat" }
4748
4849 override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
50+ // Array#concat.
51+ // Also models Buffer.concat as this happens to out work well with our toString() model.
4952 preservesValue = true and
5053 input = "Argument[this,0..].ArrayElement" and
5154 output = "ReturnValue.ArrayElement"
5255 or
56+ // String#concat
5357 preservesValue = false and
5458 input = "Argument[this,0..]" and
5559 output = "ReturnValue"
@@ -149,3 +153,16 @@ class Values extends SummarizedCallable {
149153 output = "ReturnValue.IteratorElement"
150154 }
151155}
156+
157+ class ToString extends SummarizedCallable {
158+ ToString ( ) { this = "Object#toString / Array#toString" }
159+
160+ override DataFlow:: MethodCallNode getACallSimple ( ) { result .getMethodName ( ) = "toString" }
161+
162+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
163+ preservesValue = false and
164+ // Arrays stringify their contents and joins by ","
165+ input = "Argument[this].ArrayElementDeep" and
166+ output = "ReturnValue"
167+ }
168+ }
0 commit comments