Permalink
Browse files

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 <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
  • Loading branch information...
1 parent df8b8b2 commit 8a2a763f13c7a940c7188bfee10556a9a815bb99 @mscdex mscdex committed with evanlucas Dec 19, 2016
Showing with 59 additions and 41 deletions.
  1. +59 −41 lib/_http_common.js
View
@@ -246,44 +246,44 @@ exports.httpSocketSetup = httpSocketSetup;
* so take care when making changes to the implementation so that the source
* code size does not exceed v8's default max_inlined_source_size setting.
**/
-function isValidTokenChar(ch) {
- if (ch >= 94 && ch <= 122)
- return true;
- if (ch >= 65 && ch <= 90)
- return true;
- if (ch === 45)
- return true;
- if (ch >= 48 && ch <= 57)
- return true;
- if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
+var validTokens = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
+ 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, // 112 - 127
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 ...
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // ... 255
+];
+function checkIsHttpToken(val) {
+ if (typeof val !== 'string' || val.length === 0)
+ return false;
+ if (!validTokens[val.charCodeAt(0)])
return false;
- if (ch >= 33 && ch <= 46)
+ if (val.length < 2)
return true;
- if (ch === 124 || ch === 126)
+ if (!validTokens[val.charCodeAt(1)])
+ return false;
+ if (val.length < 3)
return true;
- return false;
-}
-function checkIsHttpToken(val) {
- if (typeof val !== 'string' || val.length === 0)
+ if (!validTokens[val.charCodeAt(2)])
return false;
- if (!isValidTokenChar(val.charCodeAt(0)))
+ if (val.length < 4)
+ return true;
+ if (!validTokens[val.charCodeAt(3)])
return false;
- const len = val.length;
- if (len > 1) {
- if (!isValidTokenChar(val.charCodeAt(1)))
+ for (var i = 4; i < val.length; ++i) {
+ if (!validTokens[val.charCodeAt(i)])
return false;
- if (len > 2) {
- if (!isValidTokenChar(val.charCodeAt(2)))
- return false;
- if (len > 3) {
- if (!isValidTokenChar(val.charCodeAt(3)))
- return false;
- for (var i = 4; i < len; i++) {
- if (!isValidTokenChar(val.charCodeAt(i)))
- return false;
- }
- }
- }
}
return true;
}
@@ -299,26 +299,44 @@ exports._checkIsHttpToken = checkIsHttpToken;
* so take care when making changes to the implementation so that the source
* code size does not exceed v8's default max_inlined_source_size setting.
**/
+var validHdrChars = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, // 0 - 15
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 32 - 47
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 48 - 63
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 95
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 112 - 127
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 128 ...
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
+];
function checkInvalidHeaderChar(val) {
val += '';
if (val.length < 1)
return false;
- var c = val.charCodeAt(0);
- if ((c <= 31 && c !== 9) || c > 255 || c === 127)
+ if (!validHdrChars[val.charCodeAt(0)])
return true;
if (val.length < 2)
return false;
- c = val.charCodeAt(1);
- if ((c <= 31 && c !== 9) || c > 255 || c === 127)
+ if (!validHdrChars[val.charCodeAt(1)])
return true;
if (val.length < 3)
return false;
- c = val.charCodeAt(2);
- if ((c <= 31 && c !== 9) || c > 255 || c === 127)
+ if (!validHdrChars[val.charCodeAt(2)])
+ return true;
+ if (val.length < 4)
+ return false;
+ if (!validHdrChars[val.charCodeAt(3)])
return true;
- for (var i = 3; i < val.length; ++i) {
- c = val.charCodeAt(i);
- if ((c <= 31 && c !== 9) || c > 255 || c === 127)
+ for (var i = 4; i < val.length; ++i) {
+ if (!validHdrChars[val.charCodeAt(i)])
return true;
}
return false;

0 comments on commit 8a2a763

Please sign in to comment.