Skip to content

Commit ba894e2

Browse files
authored
Merge pull request github#11146 from mbaluda-org/main
JS: Improved Hapi support
2 parents a6f6936 + a7dc29b commit ba894e2

File tree

4 files changed

+157
-4
lines changed

4 files changed

+157
-4
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,28 @@ module Hapi {
99
/**
1010
* An expression that creates a new Hapi server.
1111
*/
12-
class ServerDefinition extends Http::Servers::StandardServerDefinition, DataFlow::NewNode {
12+
class ServerDefinition extends Http::Servers::StandardServerDefinition, DataFlow::Node {
1313
ServerDefinition() {
1414
// `server = new Hapi.Server()`
1515
this = DataFlow::moduleMember("hapi", "Server").getAnInstantiation()
16+
or
17+
// `server = Glue.compose(manifest, composeOptions)`
18+
this = DataFlow::moduleMember("@hapi/glue", "compose").getAnInvocation()
19+
or
20+
// `register (server, options)`
21+
// `module.exports.plugin = {register, pkg};`
22+
this =
23+
any(Module m)
24+
.getAnExportedValue("plugin")
25+
.getALocalSource()
26+
.getAPropertySource("register")
27+
.getAFunctionValue()
28+
.getParameter(0)
29+
or
30+
// `const after = function (server) {...};`
31+
// `server.dependency('name', after);`
32+
this =
33+
any(ServerDefinition s).ref().getAMethodCall("dependency").getABoundCallbackParameter(1, 0)
1634
}
1735
}
1836

@@ -123,15 +141,15 @@ module Hapi {
123141
kind = "parameter" and
124142
exists(DataFlow::PropRead query |
125143
// `request.query.name`
126-
query.accesses(request, "query") and
144+
query.accesses(request, ["query", "params"]) and
127145
this.(DataFlow::PropRead).accesses(query, _)
128146
)
129147
or
130148
exists(DataFlow::PropRead url |
131149
// `request.url.path`
132150
kind = "url" and
133151
url.accesses(request, "url") and
134-
this.(DataFlow::PropRead).accesses(url, "path")
152+
this.(DataFlow::PropRead).accesses(url, ["path", "origin"])
135153
)
136154
or
137155
exists(DataFlow::PropRead state |
@@ -209,6 +227,17 @@ module Hapi {
209227
// server.ext('/', fun)
210228
this.getMethodName() = "ext" and
211229
handler = this.getArgument(1)
230+
or
231+
// server.route([{ handler(request){}])
232+
this.getMethodName() = "route" and
233+
handler =
234+
this.getArgument(0)
235+
.getALocalSource()
236+
.(DataFlow::ArrayCreationNode)
237+
.getAnElement()
238+
.getALocalSource()
239+
.getAPropertySource("handler")
240+
.getAFunctionValue()
212241
)
213242
}
214243

@@ -240,7 +269,7 @@ module Hapi {
240269
RouteHandlerCandidate() {
241270
exists(string request, string responseToolkit |
242271
(request = "request" or request = "req") and
243-
responseToolkit = "h" and
272+
responseToolkit = ["h", "hapi"] and
244273
// heuristic: parameter names match the Hapi documentation
245274
astNode.getNumParameter() = 2 and
246275
astNode.getParameter(0).getName() = request and
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Added support for @hapi/glue and Hapi plugins to the frameworks/Hapi.qll library.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
var server1 = new (require('@hapi/glue')).compose(require("./manifest"), composeOptions); // test_ServerDefinition
2+
3+
var Hapi = require('@hapi/glue');
4+
var server2 = new Hapi.compose(require("./manifest"), composeOptions); // test_ServerDefinition
5+
6+
function handler1(){} // HTTP::RouteHandler
7+
server2.route({
8+
handler: handler1
9+
});
10+
11+
12+
server2.route({
13+
handler: function handler2(request, reply){ // HTTP::RouteHandler
14+
request.response.header('HEADER1', '') // HTTP::HeaderDefinition
15+
}});
16+
17+
server2.ext('onPreResponse', function handler3(request, reply) { // HTTP::RouteHandler
18+
})
19+
20+
function handler4(request, reply){
21+
request.rawPayload;
22+
request.payload.foo;
23+
request.query.bar;
24+
request.params.bar;
25+
request.url.path;
26+
request.url.origin;
27+
request.headers.baz;
28+
request.state.token;
29+
}
30+
var route = {handler: handler4};
31+
server2.route(route);
32+
33+
server2.cache({ segment: 'countries', expiresIn: 60*60*1000 });
34+
35+
function getHandler() {
36+
return function (req, hapi){}
37+
}
38+
server2.route({handler: getHandler()});
39+
40+
function after(server) {
41+
};
42+
43+
function register(server, options) {// test_ServerDefinition
44+
server.dependency(options.dependencies, server_ => after(server_, options)); // test_ServerDefinition
45+
}
46+
47+
module.exports.plugin = {
48+
register,
49+
pkg
50+
};

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,62 @@ test_RouteSetup
44
| src/hapi.js:17:1:18:2 | server2 ... dler\\n}) |
55
| src/hapi.js:29:1:29:20 | server2.route(route) |
66
| src/hapi.js:36:1:36:38 | server2 ... ler()}) |
7+
| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) |
8+
| src/hapiglue.js:12:1:15:7 | server2 ... }}) |
9+
| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) |
10+
| src/hapiglue.js:31:1:31:20 | server2.route(route) |
11+
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) |
712
test_RequestInputAccess
813
| src/hapi.js:21:3:21:20 | request.rawPayload | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
914
| src/hapi.js:22:3:22:21 | request.payload.foo | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
1015
| src/hapi.js:23:3:23:19 | request.query.bar | parameter | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
1116
| src/hapi.js:24:3:24:18 | request.url.path | url | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
1217
| src/hapi.js:25:3:25:21 | request.headers.baz | header | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
1318
| src/hapi.js:26:3:26:21 | request.state.token | cookie | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
19+
| src/hapiglue.js:21:3:21:20 | request.rawPayload | body | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
20+
| src/hapiglue.js:22:3:22:21 | request.payload.foo | body | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
21+
| src/hapiglue.js:23:3:23:19 | request.query.bar | parameter | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
22+
| src/hapiglue.js:24:3:24:20 | request.params.bar | parameter | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
23+
| src/hapiglue.js:25:3:25:18 | request.url.path | url | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
24+
| src/hapiglue.js:26:3:26:20 | request.url.origin | url | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
25+
| src/hapiglue.js:27:3:27:21 | request.headers.baz | header | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
26+
| src/hapiglue.js:28:3:28:21 | request.state.token | cookie | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
1427
test_RouteHandler_getAResponseHeader
1528
| src/hapi.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapi.js:14:9:14:46 | request ... 1', '') |
29+
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapiglue.js:14:9:14:46 | request ... 1', '') |
1630
test_HeaderDefinition_defines
1731
| src/hapi.js:14:9:14:46 | request ... 1', '') | header1 | |
32+
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 | |
1833
test_ResponseExpr
1934
| src/hapi.js:14:9:14:24 | request.response | src/hapi.js:13:14:15:5 | functio ... n\\n } |
35+
| src/hapiglue.js:14:9:14:24 | request.response | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
2036
test_HeaderDefinition
2137
| src/hapi.js:14:9:14:46 | request ... 1', '') | src/hapi.js:13:14:15:5 | functio ... n\\n } |
38+
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
2239
test_RouteSetup_getServer
2340
| src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
2441
| src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
2542
| src/hapi.js:17:1:18:2 | server2 ... dler\\n}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
2643
| src/hapi.js:29:1:29:20 | server2.route(route) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
2744
| src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:4:15:4:31 | new Hapi.Server() |
45+
| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
46+
| src/hapiglue.js:12:1:15:7 | server2 ... }}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
47+
| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
48+
| src/hapiglue.js:31:1:31:20 | server2.route(route) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
49+
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
2850
test_HeaderDefinition_getAHeaderName
2951
| src/hapi.js:14:9:14:46 | request ... 1', '') | header1 |
52+
| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 |
3053
test_ServerDefinition
3154
| src/hapi.js:1:15:1:44 | new (re ... erver() |
3255
| src/hapi.js:4:15:4:31 | new Hapi.Server() |
56+
| src/hapiglue.js:1:15:1:88 | new (re ... ptions) |
57+
| src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
58+
| src/hapiglue.js:43:19:43:24 | server |
59+
| src/hapiglue.js:44:45:44:51 | server_ |
3360
test_HeaderAccess
3461
| src/hapi.js:25:3:25:21 | request.headers.baz | baz |
62+
| src/hapiglue.js:27:3:27:21 | request.headers.baz | baz |
3563
test_RouteSetup_getARouteHandler
3664
| src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:6:1:6:21 | functio ... er1(){} |
3765
| src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:13:14:15:5 | functio ... n\\n } |
@@ -40,12 +68,24 @@ test_RouteSetup_getARouteHandler
4068
| src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:33:1:35:1 | return of function getHandler |
4169
| src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:34:12:34:30 | function (req, h){} |
4270
| src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:36:25:36:36 | getHandler() |
71+
| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapiglue.js:6:1:6:21 | functio ... er1(){} |
72+
| src/hapiglue.js:12:1:15:7 | server2 ... }}) | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
73+
| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} |
74+
| src/hapiglue.js:31:1:31:20 | server2.route(route) | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
75+
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:35:1:37:1 | return of function getHandler |
76+
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:36:12:36:33 | functio ... hapi){} |
77+
| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:38:25:38:36 | getHandler() |
4378
test_RouteHandler
4479
| src/hapi.js:6:1:6:21 | functio ... er1(){} | src/hapi.js:4:15:4:31 | new Hapi.Server() |
4580
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:4:15:4:31 | new Hapi.Server() |
4681
| src/hapi.js:17:30:18:1 | functio ... ndler\\n} | src/hapi.js:4:15:4:31 | new Hapi.Server() |
4782
| src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:4:15:4:31 | new Hapi.Server() |
4883
| src/hapi.js:34:12:34:30 | function (req, h){} | src/hapi.js:4:15:4:31 | new Hapi.Server() |
84+
| src/hapiglue.js:6:1:6:21 | functio ... er1(){} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
85+
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
86+
| src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
87+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
88+
| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) |
4989
test_RequestExpr
5090
| src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } |
5191
| src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } |
@@ -60,6 +100,21 @@ test_RequestExpr
60100
| src/hapi.js:25:3:25:9 | request | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
61101
| src/hapi.js:26:3:26:9 | request | src/hapi.js:20:1:27:1 | functio ... oken;\\n} |
62102
| src/hapi.js:34:22:34:24 | req | src/hapi.js:34:12:34:30 | function (req, h){} |
103+
| src/hapiglue.js:13:32:13:38 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
104+
| src/hapiglue.js:13:32:13:38 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
105+
| src/hapiglue.js:14:9:14:15 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } |
106+
| src/hapiglue.js:17:48:17:54 | request | src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} |
107+
| src/hapiglue.js:20:19:20:25 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
108+
| src/hapiglue.js:20:19:20:25 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
109+
| src/hapiglue.js:21:3:21:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
110+
| src/hapiglue.js:22:3:22:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
111+
| src/hapiglue.js:23:3:23:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
112+
| src/hapiglue.js:24:3:24:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
113+
| src/hapiglue.js:25:3:25:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
114+
| src/hapiglue.js:26:3:26:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
115+
| src/hapiglue.js:27:3:27:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
116+
| src/hapiglue.js:28:3:28:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} |
117+
| src/hapiglue.js:36:22:36:24 | req | src/hapiglue.js:36:12:36:33 | functio ... hapi){} |
63118
test_RouteHandler_getARequestExpr
64119
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request |
65120
| src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request |
@@ -74,3 +129,18 @@ test_RouteHandler_getARequestExpr
74129
| src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:25:3:25:9 | request |
75130
| src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:26:3:26:9 | request |
76131
| src/hapi.js:34:12:34:30 | function (req, h){} | src/hapi.js:34:22:34:24 | req |
132+
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:13:32:13:38 | request |
133+
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:13:32:13:38 | request |
134+
| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:14:9:14:15 | request |
135+
| src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | src/hapiglue.js:17:48:17:54 | request |
136+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:20:19:20:25 | request |
137+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:20:19:20:25 | request |
138+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:21:3:21:9 | request |
139+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:22:3:22:9 | request |
140+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:23:3:23:9 | request |
141+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:24:3:24:9 | request |
142+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:25:3:25:9 | request |
143+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:26:3:26:9 | request |
144+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:27:3:27:9 | request |
145+
| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:28:3:28:9 | request |
146+
| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:36:22:36:24 | req |

0 commit comments

Comments
 (0)