Skip to content

Commit 3728e1a

Browse files
authored
Merge pull request github#3715 from asger-semmle/js/returned-functions
Approved by erik-krogh, esbena
2 parents 3520f2c + 17010e2 commit 3728e1a

File tree

5 files changed

+48
-2
lines changed

5 files changed

+48
-2
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ module CallGraph {
6161
function = cls.getConstructor() and
6262
cls.getAClassReference(t.continue()).flowsTo(result)
6363
)
64+
or
65+
imprecision = 0 and
66+
exists(DataFlow::FunctionNode outer |
67+
result = getAFunctionReference(outer, 0, t.continue()).getAnInvocation() and
68+
locallyReturnedFunction(outer, function)
69+
)
70+
}
71+
72+
cached
73+
private predicate locallyReturnedFunction(
74+
DataFlow::FunctionNode outer, DataFlow::FunctionNode inner
75+
) {
76+
inner.flowsTo(outer.getAReturn())
6477
}
6578

6679
/**

javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int
6666

6767
query predicate badAnnotation(string name) {
6868
name = any(AnnotatedCall cl).getCallTargetName() and
69-
not name = any(AnnotatedFunction cl).getCalleeName()
69+
not name = any(AnnotatedFunction cl).getCalleeName() and
70+
name != "NONE"
7071
or
7172
not name = any(AnnotatedCall cl).getCallTargetName() and
7273
name = any(AnnotatedFunction cl).getCalleeName()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import 'dummy';
2+
3+
/** name:curry1 */
4+
function curry1() {
5+
/** name:curry2 */
6+
function curry2(x) {
7+
/** name:curry3 */
8+
function curry3(y) {
9+
10+
}
11+
return curry3;
12+
}
13+
return curry2;
14+
};
15+
16+
/** calls:curry1 */
17+
let r1 = curry1();
18+
19+
/** calls:curry2 */
20+
let r2 = r1();
21+
22+
/** calls:curry3 */
23+
r2();
24+
25+
function callback(f) {
26+
// Call graph should not include callback invocations.
27+
/** calls:NONE */
28+
f();
29+
}
30+
31+
let w1 = callback(curry1);
32+
callback(() => {});

javascript/ql/test/library-tests/frameworks/HTTP-heuristics/RouteHandler.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| src/handler-in-property.js:12:18:12:37 | function(req, res){} |
1616
| src/middleware-attacher-getter.js:4:17:4:36 | function(req, res){} |
1717
| src/middleware-attacher-getter.js:19:19:19:38 | function(req, res){} |
18+
| src/middleware-attacher-getter.js:29:32:29:51 | function(req, res){} |
1819
| src/middleware-attacher.js:3:13:3:32 | function(req, res){} |
1920
| src/nodejs.js:3:19:3:38 | function(req, res){} |
2021
| src/nodejs.js:8:14:8:33 | function(req, res){} |

javascript/ql/test/library-tests/frameworks/HTTP-heuristics/UnpromotedRouteHandlerCandidate.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
| src/bound-handler.js:9:12:9:31 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
33
| src/hapi.js:1:1:1:30 | functio ... t, h){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
44
| src/iterated-handlers.js:4:2:4:22 | functio ... res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
5-
| src/middleware-attacher-getter.js:29:32:29:51 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
65
| src/route-objects.js:7:19:7:38 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
76
| src/route-objects.js:8:12:10:5 | (req, res) {\\n\\n } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
87
| src/route-objects.js:20:16:22:9 | (req, r ... } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |

0 commit comments

Comments
 (0)