Skip to content

Commit 34cc61e

Browse files
authored
Merge pull request #7083 from asgerf/js/type-track-object-literals-with-methods
Approved by erik-krogh
2 parents b513033 + 7d8284a commit 34cc61e

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

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

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ module CallGraph {
7979
cls.getAClassReference(t.continue()) = result
8080
)
8181
or
82+
exists(DataFlow::ObjectLiteralNode object, string prop |
83+
function = object.getAPropertySource(prop) and
84+
result = getAnObjectLiteralRef(object).getAPropertyRead(prop) and
85+
t.start()
86+
)
87+
or
8288
exists(DataFlow::FunctionNode outer |
8389
result = getAFunctionReference(outer, 0, t.continue()).getAnInvocation() and
8490
locallyReturnedFunction(outer, function)
@@ -197,11 +203,39 @@ module CallGraph {
197203
)
198204
or
199205
exists(DataFlow::ObjectLiteralNode object, string name |
200-
ref = object.getAPropertyRead(name) and
206+
ref = getAnObjectLiteralRef(object).getAPropertyRead(name) and
201207
result = object.getPropertyGetter(name)
202208
or
203-
ref = object.getAPropertyWrite(name) and
209+
ref = getAnObjectLiteralRef(object).getAPropertyWrite(name) and
204210
result = object.getPropertySetter(name)
205211
)
206212
}
213+
214+
private predicate shouldTrackObjectLiteral(DataFlow::ObjectLiteralNode node) {
215+
(
216+
node.getAPropertySource() instanceof DataFlow::FunctionNode
217+
or
218+
exists(node.getPropertyGetter(_))
219+
or
220+
exists(node.getPropertySetter(_))
221+
) and
222+
not node.getTopLevel().isExterns()
223+
}
224+
225+
/**
226+
* Gets a step summary for tracking object literals.
227+
*
228+
* To avoid false flow from callbacks passed in via "named parameters", we only track object
229+
* literals out of returns, not into calls.
230+
*/
231+
private StepSummary objectLiteralStep() { result = LevelStep() or result = ReturnStep() }
232+
233+
/** Gets a node that refers to the given object literal, via a limited form of type tracking. */
234+
cached
235+
DataFlow::SourceNode getAnObjectLiteralRef(DataFlow::ObjectLiteralNode node) {
236+
shouldTrackObjectLiteral(node) and
237+
result = node
238+
or
239+
StepSummary::step(getAnObjectLiteralRef(node), result, objectLiteralStep())
240+
}
207241
}

0 commit comments

Comments
 (0)