OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "url/url_canon_ip.h" | 5 #include "url/url_canon_ip.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 } else { | 112 } else { |
113 base = CHAR_DEC; | 113 base = CHAR_DEC; |
114 } | 114 } |
115 | 115 |
116 // Extend the prefix to consume all leading zeros. | 116 // Extend the prefix to consume all leading zeros. |
117 while (base_prefix_len < component.len && | 117 while (base_prefix_len < component.len && |
118 spec[component.begin + base_prefix_len] == '0') | 118 spec[component.begin + base_prefix_len] == '0') |
119 base_prefix_len++; | 119 base_prefix_len++; |
120 | 120 |
121 // Put the component, minus any base prefix, into a NULL-terminated buffer so | 121 // Put the component, minus any base prefix, into a NULL-terminated buffer so |
122 // we can call the standard library. Because leading zeros have already been | 122 // we can call the standard library. Because leading zeros have already been |
123 // discarded, filling the entire buffer is guaranteed to trigger the 32-bit | 123 // discarded, filling the entire buffer is guaranteed to trigger the 32-bit |
124 // overflow check. | 124 // overflow check. |
125 const int kMaxComponentLen = 16; | 125 const int kMaxComponentLen = 16; |
126 char buf[kMaxComponentLen + 1]; // digits + '\0' | 126 char buf[kMaxComponentLen + 1]; // digits + '\0' |
127 int dest_i = 0; | 127 int dest_i = 0; |
128 for (int i = component.begin + base_prefix_len; i < component.end(); i++) { | 128 for (int i = component.begin + base_prefix_len; i < component.end(); i++) { |
129 // We know the input is 7-bit, so convert to narrow (if this is the wide | 129 // We know the input is 7-bit, so convert to narrow (if this is the wide |
130 // version of the template) by casting. | 130 // version of the template) by casting. |
131 char input = static_cast<char>(spec[i]); | 131 char input = static_cast<char>(spec[i]); |
132 | 132 |
133 // Validate that this character is OK for the given base. | 133 // Validate that this character is OK for the given base. |
134 if (!IsCharOfType(input, base)) | 134 if (!IsCharOfType(input, base)) |
135 return CanonHostInfo::NEUTRAL; | 135 return CanonHostInfo::NEUTRAL; |
136 | 136 |
137 // Fill the buffer, if there's space remaining. This check allows us to | 137 // Fill the buffer, if there's space remaining. This check allows us to |
138 // verify that all characters are numeric, even those that don't fit. | 138 // verify that all characters are numeric, even those that don't fit. |
139 if (dest_i < kMaxComponentLen) | 139 if (dest_i < kMaxComponentLen) |
140 buf[dest_i++] = input; | 140 buf[dest_i++] = input; |
141 } | 141 } |
142 | 142 |
143 buf[dest_i] = '\0'; | 143 buf[dest_i] = '\0'; |
144 | 144 |
145 // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal | 145 // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal |
146 // number can overflow a 64-bit number in <= 16 characters). | 146 // number can overflow a 64-bit number in <= 16 characters). |
147 uint64_t num = _strtoui64(buf, NULL, BaseForType(base)); | 147 uint64_t num = _strtoui64(buf, NULL, BaseForType(base)); |
148 | 148 |
149 // Check for 32-bit overflow. | 149 // Check for 32-bit overflow. |
150 if (num > std::numeric_limits<uint32_t>::max()) | 150 if (num > std::numeric_limits<uint32_t>::max()) |
151 return CanonHostInfo::BROKEN; | 151 return CanonHostInfo::BROKEN; |
152 | 152 |
153 // No overflow. Success! | 153 // No overflow. Success! |
154 *number = static_cast<uint32_t>(num); | 154 *number = static_cast<uint32_t>(num); |
155 return CanonHostInfo::IPV4; | 155 return CanonHostInfo::IPV4; |
156 } | 156 } |
157 | 157 |
158 // See declaration of IPv4AddressToNumber for documentation. | 158 // See declaration of IPv4AddressToNumber for documentation. |
159 template<typename CHAR> | 159 template<typename CHAR> |
160 CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec, | 160 CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec, |
161 const Component& host, | 161 const Component& host, |
162 unsigned char address[4], | 162 unsigned char address[4], |
163 int* num_ipv4_components) { | 163 int* num_ipv4_components) { |
164 // The identified components. Not all may exist. | 164 // The identified components. Not all may exist. |
165 Component components[4]; | 165 Component components[4]; |
166 if (!FindIPv4Components(spec, host, components)) | 166 if (!FindIPv4Components(spec, host, components)) |
167 return CanonHostInfo::NEUTRAL; | 167 return CanonHostInfo::NEUTRAL; |
168 | 168 |
169 // Convert existing components to digits. Values up to | 169 // Convert existing components to digits. Values up to |
170 // |existing_components| will be valid. | 170 // |existing_components| will be valid. |
171 uint32_t component_values[4]; | 171 uint32_t component_values[4]; |
172 int existing_components = 0; | 172 int existing_components = 0; |
173 | 173 |
174 // Set to true if one or more components are BROKEN. BROKEN is only | 174 // Set to true if one or more components are BROKEN. BROKEN is only |
175 // returned if all components are IPV4 or BROKEN, so, for example, | 175 // returned if all components are IPV4 or BROKEN, so, for example, |
176 // 12345678912345.de returns NEUTRAL rather than broken. | 176 // 12345678912345.de returns NEUTRAL rather than broken. |
177 bool broken = false; | 177 bool broken = false; |
178 for (int i = 0; i < 4; i++) { | 178 for (int i = 0; i < 4; i++) { |
179 if (components[i].len <= 0) | 179 if (components[i].len <= 0) |
180 continue; | 180 continue; |
181 CanonHostInfo::Family family = IPv4ComponentToNumber( | 181 CanonHostInfo::Family family = IPv4ComponentToNumber( |
182 spec, components[i], &component_values[existing_components]); | 182 spec, components[i], &component_values[existing_components]); |
183 | 183 |
184 if (family == CanonHostInfo::BROKEN) { | 184 if (family == CanonHostInfo::BROKEN) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 } | 434 } |
435 | 435 |
436 // Check that the numbers add up. | 436 // Check that the numbers add up. |
437 if (num_bytes_without_contraction + num_bytes_of_contraction != 16) | 437 if (num_bytes_without_contraction + num_bytes_of_contraction != 16) |
438 return false; | 438 return false; |
439 | 439 |
440 *out_num_bytes_of_contraction = num_bytes_of_contraction; | 440 *out_num_bytes_of_contraction = num_bytes_of_contraction; |
441 return true; | 441 return true; |
442 } | 442 } |
443 | 443 |
444 // Converts a hex comonent into a number. This cannot fail since the caller has | 444 // Converts a hex component into a number. This cannot fail since the caller has |
445 // already verified that each character in the string was a hex digit, and | 445 // already verified that each character in the string was a hex digit, and |
446 // that there were no more than 4 characters. | 446 // that there were no more than 4 characters. |
447 template <typename CHAR> | 447 template <typename CHAR> |
448 uint16_t IPv6HexComponentToNumber(const CHAR* spec, | 448 uint16_t IPv6HexComponentToNumber(const CHAR* spec, |
449 const Component& component) { | 449 const Component& component) { |
450 DCHECK(component.len <= 4); | 450 DCHECK(component.len <= 4); |
451 | 451 |
452 // Copy the hex string into a C-string. | 452 // Copy the hex string into a C-string. |
453 char buf[5]; | 453 char buf[5]; |
454 for (int i = 0; i < component.len; ++i) | 454 for (int i = 0; i < component.len; ++i) |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 for (int i = host.begin; i < host.end(); i++) { | 571 for (int i = host.begin; i < host.end(); i++) { |
572 switch (spec[i]) { | 572 switch (spec[i]) { |
573 case '[': | 573 case '[': |
574 case ']': | 574 case ']': |
575 case ':': | 575 case ':': |
576 host_info->family = CanonHostInfo::BROKEN; | 576 host_info->family = CanonHostInfo::BROKEN; |
577 return true; | 577 return true; |
578 } | 578 } |
579 } | 579 } |
580 | 580 |
581 // No invalid characters. Could still be IPv4 or a hostname. | 581 // No invalid characters. Could still be IPv4 or a hostname. |
582 host_info->family = CanonHostInfo::NEUTRAL; | 582 host_info->family = CanonHostInfo::NEUTRAL; |
583 return false; | 583 return false; |
584 } | 584 } |
585 | 585 |
586 host_info->out_host.begin = output->length(); | 586 host_info->out_host.begin = output->length(); |
587 output->push_back('['); | 587 output->push_back('['); |
588 AppendIPv6Address(host_info->address, output); | 588 AppendIPv6Address(host_info->address, output); |
589 output->push_back(']'); | 589 output->push_back(']'); |
590 host_info->out_host.len = output->length() - host_info->out_host.begin; | 590 host_info->out_host.len = output->length() - host_info->out_host.begin; |
591 | 591 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 return DoIPv6AddressToNumber<char, unsigned char>(spec, host, address); | 702 return DoIPv6AddressToNumber<char, unsigned char>(spec, host, address); |
703 } | 703 } |
704 | 704 |
705 bool IPv6AddressToNumber(const base::char16* spec, | 705 bool IPv6AddressToNumber(const base::char16* spec, |
706 const Component& host, | 706 const Component& host, |
707 unsigned char address[16]) { | 707 unsigned char address[16]) { |
708 return DoIPv6AddressToNumber<base::char16, base::char16>(spec, host, address); | 708 return DoIPv6AddressToNumber<base::char16, base::char16>(spec, host, address); |
709 } | 709 } |
710 | 710 |
711 } // namespace url | 711 } // namespace url |
OLD | NEW |