Skip to content

Commit

Permalink
url: reduce deplicated codes in autoEscapeStr
Browse files Browse the repository at this point in the history
PR-URL: nodejs#18613
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
starkwang authored and MayaLekova committed May 8, 2018
1 parent b1b52f6 commit be4a1ea
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 87 deletions.
22 changes: 22 additions & 0 deletions benchmark/url/url-parse.js
@@ -0,0 +1,22 @@
'use strict';
const common = require('../common.js');
const url = require('url');

const inputs = {
normal: 'http://foo.com/bar',
escaped: 'https://foo.bar/{}^`/abcd'
};

const bench = common.createBenchmark(main, {
type: Object.keys(inputs),
n: [1e7]
});

function main({ type, n }) {
const input = inputs[type] || '';

bench.start();
for (var i = 0; i < n; i += 1)
url.parse(input);
bench.end(n);
}
112 changes: 25 additions & 87 deletions lib/url.js
Expand Up @@ -439,101 +439,39 @@ function validateHostname(self, rest, hostname) {
}
}

// Escaped characters. Use empty strings to fill up unused entries.
// Using Array is faster than Object/Map
const escapedCodes = [
/*0 - 9*/ '', '', '', '', '', '', '', '', '', '%09',
/*10 - 19*/ '%0A', '', '', '%0D', '', '', '', '', '', '',
/*20 - 29*/ '', '', '', '', '', '', '', '', '', '',
/*30 - 39*/ '', '', '%20', '', '%22', '', '', '', '', '%27',
/*40 - 49*/ '', '', '', '', '', '', '', '', '', '',
/*50 - 59*/ '', '', '', '', '', '', '', '', '', '',
/*60 - 69*/ '%3C', '', '%3E', '', '', '', '', '', '', '',
/*70 - 79*/ '', '', '', '', '', '', '', '', '', '',
/*80 - 89*/ '', '', '', '', '', '', '', '', '', '',
/*90 - 99*/ '', '', '%5C', '', '%5E', '', '%60', '', '', '',
/*100 - 109*/ '', '', '', '', '', '', '', '', '', '',
/*110 - 119*/ '', '', '', '', '', '', '', '', '', '',
/*120 - 125*/ '', '', '', '%7B', '%7C', '%7D'
];

// Automatically escape all delimiters and unwise characters from RFC 2396.
// Also escape single quotes in case of an XSS attack.
// Return the escaped string.
function autoEscapeStr(rest) {
var escaped = '';
var lastEscapedPos = 0;
for (var i = 0; i < rest.length; ++i) {
// Manual switching is faster than using a Map/Object.
// `escaped` contains substring up to the last escaped character.
switch (rest.charCodeAt(i)) {
case 9: // '\t'
// Concat if there are ordinary characters in the middle.
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%09';
lastEscapedPos = i + 1;
break;
case 10: // '\n'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%0A';
lastEscapedPos = i + 1;
break;
case 13: // '\r'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%0D';
lastEscapedPos = i + 1;
break;
case 32: // ' '
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%20';
lastEscapedPos = i + 1;
break;
case 34: // '"'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%22';
lastEscapedPos = i + 1;
break;
case 39: // '\''
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%27';
lastEscapedPos = i + 1;
break;
case 60: // '<'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%3C';
lastEscapedPos = i + 1;
break;
case 62: // '>'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%3E';
lastEscapedPos = i + 1;
break;
case 92: // '\\'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%5C';
lastEscapedPos = i + 1;
break;
case 94: // '^'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%5E';
lastEscapedPos = i + 1;
break;
case 96: // '`'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%60';
lastEscapedPos = i + 1;
break;
case 123: // '{'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%7B';
lastEscapedPos = i + 1;
break;
case 124: // '|'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%7C';
lastEscapedPos = i + 1;
break;
case 125: // '}'
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += '%7D';
lastEscapedPos = i + 1;
break;
var escapedChar = escapedCodes[rest.charCodeAt(i)];
if (escapedChar) {
// Concat if there are ordinary characters in the middle.
if (i > lastEscapedPos)
escaped += rest.slice(lastEscapedPos, i);
escaped += escapedChar;
lastEscapedPos = i + 1;
}
}
if (lastEscapedPos === 0) // Nothing has been escaped.
Expand Down

0 comments on commit be4a1ea

Please sign in to comment.