Skip to content

Commit 7426d95

Browse files
committed
Update IPv6 parser
1 parent 73fc76e commit 7426d95

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

src/host.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
423423
return Err(ParseError::InvalidIpv6Address)
424424
}
425425
i = start;
426+
if piece_pointer > 6 {
427+
return Err(ParseError::InvalidIpv6Address)
428+
}
426429
is_ip_v4 = true;
427430
},
428431
b':' => {
@@ -445,16 +448,24 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
445448
if piece_pointer > 6 {
446449
return Err(ParseError::InvalidIpv6Address)
447450
}
448-
let mut dots_seen = 0;
451+
let mut numbers_seen = 0;
449452
while i < len {
450-
let mut value = None;
453+
if numbers_seen > 0 {
454+
if numbers_seen < 4 && (i < len && input[i] == b'.') {
455+
i += 1
456+
} else {
457+
return Err(ParseError::InvalidIpv6Address)
458+
}
459+
}
460+
461+
let mut ipv4_piece = None;
451462
while i < len {
452463
let digit = match input[i] {
453464
c @ b'0' ... b'9' => c - b'0',
454465
_ => break
455466
};
456-
match value {
457-
None => value = Some(digit as u16),
467+
match ipv4_piece {
468+
None => ipv4_piece = Some(digit as u16),
458469
Some(0) => return Err(ParseError::InvalidIpv6Address), // No leading zero
459470
Some(ref mut v) => {
460471
*v = *v * 10 + digit as u16;
@@ -465,24 +476,28 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
465476
}
466477
i += 1;
467478
}
468-
if dots_seen < 3 && !(i < len && input[i] == b'.') {
469-
return Err(ParseError::InvalidIpv6Address)
470-
}
471-
pieces[piece_pointer] = if let Some(v) = value {
479+
480+
pieces[piece_pointer] = if let Some(v) = ipv4_piece {
472481
pieces[piece_pointer] * 0x100 + v
473482
} else {
474483
return Err(ParseError::InvalidIpv6Address)
475484
};
476-
if dots_seen == 1 || dots_seen == 3 {
485+
numbers_seen += 1;
486+
487+
if numbers_seen == 2 || numbers_seen == 4 {
477488
piece_pointer += 1;
478489
}
479-
i += 1;
480-
if dots_seen == 3 && i < len {
481-
return Err(ParseError::InvalidIpv6Address)
482-
}
483-
dots_seen += 1;
490+
}
491+
492+
if numbers_seen != 4 {
493+
return Err(ParseError::InvalidIpv6Address)
484494
}
485495
}
496+
497+
if i < len {
498+
return Err(ParseError::InvalidIpv6Address)
499+
}
500+
486501
match compress_pointer {
487502
Some(compress_pointer) => {
488503
let mut swaps = piece_pointer - compress_pointer;

tests/urltestdata.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,6 +3634,26 @@
36343634
"base": "http://other.com/",
36353635
"failure": true
36363636
},
3637+
{
3638+
"input": "http://[::1.2.3.4x]",
3639+
"base": "http://other.com/",
3640+
"failure": true
3641+
},
3642+
{
3643+
"input": "http://[::1.2.3.]",
3644+
"base": "http://other.com/",
3645+
"failure": true
3646+
},
3647+
{
3648+
"input": "http://[::1.2.]",
3649+
"base": "http://other.com/",
3650+
"failure": true
3651+
},
3652+
{
3653+
"input": "http://[::1.]",
3654+
"base": "http://other.com/",
3655+
"failure": true
3656+
},
36373657
"Misc Unicode",
36383658
{
36393659
"input": "http://foo:💩@example.com/bar",

0 commit comments

Comments
 (0)