@@ -797,119 +797,28 @@ bool ToASCII(const std::string& input, std::string* output) {
797797}
798798#endif
799799
800+ #define NS_IN6ADDRSZ 16
801+
800802void URLHost::ParseIPv6Host (const char * input, size_t length) {
801803 CHECK_EQ (type_, HostType::H_FAILED);
802- unsigned size = arraysize (value_.ipv6 );
803- for (unsigned n = 0 ; n < size; n++)
804- value_.ipv6 [n] = 0 ;
805- uint16_t * piece_pointer = &value_.ipv6 [0 ];
806- uint16_t * const buffer_end = piece_pointer + size;
807- uint16_t * compress_pointer = nullptr ;
808- const char * pointer = input;
809- const char * end = pointer + length;
810- unsigned value, len, numbers_seen;
811- char ch = pointer < end ? pointer[0 ] : kEOL ;
812- if (ch == ' :' ) {
813- if (length < 2 || pointer[1 ] != ' :' )
814- return ;
815- pointer += 2 ;
816- ch = pointer < end ? pointer[0 ] : kEOL ;
817- piece_pointer++;
818- compress_pointer = piece_pointer;
819- }
820- while (ch != kEOL ) {
821- if (piece_pointer >= buffer_end)
822- return ;
823- if (ch == ' :' ) {
824- if (compress_pointer != nullptr )
825- return ;
826- pointer++;
827- ch = pointer < end ? pointer[0 ] : kEOL ;
828- piece_pointer++;
829- compress_pointer = piece_pointer;
830- continue ;
831- }
832- value = 0 ;
833- len = 0 ;
834- while (len < 4 && IsASCIIHexDigit (ch)) {
835- value = value * 0x10 + hex2bin (ch);
836- pointer++;
837- ch = pointer < end ? pointer[0 ] : kEOL ;
838- len++;
839- }
840- switch (ch) {
841- case ' .' :
842- if (len == 0 )
843- return ;
844- pointer -= len;
845- ch = pointer < end ? pointer[0 ] : kEOL ;
846- if (piece_pointer > buffer_end - 2 )
847- return ;
848- numbers_seen = 0 ;
849- while (ch != kEOL ) {
850- value = 0xffffffff ;
851- if (numbers_seen > 0 ) {
852- if (ch == ' .' && numbers_seen < 4 ) {
853- pointer++;
854- ch = pointer < end ? pointer[0 ] : kEOL ;
855- } else {
856- return ;
857- }
858- }
859- if (!IsASCIIDigit (ch))
860- return ;
861- while (IsASCIIDigit (ch)) {
862- unsigned number = ch - ' 0' ;
863- if (value == 0xffffffff ) {
864- value = number;
865- } else if (value == 0 ) {
866- return ;
867- } else {
868- value = value * 10 + number;
869- }
870- if (value > 255 )
871- return ;
872- pointer++;
873- ch = pointer < end ? pointer[0 ] : kEOL ;
874- }
875- *piece_pointer = *piece_pointer * 0x100 + value;
876- numbers_seen++;
877- if (numbers_seen == 2 || numbers_seen == 4 )
878- piece_pointer++;
879- }
880- if (numbers_seen != 4 )
881- return ;
882- continue ;
883- case ' :' :
884- pointer++;
885- ch = pointer < end ? pointer[0 ] : kEOL ;
886- if (ch == kEOL )
887- return ;
888- break ;
889- case kEOL :
890- break ;
891- default :
892- return ;
893- }
894- *piece_pointer = value;
895- piece_pointer++;
896- }
897804
898- if (compress_pointer != nullptr ) {
899- int64_t swaps = piece_pointer - compress_pointer;
900- piece_pointer = buffer_end - 1 ;
901- while (piece_pointer != &value_.ipv6 [0 ] && swaps > 0 ) {
902- uint16_t temp = *piece_pointer;
903- uint16_t * swap_piece = compress_pointer + swaps - 1 ;
904- *piece_pointer = *swap_piece;
905- *swap_piece = temp;
906- piece_pointer--;
907- swaps--;
908- }
909- } else if (compress_pointer == nullptr &&
910- piece_pointer != buffer_end) {
805+ unsigned char buf[sizeof (struct in6_addr )];
806+ MaybeStackBuffer<char > ipv6 (length + 1 );
807+ *(*ipv6 + length) = 0 ;
808+ memset (buf, 0 , sizeof (buf));
809+ memcpy (*ipv6, input, sizeof (const char ) * length);
810+
811+ int ret = uv_inet_pton (AF_INET6, *ipv6, buf);
812+
813+ if (ret != 0 ) {
911814 return ;
912815 }
816+
817+ // Ref: https://sourceware.org/git/?p=glibc.git;a=blob;f=resolv/inet_ntop.c;h=c4d38c0f951013e51a4fc6eaa8a9b82e146abe5a;hb=HEAD#l119
818+ for (int i = 0 ; i < NS_IN6ADDRSZ; i += 2 ) {
819+ value_.ipv6 [i >> 1 ] = (buf[i] << 8 ) | buf[i + 1 ];
820+ }
821+
913822 type_ = HostType::H_IPV6;
914823}
915824
0 commit comments