|
3 | 3 | #include "node_errors.h"
|
4 | 4 | #include "node_external_reference.h"
|
5 | 5 | #include "node_i18n.h"
|
| 6 | +#include "util.h" |
6 | 7 | #include "util-inl.h"
|
7 | 8 |
|
8 | 9 | #include <cmath>
|
@@ -58,7 +59,7 @@ class URLHost {
|
58 | 59 | public:
|
59 | 60 | ~URLHost();
|
60 | 61 |
|
61 |
| - void ParseIPv4Host(const char* input, size_t length, bool* is_ipv4); |
| 62 | + void ParseIPv4Host(const char* input, size_t length); |
62 | 63 | void ParseIPv6Host(const char* input, size_t length);
|
63 | 64 | void ParseOpaqueHost(const char* input, size_t length);
|
64 | 65 | void ParseHost(const char* input,
|
@@ -401,9 +402,37 @@ int64_t ParseNumber(const char* start, const char* end) {
|
401 | 402 | return strtoll(start, nullptr, R);
|
402 | 403 | }
|
403 | 404 |
|
404 |
| -void URLHost::ParseIPv4Host(const char* input, size_t length, bool* is_ipv4) { |
| 405 | +// https://url.spec.whatwg.org/#ends-in-a-number-checker |
| 406 | +bool EndsInANumber(std::string& str) { |
| 407 | + std::vector<std::string> parts = SplitString(str, '.', false); |
| 408 | + if (parts.size() == 0) |
| 409 | + return false; |
| 410 | + |
| 411 | + if (parts.back() == "") { |
| 412 | + if (parts.size() == 1) |
| 413 | + return false; |
| 414 | + parts.pop_back(); |
| 415 | + } |
| 416 | + |
| 417 | + const std::string& last = parts.back(); |
| 418 | + |
| 419 | + if (last == "") |
| 420 | + return false; |
| 421 | + |
| 422 | + int64_t num = ParseNumber(last.c_str(), last.c_str() + last.size()); |
| 423 | + if (num >= 0) |
| 424 | + return true; |
| 425 | + |
| 426 | + if (last.find_first_not_of("0123456789") == std::string::npos) { |
| 427 | + return true; |
| 428 | + } |
| 429 | + |
| 430 | + return false; |
| 431 | +} |
| 432 | + |
| 433 | + |
| 434 | +void URLHost::ParseIPv4Host(const char* input, size_t length) { |
405 | 435 | CHECK_EQ(type_, HostType::H_FAILED);
|
406 |
| - *is_ipv4 = false; |
407 | 436 | const char* pointer = input;
|
408 | 437 | const char* mark = input;
|
409 | 438 | const char* end = pointer + length;
|
@@ -436,7 +465,6 @@ void URLHost::ParseIPv4Host(const char* input, size_t length, bool* is_ipv4) {
|
436 | 465 | pointer++;
|
437 | 466 | }
|
438 | 467 | CHECK_GT(parts, 0);
|
439 |
| - *is_ipv4 = true; |
440 | 468 |
|
441 | 469 | // If any but the last item in numbers is greater than 255, return failure.
|
442 | 470 | // If the last item in numbers is greater than or equal to
|
@@ -508,11 +536,10 @@ void URLHost::ParseHost(const char* input,
|
508 | 536 | }
|
509 | 537 | }
|
510 | 538 |
|
511 |
| - // Check to see if it's an IPv4 IP address |
512 |
| - bool is_ipv4; |
513 |
| - ParseIPv4Host(decoded.c_str(), decoded.length(), &is_ipv4); |
514 |
| - if (is_ipv4) |
515 |
| - return; |
| 539 | + // If domain ends in a number, then return the result of IPv4 parsing domain |
| 540 | + if (EndsInANumber(decoded)) { |
| 541 | + return ParseIPv4Host(decoded.c_str(), decoded.length()); |
| 542 | + } |
516 | 543 |
|
517 | 544 | // If the unicode flag is set, run the result through punycode ToUnicode
|
518 | 545 | if (unicode && !ToUnicode(decoded, &decoded))
|
|
0 commit comments