Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: net/base/ip_address.cc

Issue 2881673002: Avoid heap allocations in IPAddress (Closed)
Patch Set: Fix more comments and use StackVector more Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 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 "net/base/ip_address.h" 5 #include "net/base/ip_address.h"
6 6
7 #include <limits.h> 7 #include <limits.h>
8 #include <algorithm>
8 9
9 #include "base/strings/string_piece.h" 10 #include "base/strings/string_piece.h"
10 #include "base/strings/string_split.h" 11 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
12 #include "net/base/parse_number.h" 13 #include "net/base/parse_number.h"
13 #include "url/gurl.h" 14 #include "url/gurl.h"
14 #include "url/url_canon_ip.h" 15 #include "url/url_canon_ip.h"
15 16
17 namespace net {
16 namespace { 18 namespace {
17 19
18 // The prefix for IPv6 mapped IPv4 addresses. 20 // The prefix for IPv6 mapped IPv4 addresses.
19 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2 21 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2
20 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF}; 22 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
21 23
22 // Note that this function assumes: 24 // Note that this function assumes:
23 // * |ip_address| is at least |prefix_length_in_bits| (bits) long; 25 // * |ip_address| is at least |prefix_length_in_bits| (bits) long;
24 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long. 26 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long.
25 bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address, 27 bool IPAddressPrefixCheck(const IPAddress::IPAddressBytes& ip_address,
26 const uint8_t* ip_prefix, 28 const uint8_t* ip_prefix,
27 size_t prefix_length_in_bits) { 29 size_t prefix_length_in_bits) {
28 // Compare all the bytes that fall entirely within the prefix. 30 // Compare all the bytes that fall entirely within the prefix.
29 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8; 31 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
30 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) { 32 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
31 if (ip_address[i] != ip_prefix[i]) 33 if (ip_address[i] != ip_prefix[i])
32 return false; 34 return false;
33 } 35 }
34 36
35 // In case the prefix was not a multiple of 8, there will be 1 byte 37 // In case the prefix was not a multiple of 8, there will be 1 byte
36 // which is only partially masked. 38 // which is only partially masked.
37 size_t remaining_bits = prefix_length_in_bits % 8; 39 size_t remaining_bits = prefix_length_in_bits % 8;
38 if (remaining_bits != 0) { 40 if (remaining_bits != 0) {
39 uint8_t mask = 0xFF << (8 - remaining_bits); 41 uint8_t mask = 0xFF << (8 - remaining_bits);
40 size_t i = num_entire_bytes_in_prefix; 42 size_t i = num_entire_bytes_in_prefix;
41 if ((ip_address[i] & mask) != (ip_prefix[i] & mask)) 43 if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
42 return false; 44 return false;
43 } 45 }
44 return true; 46 return true;
45 } 47 }
46 48
47 // Returns true if |ip_address| matches any of the reserved IPv4 ranges. This 49 // Returns true if |ip_address| matches any of the reserved IPv4 ranges. This
48 // method operates on a blacklist of reserved IPv4 ranges. Some ranges are 50 // method operates on a blacklist of reserved IPv4 ranges. Some ranges are
49 // consolidated. 51 // consolidated.
50 // Sources for info: 52 // Sources for info:
51 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml 53 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
52 // www.iana.org/assignments/iana-ipv4-special-registry/ 54 // www.iana.org/assignments/iana-ipv4-special-registry/
53 // iana-ipv4-special-registry.xhtml 55 // iana-ipv4-special-registry.xhtml
54 bool IsReservedIPv4(const std::vector<uint8_t>& ip_address) { 56 bool IsReservedIPv4(const IPAddress::IPAddressBytes& ip_address) {
55 // Different IP versions have different range reservations. 57 // Different IP versions have different range reservations.
56 DCHECK_EQ(net::IPAddress::kIPv4AddressSize, ip_address.size()); 58 DCHECK_EQ(IPAddress::kIPv4AddressSize, ip_address.size());
57 struct { 59 struct {
58 const uint8_t address[4]; 60 const uint8_t address[4];
59 size_t prefix_length_in_bits; 61 size_t prefix_length_in_bits;
60 } static const kReservedIPv4Ranges[] = { 62 } static const kReservedIPv4Ranges[] = {
61 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10}, 63 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10},
62 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12}, 64 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12},
63 {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24}, {{192, 168, 0, 0}, 16}, 65 {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24}, {{192, 168, 0, 0}, 16},
64 {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24}, {{203, 0, 113, 0}, 24}, 66 {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24}, {{203, 0, 113, 0}, 24},
65 {{224, 0, 0, 0}, 3}}; 67 {{224, 0, 0, 0}, 3}};
66 68
67 for (const auto& range : kReservedIPv4Ranges) { 69 for (const auto& range : kReservedIPv4Ranges) {
68 if (IPAddressPrefixCheck(ip_address, range.address, 70 if (IPAddressPrefixCheck(ip_address, range.address,
69 range.prefix_length_in_bits)) { 71 range.prefix_length_in_bits)) {
70 return true; 72 return true;
71 } 73 }
72 } 74 }
73 75
74 return false; 76 return false;
75 } 77 }
76 78
77 // Returns true if |ip_address| matches any of the reserved IPv6 ranges. This 79 // Returns true if |ip_address| matches any of the reserved IPv6 ranges. This
78 // method operates on a whitelist of non-reserved IPv6 ranges. All IPv6 80 // method operates on a whitelist of non-reserved IPv6 ranges. All IPv6
79 // addresses outside these ranges are reserved. 81 // addresses outside these ranges are reserved.
80 // Sources for info: 82 // Sources for info:
81 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml 83 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
82 bool IsReservedIPv6(const std::vector<uint8_t>& ip_address) { 84 bool IsReservedIPv6(const IPAddress::IPAddressBytes& ip_address) {
83 // Different IP versions have different range reservations. 85 // Different IP versions have different range reservations.
84 DCHECK_EQ(net::IPAddress::kIPv6AddressSize, ip_address.size()); 86 DCHECK_EQ(IPAddress::kIPv6AddressSize, ip_address.size());
85 struct { 87 struct {
86 const uint8_t address_prefix[2]; 88 const uint8_t address_prefix[2];
87 size_t prefix_length_in_bits; 89 size_t prefix_length_in_bits;
88 } static const kPublicIPv6Ranges[] = { 90 } static const kPublicIPv6Ranges[] = {
89 // 2000::/3 -- Global Unicast 91 // 2000::/3 -- Global Unicast
90 {{0x20, 0}, 3}, 92 {{0x20, 0}, 3},
91 // ff00::/8 -- Multicast 93 // ff00::/8 -- Multicast
92 {{0xff, 0}, 8}, 94 {{0xff, 0}, 8},
93 }; 95 };
94 96
95 for (const auto& range : kPublicIPv6Ranges) { 97 for (const auto& range : kPublicIPv6Ranges) {
96 if (IPAddressPrefixCheck(ip_address, range.address_prefix, 98 if (IPAddressPrefixCheck(ip_address, range.address_prefix,
97 range.prefix_length_in_bits)) { 99 range.prefix_length_in_bits)) {
98 return false; 100 return false;
99 } 101 }
100 } 102 }
101 103
102 return true; 104 return true;
103 } 105 }
104 106
105 bool ParseIPLiteralToBytes(const base::StringPiece& ip_literal, 107 bool ParseIPLiteralToBytes(const base::StringPiece& ip_literal,
106 std::vector<uint8_t>* bytes) { 108 IPAddress::IPAddressBytes* bytes) {
107 // |ip_literal| could be either an IPv4 or an IPv6 literal. If it contains 109 // |ip_literal| could be either an IPv4 or an IPv6 literal. If it contains
108 // a colon however, it must be an IPv6 address. 110 // a colon however, it must be an IPv6 address.
109 if (ip_literal.find(':') != base::StringPiece::npos) { 111 if (ip_literal.find(':') != base::StringPiece::npos) {
110 // GURL expects IPv6 hostnames to be surrounded with brackets. 112 // GURL expects IPv6 hostnames to be surrounded with brackets.
111 std::string host_brackets = "["; 113 std::string host_brackets = "[";
112 ip_literal.AppendToString(&host_brackets); 114 ip_literal.AppendToString(&host_brackets);
113 host_brackets.push_back(']'); 115 host_brackets.push_back(']');
114 url::Component host_comp(0, host_brackets.size()); 116 url::Component host_comp(0, host_brackets.size());
115 117
116 // Try parsing the hostname as an IPv6 literal. 118 // Try parsing the hostname as an IPv6 literal.
117 bytes->resize(16); // 128 bits. 119 bytes->Resize(16); // 128 bits.
118 return url::IPv6AddressToNumber(host_brackets.data(), host_comp, 120 return url::IPv6AddressToNumber(host_brackets.data(), host_comp,
119 bytes->data()); 121 bytes->data());
120 } 122 }
121 123
122 // Otherwise the string is an IPv4 address. 124 // Otherwise the string is an IPv4 address.
123 bytes->resize(4); // 32 bits. 125 bytes->Resize(4); // 32 bits.
124 url::Component host_comp(0, ip_literal.size()); 126 url::Component host_comp(0, ip_literal.size());
125 int num_components; 127 int num_components;
126 url::CanonHostInfo::Family family = url::IPv4AddressToNumber( 128 url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
127 ip_literal.data(), host_comp, bytes->data(), &num_components); 129 ip_literal.data(), host_comp, bytes->data(), &num_components);
128 return family == url::CanonHostInfo::IPV4; 130 return family == url::CanonHostInfo::IPV4;
129 } 131 }
130 132
131 } // namespace 133 } // namespace
132 134
133 namespace net { 135 IPAddress::IPAddressBytes::IPAddressBytes() : size_(0) {}
136
137 IPAddress::IPAddressBytes::IPAddressBytes(const uint8_t* data, size_t data_len)
138 : size_(data_len) {
139 CHECK_GE(16u, data_len);
140 std::copy_n(data, data_len, bytes_.data());
141 }
142
143 IPAddress::IPAddressBytes::~IPAddressBytes() {}
144 IPAddress::IPAddressBytes::IPAddressBytes(
145 IPAddress::IPAddressBytes const& other) = default;
146
147 bool IPAddress::IPAddressBytes::operator<(
148 const IPAddress::IPAddressBytes& other) const {
149 if (size_ < other.size_)
150 return true;
151 if (size_ > other.size_)
152 return false;
153 for (size_t i = 0; i < size_; ++i) {
eroman 2017/05/19 17:37:54 Since you already include <algorithm> could do: r
Ryan Hamilton 2017/05/19 21:30:46 BRILLIANT! I had no idea this existed, but it does
154 if (bytes_[i] < other.bytes_[i])
155 return true;
156 if (bytes_[i] > other.bytes_[i])
157 return false;
158 }
159 return false;
160 }
161
162 bool IPAddress::IPAddressBytes::operator==(
eroman 2017/05/19 17:37:54 Or: return std::equal(begin(), end(), other.begin
Ryan Hamilton 2017/05/19 21:30:46 Done. (though std::equal does not take 4 args, cur
163 const IPAddress::IPAddressBytes& other) const {
164 if (size_ != other.size_)
165 return false;
166 for (size_t i = 0; i < size_; ++i) {
167 if (bytes_[i] != other.bytes_[i])
168 return false;
169 }
170 return true;
171 }
172
173 bool IPAddress::IPAddressBytes::operator!=(
174 const IPAddress::IPAddressBytes& other) const {
175 return !(*this == other);
176 }
134 177
135 IPAddress::IPAddress() {} 178 IPAddress::IPAddress() {}
136 179
137 IPAddress::IPAddress(const std::vector<uint8_t>& address) 180 IPAddress::IPAddress(const std::vector<uint8_t>& address)
138 : ip_address_(address) {} 181 : ip_address_(address.data(), address.size()) {}
182
183 IPAddress::IPAddress(const base::StackVector<uint8_t, 16>& address)
184 : ip_address_(address->data(), address->size()) {}
139 185
140 IPAddress::IPAddress(const IPAddress& other) = default; 186 IPAddress::IPAddress(const IPAddress& other) = default;
141 187
142 IPAddress::IPAddress(const uint8_t* address, size_t address_len) 188 IPAddress::IPAddress(const uint8_t* address, size_t address_len)
143 : ip_address_(address, address + address_len) {} 189 : ip_address_(address, address_len) {}
144 190
145 IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) { 191 IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {
146 ip_address_.reserve(4);
147 ip_address_.push_back(b0); 192 ip_address_.push_back(b0);
148 ip_address_.push_back(b1); 193 ip_address_.push_back(b1);
149 ip_address_.push_back(b2); 194 ip_address_.push_back(b2);
150 ip_address_.push_back(b3); 195 ip_address_.push_back(b3);
151 } 196 }
152 197
153 IPAddress::IPAddress(uint8_t b0, 198 IPAddress::IPAddress(uint8_t b0,
154 uint8_t b1, 199 uint8_t b1,
155 uint8_t b2, 200 uint8_t b2,
156 uint8_t b3, 201 uint8_t b3,
157 uint8_t b4, 202 uint8_t b4,
158 uint8_t b5, 203 uint8_t b5,
159 uint8_t b6, 204 uint8_t b6,
160 uint8_t b7, 205 uint8_t b7,
161 uint8_t b8, 206 uint8_t b8,
162 uint8_t b9, 207 uint8_t b9,
163 uint8_t b10, 208 uint8_t b10,
164 uint8_t b11, 209 uint8_t b11,
165 uint8_t b12, 210 uint8_t b12,
166 uint8_t b13, 211 uint8_t b13,
167 uint8_t b14, 212 uint8_t b14,
168 uint8_t b15) { 213 uint8_t b15) {
169 const uint8_t address[] = {b0, b1, b2, b3, b4, b5, b6, b7, 214 ip_address_.push_back(b0);
170 b8, b9, b10, b11, b12, b13, b14, b15}; 215 ip_address_.push_back(b1);
171 ip_address_ = std::vector<uint8_t>(std::begin(address), std::end(address)); 216 ip_address_.push_back(b2);
217 ip_address_.push_back(b3);
218 ip_address_.push_back(b4);
219 ip_address_.push_back(b5);
220 ip_address_.push_back(b6);
221 ip_address_.push_back(b7);
222 ip_address_.push_back(b8);
223 ip_address_.push_back(b9);
224 ip_address_.push_back(b10);
225 ip_address_.push_back(b11);
226 ip_address_.push_back(b12);
227 ip_address_.push_back(b13);
228 ip_address_.push_back(b14);
229 ip_address_.push_back(b15);
172 } 230 }
173 231
174 IPAddress::~IPAddress() {} 232 IPAddress::~IPAddress() {}
175 233
176 bool IPAddress::IsIPv4() const { 234 bool IPAddress::IsIPv4() const {
177 return ip_address_.size() == kIPv4AddressSize; 235 return ip_address_.size() == kIPv4AddressSize;
178 } 236 }
179 237
180 bool IPAddress::IsIPv6() const { 238 bool IPAddress::IsIPv6() const {
181 return ip_address_.size() == kIPv6AddressSize; 239 return ip_address_.size() == kIPv6AddressSize;
(...skipping 19 matching lines...) Expand all
201 } 259 }
202 260
203 return !empty(); 261 return !empty();
204 } 262 }
205 263
206 bool IPAddress::IsIPv4MappedIPv6() const { 264 bool IPAddress::IsIPv4MappedIPv6() const {
207 return IsIPv6() && IPAddressStartsWith(*this, kIPv4MappedPrefix); 265 return IsIPv6() && IPAddressStartsWith(*this, kIPv4MappedPrefix);
208 } 266 }
209 267
210 bool IPAddress::AssignFromIPLiteral(const base::StringPiece& ip_literal) { 268 bool IPAddress::AssignFromIPLiteral(const base::StringPiece& ip_literal) {
211 std::vector<uint8_t> number; 269 IPAddressBytes number;
212 270
271 // TODO(rch): change the contract so ip_address_ is cleared on failure,
272 // to avoid needing this temporary at all.
213 if (!ParseIPLiteralToBytes(ip_literal, &number)) 273 if (!ParseIPLiteralToBytes(ip_literal, &number))
214 return false; 274 return false;
215 275
216 std::swap(number, ip_address_); 276 ip_address_ = number;
217 return true; 277 return true;
218 } 278 }
219 279
280 std::vector<uint8_t> IPAddress::BytesAsVector() const {
281 return std::vector<uint8_t>(ip_address_.begin(), ip_address_.end());
282 }
283
220 // static 284 // static
221 IPAddress IPAddress::IPv4Localhost() { 285 IPAddress IPAddress::IPv4Localhost() {
222 static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1}; 286 static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1};
223 return IPAddress(kLocalhostIPv4); 287 return IPAddress(kLocalhostIPv4);
224 } 288 }
225 289
226 // static 290 // static
227 IPAddress IPAddress::IPv6Localhost() { 291 IPAddress IPAddress::IPv6Localhost() {
228 static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0, 292 static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 1}; 293 0, 0, 0, 0, 0, 0, 0, 1};
230 return IPAddress(kLocalhostIPv6); 294 return IPAddress(kLocalhostIPv6);
231 } 295 }
232 296
233 // static 297 // static
234 IPAddress IPAddress::AllZeros(size_t num_zero_bytes) { 298 IPAddress IPAddress::AllZeros(size_t num_zero_bytes) {
235 return IPAddress(std::vector<uint8_t>(num_zero_bytes)); 299 base::StackVector<uint8_t, 16> bytes;
eroman 2017/05/19 17:37:54 optional: If you want to save a extra copy: CHECK
Ryan Hamilton 2017/05/19 21:30:46 There are a couple of problems with this. begin()
300 bytes->resize(num_zero_bytes);
301 return IPAddress(bytes);
236 } 302 }
237 303
238 // static 304 // static
239 IPAddress IPAddress::IPv4AllZeros() { 305 IPAddress IPAddress::IPv4AllZeros() {
240 return AllZeros(kIPv4AddressSize); 306 return AllZeros(kIPv4AddressSize);
241 } 307 }
242 308
243 // static 309 // static
244 IPAddress IPAddress::IPv6AllZeros() { 310 IPAddress IPAddress::IPv6AllZeros() {
245 return AllZeros(kIPv6AddressSize); 311 return AllZeros(kIPv6AddressSize);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 356
291 std::string IPAddressToPackedString(const IPAddress& address) { 357 std::string IPAddressToPackedString(const IPAddress& address) {
292 return std::string(reinterpret_cast<const char*>(address.bytes().data()), 358 return std::string(reinterpret_cast<const char*>(address.bytes().data()),
293 address.size()); 359 address.size());
294 } 360 }
295 361
296 IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) { 362 IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) {
297 DCHECK(address.IsIPv4()); 363 DCHECK(address.IsIPv4());
298 // IPv4-mapped addresses are formed by: 364 // IPv4-mapped addresses are formed by:
299 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>. 365 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>.
300 std::vector<uint8_t> bytes; 366 base::StackVector<uint8_t, 16> bytes;
301 bytes.reserve(16); 367 bytes->insert(bytes->end(), std::begin(kIPv4MappedPrefix),
302 bytes.insert(bytes.end(), std::begin(kIPv4MappedPrefix), 368 std::end(kIPv4MappedPrefix));
303 std::end(kIPv4MappedPrefix)); 369 bytes->insert(bytes->end(), address.bytes().begin(), address.bytes().end());
304 bytes.insert(bytes.end(), address.bytes().begin(), address.bytes().end());
305 return IPAddress(bytes); 370 return IPAddress(bytes);
306 } 371 }
307 372
308 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) { 373 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
309 DCHECK(address.IsIPv4MappedIPv6()); 374 DCHECK(address.IsIPv4MappedIPv6());
310 375
311 return IPAddress(std::vector<uint8_t>( 376 base::StackVector<uint8_t, 16> bytes;
312 address.bytes().begin() + arraysize(kIPv4MappedPrefix), 377 bytes->insert(bytes->end(),
313 address.bytes().end())); 378 address.bytes().begin() + arraysize(kIPv4MappedPrefix),
379 address.bytes().end());
380 return IPAddress(bytes);
314 } 381 }
315 382
316 bool IPAddressMatchesPrefix(const IPAddress& ip_address, 383 bool IPAddressMatchesPrefix(const IPAddress& ip_address,
317 const IPAddress& ip_prefix, 384 const IPAddress& ip_prefix,
318 size_t prefix_length_in_bits) { 385 size_t prefix_length_in_bits) {
319 // Both the input IP address and the prefix IP address should be either IPv4 386 // Both the input IP address and the prefix IP address should be either IPv4
320 // or IPv6. 387 // or IPv6.
321 DCHECK(ip_address.IsValid()); 388 DCHECK(ip_address.IsValid());
322 DCHECK(ip_prefix.IsValid()); 389 DCHECK(ip_prefix.IsValid());
323 390
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 if (diff & (1 << (CHAR_BIT - 1))) 458 if (diff & (1 << (CHAR_BIT - 1)))
392 return i * CHAR_BIT + j; 459 return i * CHAR_BIT + j;
393 diff <<= 1; 460 diff <<= 1;
394 } 461 }
395 NOTREACHED(); 462 NOTREACHED();
396 } 463 }
397 return a1.size() * CHAR_BIT; 464 return a1.size() * CHAR_BIT;
398 } 465 }
399 466
400 unsigned MaskPrefixLength(const IPAddress& mask) { 467 unsigned MaskPrefixLength(const IPAddress& mask) {
401 std::vector<uint8_t> all_ones(mask.size(), 0xFF); 468 base::StackVector<uint8_t, 16> all_ones;
469 all_ones->resize(mask.size(), 0xFF);
402 return CommonPrefixLength(mask, IPAddress(all_ones)); 470 return CommonPrefixLength(mask, IPAddress(all_ones));
403 } 471 }
404 472
405 } // namespace net 473 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698