test,url: improve escaping in url.parse
- rename variables in autoEscapeStr so they are easier to understand - comment the escaping algorithm - increase coverage for autoEscapeStr PR-URL: https://github.com/nodejs/node/pull/10083 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
72b1f79a64
commit
4422c35c5e
136
lib/url.js
136
lib/url.js
@ -437,105 +437,111 @@ function validateHostname(self, rest, hostname) {
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically escape all delimiters and unwise characters from RFC 2396.
|
||||
// Also escape single quotes in case of an XSS attack.
|
||||
// Return undefined if the string doesn't need escaping,
|
||||
// otherwise return the escaped string.
|
||||
function autoEscapeStr(rest) {
|
||||
var newRest = '';
|
||||
var lastPos = 0;
|
||||
var escaped = '';
|
||||
var lastEscapedPos = 0;
|
||||
for (var i = 0; i < rest.length; ++i) {
|
||||
// Automatically escape all delimiters and unwise characters from RFC 2396
|
||||
// Also escape single quotes in case of an XSS attack
|
||||
// Manual switching is faster than using a Map/Object.
|
||||
// `escaped` contains substring up to the last escaped cahracter.
|
||||
switch (rest.charCodeAt(i)) {
|
||||
case 9: // '\t'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%09';
|
||||
lastPos = i + 1;
|
||||
// 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 - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%0A';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%0A';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 13: // '\r'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%0D';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%0D';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 32: // ' '
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%20';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%20';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 34: // '"'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%22';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%22';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 39: // '\''
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%27';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%27';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 60: // '<'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%3C';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%3C';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 62: // '>'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%3E';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%3E';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 92: // '\\'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%5C';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%5C';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 94: // '^'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%5E';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%5E';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 96: // '`'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%60';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%60';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 123: // '{'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%7B';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%7B';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 124: // '|'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%7C';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%7C';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
case 125: // '}'
|
||||
if (i - lastPos > 0)
|
||||
newRest += rest.slice(lastPos, i);
|
||||
newRest += '%7D';
|
||||
lastPos = i + 1;
|
||||
if (i > lastEscapedPos)
|
||||
escaped += rest.slice(lastEscapedPos, i);
|
||||
escaped += '%7D';
|
||||
lastEscapedPos = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastPos === 0)
|
||||
if (lastEscapedPos === 0) // Nothing has been escaped.
|
||||
return;
|
||||
if (lastPos < rest.length)
|
||||
return newRest + rest.slice(lastPos);
|
||||
else
|
||||
return newRest;
|
||||
// There are ordinary characters at the end.
|
||||
if (lastEscapedPos < rest.length)
|
||||
return escaped + rest.slice(lastEscapedPos);
|
||||
else // The last character is escaped.
|
||||
return escaped;
|
||||
}
|
||||
|
||||
// format a parsed object into a url string
|
||||
|
@ -834,6 +834,20 @@ var parseTests = {
|
||||
query: '@c'
|
||||
},
|
||||
|
||||
'http://a.b/\tbc\ndr\ref g"hq\'j<kl>?mn\\op^q=r`99{st|uv}wz': {
|
||||
protocol: 'http:',
|
||||
slashes: true,
|
||||
host: 'a.b',
|
||||
port: null,
|
||||
hostname: 'a.b',
|
||||
hash: null,
|
||||
pathname: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E',
|
||||
path: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
|
||||
search: '?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
|
||||
query: 'mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
|
||||
href: 'http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz'
|
||||
},
|
||||
|
||||
'http://a\r" \t\n<\'b:b@c\r\nd/e?f': {
|
||||
protocol: 'http:',
|
||||
slashes: true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user