Skip to content

Commit 8a2a763

Browse files
mscdexevanlucas
authored andcommitted
http: improve validation performance
The new table-based lookups perform significantly better for the common cases (checking latin1 characters). PR-URL: #6533 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent df8b8b2 commit 8a2a763

File tree

1 file changed

+59
-41
lines changed

1 file changed

+59
-41
lines changed

lib/_http_common.js

+59-41
Original file line numberDiff line numberDiff line change
@@ -246,44 +246,44 @@ exports.httpSocketSetup = httpSocketSetup;
246246
* so take care when making changes to the implementation so that the source
247247
* code size does not exceed v8's default max_inlined_source_size setting.
248248
**/
249-
function isValidTokenChar(ch) {
250-
if (ch >= 94 && ch <= 122)
251-
return true;
252-
if (ch >= 65 && ch <= 90)
253-
return true;
254-
if (ch === 45)
255-
return true;
256-
if (ch >= 48 && ch <= 57)
257-
return true;
258-
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
249+
var validTokens = [
250+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
251+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
252+
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
253+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
254+
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
255+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
256+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
257+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112 - 127
258+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 ...
259+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // ... 255
266+
];
267+
function checkIsHttpToken(val) {
268+
if (typeof val !== 'string' || val.length === 0)
269+
return false;
270+
if (!validTokens[val.charCodeAt(0)])
259271
return false;
260-
if (ch >= 33 && ch <= 46)
272+
if (val.length < 2)
261273
return true;
262-
if (ch === 124 || ch === 126)
274+
if (!validTokens[val.charCodeAt(1)])
275+
return false;
276+
if (val.length < 3)
263277
return true;
264-
return false;
265-
}
266-
function checkIsHttpToken(val) {
267-
if (typeof val !== 'string' || val.length === 0)
278+
if (!validTokens[val.charCodeAt(2)])
268279
return false;
269-
if (!isValidTokenChar(val.charCodeAt(0)))
280+
if (val.length < 4)
281+
return true;
282+
if (!validTokens[val.charCodeAt(3)])
270283
return false;
271-
const len = val.length;
272-
if (len > 1) {
273-
if (!isValidTokenChar(val.charCodeAt(1)))
284+
for (var i = 4; i < val.length; ++i) {
285+
if (!validTokens[val.charCodeAt(i)])
274286
return false;
275-
if (len > 2) {
276-
if (!isValidTokenChar(val.charCodeAt(2)))
277-
return false;
278-
if (len > 3) {
279-
if (!isValidTokenChar(val.charCodeAt(3)))
280-
return false;
281-
for (var i = 4; i < len; i++) {
282-
if (!isValidTokenChar(val.charCodeAt(i)))
283-
return false;
284-
}
285-
}
286-
}
287287
}
288288
return true;
289289
}
@@ -299,26 +299,44 @@ exports._checkIsHttpToken = checkIsHttpToken;
299299
* so take care when making changes to the implementation so that the source
300300
* code size does not exceed v8's default max_inlined_source_size setting.
301301
**/
302+
var validHdrChars = [
303+
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
304+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
305+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
306+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
307+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
308+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
309+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
310+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
311+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
312+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
313+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
314+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
315+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
316+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
317+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
318+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
319+
];
302320
function checkInvalidHeaderChar(val) {
303321
val += '';
304322
if (val.length < 1)
305323
return false;
306-
var c = val.charCodeAt(0);
307-
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
324+
if (!validHdrChars[val.charCodeAt(0)])
308325
return true;
309326
if (val.length < 2)
310327
return false;
311-
c = val.charCodeAt(1);
312-
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
328+
if (!validHdrChars[val.charCodeAt(1)])
313329
return true;
314330
if (val.length < 3)
315331
return false;
316-
c = val.charCodeAt(2);
317-
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
332+
if (!validHdrChars[val.charCodeAt(2)])
333+
return true;
334+
if (val.length < 4)
335+
return false;
336+
if (!validHdrChars[val.charCodeAt(3)])
318337
return true;
319-
for (var i = 3; i < val.length; ++i) {
320-
c = val.charCodeAt(i);
321-
if ((c <= 31 && c !== 9) || c > 255 || c === 127)
338+
for (var i = 4; i < val.length; ++i) {
339+
if (!validHdrChars[val.charCodeAt(i)])
322340
return true;
323341
}
324342
return false;

0 commit comments

Comments
 (0)