// Copyright 2013 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/350788890): Remove this and spanify to fix the errors. #pragma allow_unsafe_buffers #endif #include "url/url_canon_ip.h" #include <stdint.h> #include <stdlib.h> #include <limits> #include "base/check.h" #include "url/url_canon_internal.h" #include "url/url_features.h" namespace url { namespace { // Converts one of the character types that represent a numerical base to the // corresponding base. int BaseForType(SharedCharTypes type) { … } // Converts an IPv4 component to a 32-bit number, while checking for overflow. // // Possible return values: // - IPV4 - The number was valid, and did not overflow. // - BROKEN - The input was numeric, but too large for a 32-bit field. // - NEUTRAL - Input was not numeric. // // The input is assumed to be ASCII. The components are assumed to be non-empty. template<typename CHAR> CanonHostInfo::Family IPv4ComponentToNumber(const CHAR* spec, const Component& component, uint32_t* number) { … } // See declaration of IPv4AddressToNumber for documentation. template <typename CHAR, typename UCHAR> CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec, Component host, unsigned char address[4], int* num_ipv4_components) { … } // Return true if we've made a final IPV4/BROKEN decision, false if the result // is NEUTRAL, and we could use a second opinion. template<typename CHAR, typename UCHAR> bool DoCanonicalizeIPv4Address(const CHAR* spec, const Component& host, CanonOutput* output, CanonHostInfo* host_info) { … } // Helper class that describes the main components of an IPv6 input string. // See the following examples to understand how it breaks up an input string: // // [Example 1]: input = "[::aa:bb]" // ==> num_hex_components = 2 // ==> hex_components[0] = Component(3,2) "aa" // ==> hex_components[1] = Component(6,2) "bb" // ==> index_of_contraction = 0 // ==> ipv4_component = Component(0, -1) // // [Example 2]: input = "[1:2::3:4:5]" // ==> num_hex_components = 5 // ==> hex_components[0] = Component(1,1) "1" // ==> hex_components[1] = Component(3,1) "2" // ==> hex_components[2] = Component(6,1) "3" // ==> hex_components[3] = Component(8,1) "4" // ==> hex_components[4] = Component(10,1) "5" // ==> index_of_contraction = 2 // ==> ipv4_component = Component(0, -1) // // [Example 3]: input = "[::ffff:192.168.0.1]" // ==> num_hex_components = 1 // ==> hex_components[0] = Component(3,4) "ffff" // ==> index_of_contraction = 0 // ==> ipv4_component = Component(8, 11) "192.168.0.1" // // [Example 4]: input = "[1::]" // ==> num_hex_components = 1 // ==> hex_components[0] = Component(1,1) "1" // ==> index_of_contraction = 1 // ==> ipv4_component = Component(0, -1) // // [Example 5]: input = "[::192.168.0.1]" // ==> num_hex_components = 0 // ==> index_of_contraction = 0 // ==> ipv4_component = Component(8, 11) "192.168.0.1" // struct IPv6Parsed { … }; // Parse the IPv6 input string. If parsing succeeded returns true and fills // |parsed| with the information. If parsing failed (because the input is // invalid) returns false. template<typename CHAR, typename UCHAR> bool DoParseIPv6(const CHAR* spec, const Component& host, IPv6Parsed* parsed) { … } // Verifies the parsed IPv6 information, checking that the various components // add up to the right number of bits (hex components are 16 bits, while // embedded IPv4 formats are 32 bits, and contractions are placeholdes for // 16 or more bits). Returns true if sizes match up, false otherwise. On // success writes the length of the contraction (if any) to // |out_num_bytes_of_contraction|. bool CheckIPv6ComponentsSize(const IPv6Parsed& parsed, int* out_num_bytes_of_contraction) { … } // Converts a hex component into a number. This cannot fail since the caller has // already verified that each character in the string was a hex digit, and // that there were no more than 4 characters. template <typename CHAR> uint16_t IPv6HexComponentToNumber(const CHAR* spec, const Component& component) { … } // Converts an IPv6 address to a 128-bit number (network byte order), returning // true on success. False means that the input was not a valid IPv6 address. template<typename CHAR, typename UCHAR> bool DoIPv6AddressToNumber(const CHAR* spec, const Component& host, unsigned char address[16]) { … } // Searches for the longest sequence of zeros in |address|, and writes the // range into |contraction_range|. The run of zeros must be at least 16 bits, // and if there is a tie the first is chosen. void ChooseIPv6ContractionRange(const unsigned char address[16], Component* contraction_range) { … } // Return true if we've made a final IPV6/BROKEN decision, false if the result // is NEUTRAL, and we could use a second opinion. template<typename CHAR, typename UCHAR> bool DoCanonicalizeIPv6Address(const CHAR* spec, const Component& host, CanonOutput* output, CanonHostInfo* host_info) { … } } // namespace void AppendIPv4Address(const unsigned char address[4], CanonOutput* output) { … } void AppendIPv6Address(const unsigned char address[16], CanonOutput* output) { … } void CanonicalizeIPAddress(const char* spec, const Component& host, CanonOutput* output, CanonHostInfo* host_info) { … } void CanonicalizeIPAddress(const char16_t* spec, const Component& host, CanonOutput* output, CanonHostInfo* host_info) { … } void CanonicalizeIPv6Address(const char* spec, const Component& host, CanonOutput& output, CanonHostInfo& host_info) { … } void CanonicalizeIPv6Address(const char16_t* spec, const Component& host, CanonOutput& output, CanonHostInfo& host_info) { … } CanonHostInfo::Family IPv4AddressToNumber(const char* spec, const Component& host, unsigned char address[4], int* num_ipv4_components) { … } CanonHostInfo::Family IPv4AddressToNumber(const char16_t* spec, const Component& host, unsigned char address[4], int* num_ipv4_components) { … } bool IPv6AddressToNumber(const char* spec, const Component& host, unsigned char address[16]) { … } bool IPv6AddressToNumber(const char16_t* spec, const Component& host, unsigned char address[16]) { … } } // namespace url