Skip to content

Commit 19e5db7

Browse files
author
Esben Sparre Andreasen
committed
JS: make AnalyzedFunction public and move getAReturnValue there
1 parent ac947f1 commit 19e5db7

File tree

3 files changed

+57
-57
lines changed

3 files changed

+57
-57
lines changed

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,52 @@ class AnalyzedModule extends TopLevel {
239239
)
240240
}
241241
}
242+
243+
/**
244+
* Flow analysis for functions.
245+
*/
246+
class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
247+
override Function astNode;
248+
249+
override AbstractValue getALocalValue() { result = TAbstractFunction(astNode) }
250+
251+
/**
252+
* Gets a return value for a call to this function.
253+
*/
254+
AbstractValue getAReturnValue() {
255+
if astNode.isGenerator() or astNode.isAsync() then
256+
result = TAbstractOtherObject()
257+
else (
258+
// explicit return value
259+
result = astNode.getAReturnedExpr().analyze().getALocalValue()
260+
or
261+
// implicit return value
262+
(
263+
// either because execution of the function may terminate normally
264+
mayReturnImplicitly()
265+
or
266+
// or because there is a bare `return;` statement
267+
exists (ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))
268+
) and
269+
result = TAbstractUndefined()
270+
)
271+
}
272+
273+
/**
274+
* Holds if the execution of this function may complete normally without
275+
* encountering a `return` or `throw` statement.
276+
*
277+
* Note that this is an overapproximation, that is, the predicate may hold
278+
* of functions that cannot actually complete normally, since it does not
279+
* account for `finally` blocks and does not check reachability.
280+
*/
281+
private predicate mayReturnImplicitly() {
282+
exists (ConcreteControlFlowNode final |
283+
final.getContainer() = astNode and
284+
final.isAFinalNode() and
285+
not final instanceof ReturnStmt and
286+
not final instanceof ThrowStmt
287+
)
288+
}
289+
290+
}

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,6 @@ private class AnalyzedArrayComprehensionExpr extends DataFlow::AnalyzedValueNode
8989
override AbstractValue getALocalValue() { result = TAbstractOtherObject() }
9090
}
9191

92-
/**
93-
* Flow analysis for functions.
94-
*/
95-
private class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
96-
override Function astNode;
97-
98-
override AbstractValue getALocalValue() { result = TAbstractFunction(astNode) }
99-
}
100-
10192
/**
10293
* Flow analysis for class declarations.
10394
*/

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

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -127,59 +127,19 @@ private class AnalyzedThisInPropertyFunction extends AnalyzedThisExpr {
127127
}
128128
}
129129

130-
/**
131-
* Holds if the execution of function `f` may complete normally without
132-
* encountering a `return` or `throw` statement.
133-
*
134-
* Note that this is an overapproximation, that is, the predicate may hold
135-
* of functions that cannot actually complete normally, since it does not
136-
* account for `finally` blocks and does not check reachability.
137-
*/
138-
predicate mayReturnImplicitly(Function f) {
139-
exists (ConcreteControlFlowNode final |
140-
final.getContainer() = f and
141-
final.isAFinalNode() and
142-
not final instanceof ReturnStmt and
143-
not final instanceof ThrowStmt
144-
)
145-
}
146-
147130
/**
148131
* A call with inter-procedural type inference for the return value.
149132
*/
150-
abstract class CallWithAnalyzedReturnFlow extends DataFlow::CallNode, DataFlow::AnalyzedValueNode {
133+
abstract class CallWithAnalyzedReturnFlow extends DataFlow::AnalyzedValueNode {
151134

152135
/**
153136
* Gets a called function.
154137
*/
155-
abstract Function getAFunction();
156-
157-
/**
158-
* Gets a return value for this call.
159-
*/
160-
AbstractValue getAReturnValue() {
161-
exists (Function f | f = getAFunction() |
162-
if f.isGenerator() or f.isAsync() then
163-
result = TAbstractOtherObject()
164-
else (
165-
// explicit return value
166-
result = f.getAReturnedExpr().analyze().getALocalValue()
167-
or
168-
// implicit return value
169-
(
170-
// either because execution of the function may terminate normally
171-
mayReturnImplicitly(f)
172-
or
173-
// or because there is a bare `return;` statement
174-
exists (ReturnStmt ret | ret = f.getAReturnStmt() | not exists(ret.getExpr()))
175-
) and
176-
result = TAbstractUndefined()
177-
)
178-
)
179-
}
138+
abstract AnalyzedFunction getACallee();
180139

181140
override AbstractValue getALocalValue() {
182-
result = getAReturnValue()
141+
result = getACallee().getAReturnValue() and
142+
not this instanceof DataFlow::NewNode
183143
}
184144
}
185145

@@ -194,8 +154,8 @@ private class IIFEWithAnalyzedReturnFlow extends CallWithAnalyzedReturnFlow {
194154
astNode = iife.getInvocation()
195155
}
196156

197-
override Function getAFunction() {
198-
result = iife
157+
override AnalyzedFunction getACallee() {
158+
result = iife.analyze()
199159
}
200160

201161
}
@@ -238,8 +198,8 @@ private class LocalFunctionCallWithAnalyzedReturnFlow extends CallWithAnalyzedRe
238198
this = f.getAnInvocation()
239199
}
240200

241-
override Function getAFunction() {
242-
result = f
201+
override AnalyzedFunction getACallee() {
202+
result = f.analyze()
243203
}
244204

245205
}

0 commit comments

Comments
 (0)