Skip to content

Commit e276676

Browse files
committed
fix parsing of non-IPv4 hosts ends in a number in the URL polyfill
1 parent 79e4d2b commit e276676

4 files changed

Lines changed: 37 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
- Fixed possible removal of unnecessary entries in `URLSearchParam.prototype.delete` polyfill with second argument
4343
- Fixed an error in some cases of non-special URLs without a path in the `URL` polyfill
4444
- Fixed some percent encode cases / character sets in the `URL` polyfill
45+
- Fixed parsing of non-IPv4 hosts ends in a number in the `URL` polyfill
4546
- Fixed some cases of `''` and `null` host handling in the `URL` polyfill
4647
- Fixed host parsing with `hostname = host:port` in the `URL` polyfill
4748
- Fixed host inheritance in some cases of file scheme in the `URL` polyfill

packages/core-js/modules/web.url.constructor.js

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,36 @@ var TAB_AND_NEW_LINE = /[\t\n\r]/g;
6868
// eslint-disable-next-line no-unassigned-vars -- expected `undefined` value
6969
var EOF;
7070

71-
// https://url.spec.whatwg.org/#ipv4-number-parser
71+
// https://url.spec.whatwg.org/#ends-in-a-number-checker
72+
var endsInNumber = function (input) {
73+
var parts = split(input, '.');
74+
var last, hexPart;
75+
if (parts[parts.length - 1] === '') {
76+
if (parts.length === 1) return false;
77+
parts.length--;
78+
}
79+
last = parts[parts.length - 1];
80+
if (exec(DEC, last)) return true;
81+
if (exec(HEX_START, last)) {
82+
hexPart = stringSlice(last, 2);
83+
return hexPart === '' || !!exec(HEX, hexPart);
84+
}
85+
return false;
86+
};
87+
88+
// https://url.spec.whatwg.org/#concept-ipv4-parser
7289
var parseIPv4 = function (input) {
7390
var parts = split(input, '.');
7491
var partsLength, numbers, index, part, radix, number, ipv4;
7592
if (parts.length && parts[parts.length - 1] === '') {
7693
parts.length--;
7794
}
7895
partsLength = parts.length;
79-
if (partsLength > 4) return input;
96+
if (partsLength > 4) return null;
8097
numbers = [];
8198
for (index = 0; index < partsLength; index++) {
8299
part = parts[index];
83-
if (part === '') return input;
100+
if (part === '') return null;
84101
radix = 10;
85102
if (part.length > 1 && charAt(part, 0) === '0') {
86103
radix = exec(HEX_START, part) ? 16 : 8;
@@ -89,7 +106,7 @@ var parseIPv4 = function (input) {
89106
if (part === '') {
90107
number = 0;
91108
} else {
92-
if (!exec(radix === 10 ? DEC : radix === 8 ? OCT : HEX, part)) return input;
109+
if (!exec(radix === 10 ? DEC : radix === 8 ? OCT : HEX, part)) return null;
93110
number = parseInt(part, radix);
94111
}
95112
push(numbers, number);
@@ -771,9 +788,13 @@ URLState.prototype = {
771788
} else {
772789
input = toASCII(input);
773790
if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
774-
result = parseIPv4(input);
775-
if (result === null) return INVALID_HOST;
776-
this.host = result;
791+
if (endsInNumber(input)) {
792+
result = parseIPv4(input);
793+
if (result === null) return INVALID_HOST;
794+
this.host = result;
795+
} else {
796+
this.host = input;
797+
}
777798
}
778799
},
779800
// https://url.spec.whatwg.org/#cannot-have-a-username-password-port

tests/unit-global/web.url.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ QUnit.test('URL constructor', assert => {
3939
assert.same(String(new URL('http://0300.168.0xF0')), 'http://192.168.0.240/');
4040
assert.same(String(new URL('http://[20:0:0:1:0:0:0:ff]')), 'http://[20:0:0:1::ff]/');
4141
// assert.same(String(new URL('http://257.168.0xF0')), 'http://257.168.0xf0/', 'incorrect IPv4 parsed as host'); // TypeError in Chrome and Safari
42+
assert.throws(() => new URL('http://257.168.0xF0'), 'invalid IPv4: octet > 255');
4243
assert.same(String(new URL('http://0300.168.0xG0')), 'http://0300.168.0xg0/', 'incorrect IPv4 parsed as host');
4344

45+
assert.throws(() => new URL('http://1.2.3.4.5/'), 'IPv4 with > 4 parts');
46+
assert.throws(() => new URL('http://a.b.c.d.5/'), 'host ending in number with non-numeric parts');
47+
assert.throws(() => new URL('http://foo.1/'), 'host ending in number with non-IPv4');
4448
assert.same(String(new URL('file:///var/log/system.log')), 'file:///var/log/system.log', 'file scheme');
4549

4650
// Chromium ~ 145 on Windows works differently

tests/unit-pure/web.url.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ QUnit.test('URL constructor', assert => {
4040
assert.same(String(new URL('http://0300.168.0xF0')), 'http://192.168.0.240/');
4141
assert.same(String(new URL('http://[20:0:0:1:0:0:0:ff]')), 'http://[20:0:0:1::ff]/');
4242
// assert.same(String(new URL('http://257.168.0xF0')), 'http://257.168.0xf0/', 'incorrect IPv4 parsed as host'); // TypeError in Chrome and Safari
43+
assert.throws(() => new URL('http://257.168.0xF0'), 'invalid IPv4: octet > 255');
4344
assert.same(String(new URL('http://0300.168.0xG0')), 'http://0300.168.0xg0/', 'incorrect IPv4 parsed as host');
4445

46+
assert.throws(() => new URL('http://1.2.3.4.5/'), 'IPv4 with > 4 parts');
47+
assert.throws(() => new URL('http://a.b.c.d.5/'), 'host ending in number with non-numeric parts');
48+
assert.throws(() => new URL('http://foo.1/'), 'host ending in number with non-IPv4');
4549
assert.same(String(new URL('file:///var/log/system.log')), 'file:///var/log/system.log', 'file scheme');
4650

4751
// Chromium ~ 145 on Windows works differently

0 commit comments

Comments
 (0)