Skip to content

Commit b6942a6

Browse files
XadillaXrichardlau
authored andcommitted
url,src: simplify ipv6 logic by using uv_inet_pton
PR-URL: #38842 Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent b405296 commit b6942a6

File tree

1 file changed

+17
-108
lines changed

1 file changed

+17
-108
lines changed

src/node_url.cc

+17-108
Original file line numberDiff line numberDiff line change
@@ -794,119 +794,28 @@ bool ToASCII(const std::string& input, std::string* output) {
794794
}
795795
#endif
796796

797+
#define NS_IN6ADDRSZ 16
798+
797799
void URLHost::ParseIPv6Host(const char* input, size_t length) {
798800
CHECK_EQ(type_, HostType::H_FAILED);
799-
unsigned size = arraysize(value_.ipv6);
800-
for (unsigned n = 0; n < size; n++)
801-
value_.ipv6[n] = 0;
802-
uint16_t* piece_pointer = &value_.ipv6[0];
803-
uint16_t* const buffer_end = piece_pointer + size;
804-
uint16_t* compress_pointer = nullptr;
805-
const char* pointer = input;
806-
const char* end = pointer + length;
807-
unsigned value, len, numbers_seen;
808-
char ch = pointer < end ? pointer[0] : kEOL;
809-
if (ch == ':') {
810-
if (length < 2 || pointer[1] != ':')
811-
return;
812-
pointer += 2;
813-
ch = pointer < end ? pointer[0] : kEOL;
814-
piece_pointer++;
815-
compress_pointer = piece_pointer;
816-
}
817-
while (ch != kEOL) {
818-
if (piece_pointer >= buffer_end)
819-
return;
820-
if (ch == ':') {
821-
if (compress_pointer != nullptr)
822-
return;
823-
pointer++;
824-
ch = pointer < end ? pointer[0] : kEOL;
825-
piece_pointer++;
826-
compress_pointer = piece_pointer;
827-
continue;
828-
}
829-
value = 0;
830-
len = 0;
831-
while (len < 4 && IsASCIIHexDigit(ch)) {
832-
value = value * 0x10 + hex2bin(ch);
833-
pointer++;
834-
ch = pointer < end ? pointer[0] : kEOL;
835-
len++;
836-
}
837-
switch (ch) {
838-
case '.':
839-
if (len == 0)
840-
return;
841-
pointer -= len;
842-
ch = pointer < end ? pointer[0] : kEOL;
843-
if (piece_pointer > buffer_end - 2)
844-
return;
845-
numbers_seen = 0;
846-
while (ch != kEOL) {
847-
value = 0xffffffff;
848-
if (numbers_seen > 0) {
849-
if (ch == '.' && numbers_seen < 4) {
850-
pointer++;
851-
ch = pointer < end ? pointer[0] : kEOL;
852-
} else {
853-
return;
854-
}
855-
}
856-
if (!IsASCIIDigit(ch))
857-
return;
858-
while (IsASCIIDigit(ch)) {
859-
unsigned number = ch - '0';
860-
if (value == 0xffffffff) {
861-
value = number;
862-
} else if (value == 0) {
863-
return;
864-
} else {
865-
value = value * 10 + number;
866-
}
867-
if (value > 255)
868-
return;
869-
pointer++;
870-
ch = pointer < end ? pointer[0] : kEOL;
871-
}
872-
*piece_pointer = *piece_pointer * 0x100 + value;
873-
numbers_seen++;
874-
if (numbers_seen == 2 || numbers_seen == 4)
875-
piece_pointer++;
876-
}
877-
if (numbers_seen != 4)
878-
return;
879-
continue;
880-
case ':':
881-
pointer++;
882-
ch = pointer < end ? pointer[0] : kEOL;
883-
if (ch == kEOL)
884-
return;
885-
break;
886-
case kEOL:
887-
break;
888-
default:
889-
return;
890-
}
891-
*piece_pointer = value;
892-
piece_pointer++;
893-
}
894801

895-
if (compress_pointer != nullptr) {
896-
int64_t swaps = piece_pointer - compress_pointer;
897-
piece_pointer = buffer_end - 1;
898-
while (piece_pointer != &value_.ipv6[0] && swaps > 0) {
899-
uint16_t temp = *piece_pointer;
900-
uint16_t* swap_piece = compress_pointer + swaps - 1;
901-
*piece_pointer = *swap_piece;
902-
*swap_piece = temp;
903-
piece_pointer--;
904-
swaps--;
905-
}
906-
} else if (compress_pointer == nullptr &&
907-
piece_pointer != buffer_end) {
802+
unsigned char buf[sizeof(struct in6_addr)];
803+
MaybeStackBuffer<char> ipv6(length + 1);
804+
*(*ipv6 + length) = 0;
805+
memset(buf, 0, sizeof(buf));
806+
memcpy(*ipv6, input, sizeof(const char) * length);
807+
808+
int ret = uv_inet_pton(AF_INET6, *ipv6, buf);
809+
810+
if (ret != 0) {
908811
return;
909812
}
813+
814+
// Ref: https://sourceware.org/git/?p=glibc.git;a=blob;f=resolv/inet_ntop.c;h=c4d38c0f951013e51a4fc6eaa8a9b82e146abe5a;hb=HEAD#l119
815+
for (int i = 0; i < NS_IN6ADDRSZ; i += 2) {
816+
value_.ipv6[i >> 1] = (buf[i] << 8) | buf[i + 1];
817+
}
818+
910819
type_ = HostType::H_IPV6;
911820
}
912821

0 commit comments

Comments
 (0)