Skip to content

Commit adc15ca

Browse files
authored
Merge pull request #574 from xiemaisi/js/avoid-materialisation
Approved by esben-semmle
2 parents 8bd8975 + 9c98aaf commit adc15ca

File tree

2 files changed

+57
-25
lines changed

2 files changed

+57
-25
lines changed

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

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,18 @@ class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
254254
* Gets a return value for a call to this function.
255255
*/
256256
AbstractValue getAReturnValue() {
257-
if astNode.isGenerator() or astNode.isAsync() then
258-
result = TAbstractOtherObject()
259-
else (
260-
// explicit return value
261-
result = astNode.getAReturnedExpr().analyze().getALocalValue()
257+
// explicit return value
258+
result = astNode.getAReturnedExpr().analyze().getALocalValue()
259+
or
260+
// implicit return value
261+
(
262+
// either because execution of the function may terminate normally
263+
mayReturnImplicitly()
262264
or
263-
// implicit return value
264-
(
265-
// either because execution of the function may terminate normally
266-
mayReturnImplicitly()
267-
or
268-
// or because there is a bare `return;` statement
269-
exists (ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))
270-
) and
271-
result = TAbstractUndefined()
272-
)
265+
// or because there is a bare `return;` statement
266+
exists (ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))
267+
) and
268+
result = TAbstractUndefined()
273269
}
274270

275271
/**
@@ -288,5 +284,26 @@ class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
288284
not final instanceof ThrowStmt
289285
)
290286
}
287+
}
288+
289+
/**
290+
* Flow analysis for generator functions.
291+
*/
292+
private class AnalyzedGeneratorFunction extends AnalyzedFunction {
293+
AnalyzedGeneratorFunction() { astNode.isGenerator() }
294+
295+
override AbstractValue getAReturnValue() {
296+
result = TAbstractOtherObject()
297+
}
298+
}
299+
300+
/**
301+
* Flow analysis for async functions.
302+
*/
303+
private class AnalyzedAsyncFunction extends AnalyzedFunction {
304+
AnalyzedAsyncFunction() { astNode.isAsync() }
291305

306+
override AbstractValue getAReturnValue() {
307+
result = TAbstractOtherObject()
308+
}
292309
}

javascript/ql/src/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,7 @@ AbstractValue getAnInitialPropertyValue(DefiniteAbstractValue baseVal, string pr
3939
)
4040
or
4141
// class members
42-
exists (ClassDefinition c, DataFlow::AnalyzedNode init, MemberDefinition m |
43-
m = c.getMember(propertyName) and
44-
not m instanceof AccessorMethodDefinition and
45-
init = m.getInit().analyze() and
46-
result = init.getALocalValue() |
47-
if m.isStatic() then
48-
baseVal = TAbstractClass(c)
49-
else
50-
baseVal = AbstractInstance::of(c)
51-
)
42+
result = getAnInitialMemberValue(getMember(baseVal, propertyName))
5243
or
5344
// object properties
5445
exists (ValueProperty p |
@@ -63,6 +54,30 @@ AbstractValue getAnInitialPropertyValue(DefiniteAbstractValue baseVal, string pr
6354
result = TAbstractInstance(baseVal)
6455
}
6556

57+
/**
58+
* Gets a class member definition that we abstractly represent as a property of `baseVal`
59+
* with the given `name`.
60+
*/
61+
private MemberDefinition getMember(DefiniteAbstractValue baseVal, string name) {
62+
exists (ClassDefinition c | result = c.getMember(name) |
63+
if result.isStatic() then
64+
baseVal = TAbstractClass(c)
65+
else
66+
baseVal = AbstractInstance::of(c)
67+
)
68+
}
69+
70+
/**
71+
* Gets an abstract representation of the initial value of member definition `m`.
72+
*
73+
* For (non-accessor) methods, this is the abstract function corresponding to the
74+
* method. For fields, it is an abstract representation of their initial value(s).
75+
*/
76+
private AbstractValue getAnInitialMemberValue(MemberDefinition m) {
77+
not m instanceof AccessorMethodDefinition and
78+
result = m.getInit().analyze().getALocalValue()
79+
}
80+
6681
/**
6782
* Holds if `baseVal` is an abstract value whose properties we track for the purposes
6883
* of `getALocalValue`.

0 commit comments

Comments
 (0)