From a5786ac26b7213088ee3869d05747e8837420d69 Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Wed, 12 Apr 2017 20:35:41 +0200 Subject: [PATCH] url: disallow invalid IPv4 in IPv6 parser Fixes: https://github.com/nodejs/node/issues/10655 --- src/node_url.cc | 26 +++--- test/fixtures/url-setter-tests.js | 144 +++++++++++++++--------------- test/fixtures/url-tests.js | 40 ++++----- 3 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/node_url.cc b/src/node_url.cc index 16a4cdd45b54b4..39f56ece679005 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -110,7 +110,7 @@ namespace url { uint16_t* compress_pointer = nullptr; const char* pointer = input; const char* end = pointer + length; - unsigned value, len, swaps, dots; + unsigned value, len, swaps, numbers_seen; char ch = pointer < end ? pointer[0] : kEOL; if (ch == ':') { if (length < 2 || pointer[1] != ':') @@ -148,9 +148,17 @@ namespace url { ch = pointer < end ? pointer[0] : kEOL; if (piece_pointer > last_piece - 2) goto end; - dots = 0; + numbers_seen = 0; while (ch != kEOL) { value = 0xffffffff; + if (numbers_seen > 0) { + if (ch == '.' && numbers_seen < 4) { + pointer++; + ch = pointer < end ? pointer[0] : kEOL; + } else { + goto end; + } + } if (!ASCII_DIGIT(ch)) goto end; while (ASCII_DIGIT(ch)) { @@ -167,19 +175,13 @@ namespace url { pointer++; ch = pointer < end ? pointer[0] : kEOL; } - if (dots < 3 && ch != '.') - goto end; *piece_pointer = *piece_pointer * 0x100 + value; - if (dots & 0x1) + numbers_seen++; + if (numbers_seen == 2 || numbers_seen == 4) piece_pointer++; - if (ch != kEOL) { - pointer++; - ch = pointer < end ? pointer[0] : kEOL; - } - if (dots == 3 && ch != kEOL) - goto end; - dots++; } + if (numbers_seen != 4) + goto end; continue; case ':': pointer++; diff --git a/test/fixtures/url-setter-tests.js b/test/fixtures/url-setter-tests.js index d0688611a01c0f..0b5280f25d76c1 100644 --- a/test/fixtures/url-setter-tests.js +++ b/test/fixtures/url-setter-tests.js @@ -880,42 +880,42 @@ module.exports = "hostname": "example.net" } }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.3.4x]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.3.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, + { + "href": "http://example.net/", + "new_value": "[::1.2.3.4x]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.2.3.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.2.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, // { // "href": "file://y/", // "new_value": "x:123", @@ -1214,42 +1214,42 @@ module.exports = "hostname": "example.net" } }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.3.4x]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.3.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.2.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, - // { - // "href": "http://example.net/", - // "new_value": "[::1.]", - // "expected": { - // "href": "http://example.net/", - // "host": "example.net", - // "hostname": "example.net" - // } - // }, + { + "href": "http://example.net/", + "new_value": "[::1.2.3.4x]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.2.3.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.2.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, + { + "href": "http://example.net/", + "new_value": "[::1.]", + "expected": { + "href": "http://example.net/", + "host": "example.net", + "hostname": "example.net" + } + }, // { // "href": "file://y/", // "new_value": "x:123", diff --git a/test/fixtures/url-tests.js b/test/fixtures/url-tests.js index 3858f12db55e0d..d44a36bcfe7e13 100644 --- a/test/fixtures/url-tests.js +++ b/test/fixtures/url-tests.js @@ -3800,26 +3800,26 @@ module.exports = "base": "http://other.com/", "failure": true }, - // { - // "input": "http://[::1.2.3.4x]", - // "base": "http://other.com/", - // "failure": true - // }, - // { - // "input": "http://[::1.2.3.]", - // "base": "http://other.com/", - // "failure": true - // }, - // { - // "input": "http://[::1.2.]", - // "base": "http://other.com/", - // "failure": true - // }, - // { - // "input": "http://[::1.]", - // "base": "http://other.com/", - // "failure": true - // }, + { + "input": "http://[::1.2.3.4x]", + "base": "http://other.com/", + "failure": true + }, + { + "input": "http://[::1.2.3.]", + "base": "http://other.com/", + "failure": true + }, + { + "input": "http://[::1.2.]", + "base": "http://other.com/", + "failure": true + }, + { + "input": "http://[::1.]", + "base": "http://other.com/", + "failure": true + }, "Misc Unicode", { "input": "http://foo:💩@example.com/bar",