Skip to content

Commit 3b77786

Browse files
committed
JS: Improve resolution of ArrayElement in API graphs
1 parent 5417f58 commit 3b77786

4 files changed

Lines changed: 21 additions & 8 deletions

File tree

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,23 @@ module API {
229229
result = this.getASuccessor(Label::unknownMember())
230230
}
231231

232+
/**
233+
* Gets a node representing an arbitrary array element in the array represented by this node.
234+
*/
235+
cached
236+
Node getArrayElement() {
237+
exists(string s, int n |
238+
result = this.getMember(s) and
239+
s.toInt() = n and
240+
n.toString() = s and // ensure 's' is the canonical integer representation
241+
n >= 0
242+
)
243+
or
244+
result = this.getMember(DataFlow::PseudoProperties::arrayElement())
245+
or
246+
result = this.getUnknownMember()
247+
}
248+
232249
/**
233250
* Gets a node representing a member of this API component where the name of the member may
234251
* or may not be known statically.

javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
162162
token.getName() = "Awaited" and
163163
result = node.getPromised()
164164
or
165-
token.getName() = "ArrayElement" and
166-
result = node.getMember(DataFlow::PseudoProperties::arrayElement())
165+
token.getName() = ["ArrayElement", "Element"] and
166+
result = node.getArrayElement()
167167
or
168168
token.getName() = "Element" and
169169
result = node.getMember(DataFlow::PseudoProperties::arrayLikeElement())
@@ -172,11 +172,6 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
172172
token.getName() = "MapValue" and
173173
result = node.getMember(DataFlow::PseudoProperties::mapValueAll())
174174
or
175-
// Currently we need to include the "unknown member" for ArrayElement and Element since
176-
// API graphs do not use store/load steps for arrays
177-
token.getName() = ["ArrayElement", "Element"] and
178-
result = node.getUnknownMember()
179-
or
180175
token.getName() = "Parameter" and
181176
token.getAnArgument() = "this" and
182177
result = node.getReceiver()

javascript/ql/test/library-tests/frameworks/data/test.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ taintFlow
8181
| test.js:272:6:272:40 | new MyS ... ource() | test.js:272:6:272:40 | new MyS ... ource() |
8282
| test.js:274:6:274:39 | testlib ... eName() | test.js:274:6:274:39 | testlib ... eName() |
8383
| test.js:277:8:277:31 | "danger ... .danger | test.js:277:8:277:31 | "danger ... .danger |
84+
| test.js:284:8:284:16 | source[0] | test.js:284:8:284:16 | source[0] |
8485
isSink
8586
| test.js:54:18:54:25 | source() | test-sink |
8687
| test.js:55:22:55:29 | source() | test-sink |

javascript/ql/test/library-tests/frameworks/data/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,5 +281,5 @@ function dangerConstant() {
281281

282282
function arraySource() {
283283
const source = testlib.getSourceArray();
284-
sink(source[0]); // NOT OK [INCONSISTENCY]
284+
sink(source[0]); // NOT OK
285285
}

0 commit comments

Comments
 (0)