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
3 // found in the LICENSE file.
4
5 #include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
6
7 #include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
8 #include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h"
9
10 namespace spdy {
11
12 namespace test {
13
14 // Expose all private methods of class SpdyAltSvcWireFormat.
15 class SpdyAltSvcWireFormatPeer {
16 public:
SkipWhiteSpace(quiche::QuicheStringPiece::const_iterator * c,quiche::QuicheStringPiece::const_iterator end)17 static void SkipWhiteSpace(quiche::QuicheStringPiece::const_iterator* c,
18 quiche::QuicheStringPiece::const_iterator end) {
19 SpdyAltSvcWireFormat::SkipWhiteSpace(c, end);
20 }
PercentDecode(quiche::QuicheStringPiece::const_iterator c,quiche::QuicheStringPiece::const_iterator end,std::string * output)21 static bool PercentDecode(quiche::QuicheStringPiece::const_iterator c,
22 quiche::QuicheStringPiece::const_iterator end,
23 std::string* output) {
24 return SpdyAltSvcWireFormat::PercentDecode(c, end, output);
25 }
ParseAltAuthority(quiche::QuicheStringPiece::const_iterator c,quiche::QuicheStringPiece::const_iterator end,std::string * host,uint16_t * port)26 static bool ParseAltAuthority(quiche::QuicheStringPiece::const_iterator c,
27 quiche::QuicheStringPiece::const_iterator end,
28 std::string* host,
29 uint16_t* port) {
30 return SpdyAltSvcWireFormat::ParseAltAuthority(c, end, host, port);
31 }
ParsePositiveInteger16(quiche::QuicheStringPiece::const_iterator c,quiche::QuicheStringPiece::const_iterator end,uint16_t * max_age)32 static bool ParsePositiveInteger16(
33 quiche::QuicheStringPiece::const_iterator c,
34 quiche::QuicheStringPiece::const_iterator end,
35 uint16_t* max_age) {
36 return SpdyAltSvcWireFormat::ParsePositiveInteger16(c, end, max_age);
37 }
ParsePositiveInteger32(quiche::QuicheStringPiece::const_iterator c,quiche::QuicheStringPiece::const_iterator end,uint32_t * max_age)38 static bool ParsePositiveInteger32(
39 quiche::QuicheStringPiece::const_iterator c,
40 quiche::QuicheStringPiece::const_iterator end,
41 uint32_t* max_age) {
42 return SpdyAltSvcWireFormat::ParsePositiveInteger32(c, end, max_age);
43 }
44 };
45
46 } // namespace test
47
48 namespace {
49
50 // Generate header field values, possibly with multiply defined parameters and
51 // random case, and corresponding AlternativeService entries.
FuzzHeaderFieldValue(int i,std::string * header_field_value,SpdyAltSvcWireFormat::AlternativeService * expected_altsvc)52 void FuzzHeaderFieldValue(
53 int i,
54 std::string* header_field_value,
55 SpdyAltSvcWireFormat::AlternativeService* expected_altsvc) {
56 if (!header_field_value->empty()) {
57 header_field_value->push_back(',');
58 }
59 // TODO(b/77515496): use struct of bools instead of int |i| to generate the
60 // header field value.
61 bool is_ietf_format_quic = (i & 1 << 0) != 0;
62 if (i & 1 << 0) {
63 expected_altsvc->protocol_id = "hq";
64 header_field_value->append("hq=\"");
65 } else {
66 expected_altsvc->protocol_id = "a=b%c";
67 header_field_value->append("a%3Db%25c=\"");
68 }
69 if (i & 1 << 1) {
70 expected_altsvc->host = "foo\"bar\\baz";
71 header_field_value->append("foo\\\"bar\\\\baz");
72 } else {
73 expected_altsvc->host = "";
74 }
75 expected_altsvc->port = 42;
76 header_field_value->append(":42\"");
77 if (i & 1 << 2) {
78 header_field_value->append(" ");
79 }
80 if (i & 3 << 3) {
81 expected_altsvc->max_age = 1111;
82 header_field_value->append(";");
83 if (i & 1 << 3) {
84 header_field_value->append(" ");
85 }
86 header_field_value->append("mA=1111");
87 if (i & 2 << 3) {
88 header_field_value->append(" ");
89 }
90 }
91 if (i & 1 << 5) {
92 header_field_value->append("; J=s");
93 }
94 if (i & 1 << 6) {
95 if (is_ietf_format_quic) {
96 if (i & 1 << 7) {
97 expected_altsvc->version.push_back(0x923457e);
98 header_field_value->append("; quic=923457E");
99 } else {
100 expected_altsvc->version.push_back(1);
101 expected_altsvc->version.push_back(0xFFFFFFFF);
102 header_field_value->append("; quic=1; quic=fFfFffFf");
103 }
104 } else {
105 if (i & i << 7) {
106 expected_altsvc->version.push_back(24);
107 header_field_value->append("; v=\"24\"");
108 } else {
109 expected_altsvc->version.push_back(1);
110 expected_altsvc->version.push_back(65535);
111 header_field_value->append("; v=\"1,65535\"");
112 }
113 }
114 }
115 if (i & 1 << 8) {
116 expected_altsvc->max_age = 999999999;
117 header_field_value->append("; Ma=999999999");
118 }
119 if (i & 1 << 9) {
120 header_field_value->append(";");
121 }
122 if (i & 1 << 10) {
123 header_field_value->append(" ");
124 }
125 if (i & 1 << 11) {
126 header_field_value->append(",");
127 }
128 if (i & 1 << 12) {
129 header_field_value->append(" ");
130 }
131 }
132
133 // Generate AlternativeService entries and corresponding header field values in
134 // canonical form, that is, what SerializeHeaderFieldValue() should output.
FuzzAlternativeService(int i,SpdyAltSvcWireFormat::AlternativeService * altsvc,std::string * expected_header_field_value)135 void FuzzAlternativeService(int i,
136 SpdyAltSvcWireFormat::AlternativeService* altsvc,
137 std::string* expected_header_field_value) {
138 if (!expected_header_field_value->empty()) {
139 expected_header_field_value->push_back(',');
140 }
141 altsvc->protocol_id = "a=b%c";
142 altsvc->port = 42;
143 expected_header_field_value->append("a%3Db%25c=\"");
144 if (i & 1 << 0) {
145 altsvc->host = "foo\"bar\\baz";
146 expected_header_field_value->append("foo\\\"bar\\\\baz");
147 }
148 expected_header_field_value->append(":42\"");
149 if (i & 1 << 1) {
150 altsvc->max_age = 1111;
151 expected_header_field_value->append("; ma=1111");
152 }
153 if (i & 1 << 2) {
154 altsvc->version.push_back(24);
155 altsvc->version.push_back(25);
156 expected_header_field_value->append("; v=\"24,25\"");
157 }
158 }
159
160 // Tests of public API.
161
TEST(SpdyAltSvcWireFormatTest,DefaultValues)162 TEST(SpdyAltSvcWireFormatTest, DefaultValues) {
163 SpdyAltSvcWireFormat::AlternativeService altsvc;
164 EXPECT_EQ("", altsvc.protocol_id);
165 EXPECT_EQ("", altsvc.host);
166 EXPECT_EQ(0u, altsvc.port);
167 EXPECT_EQ(86400u, altsvc.max_age);
168 EXPECT_TRUE(altsvc.version.empty());
169 }
170
TEST(SpdyAltSvcWireFormatTest,ParseInvalidEmptyHeaderFieldValue)171 TEST(SpdyAltSvcWireFormatTest, ParseInvalidEmptyHeaderFieldValue) {
172 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
173 ASSERT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue("", &altsvc_vector));
174 }
175
TEST(SpdyAltSvcWireFormatTest,ParseHeaderFieldValueClear)176 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueClear) {
177 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
178 ASSERT_TRUE(
179 SpdyAltSvcWireFormat::ParseHeaderFieldValue("clear", &altsvc_vector));
180 EXPECT_EQ(0u, altsvc_vector.size());
181 }
182
183 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored
184 // parameters, duplicate parameters, trailing space, trailing alternate service
185 // separator, etc. Single alternative service at a time.
TEST(SpdyAltSvcWireFormatTest,ParseHeaderFieldValue)186 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValue) {
187 for (int i = 0; i < 1 << 13; ++i) {
188 std::string header_field_value;
189 SpdyAltSvcWireFormat::AlternativeService expected_altsvc;
190 FuzzHeaderFieldValue(i, &header_field_value, &expected_altsvc);
191 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
192 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value,
193 &altsvc_vector));
194 ASSERT_EQ(1u, altsvc_vector.size());
195 EXPECT_EQ(expected_altsvc.protocol_id, altsvc_vector[0].protocol_id);
196 EXPECT_EQ(expected_altsvc.host, altsvc_vector[0].host);
197 EXPECT_EQ(expected_altsvc.port, altsvc_vector[0].port);
198 EXPECT_EQ(expected_altsvc.max_age, altsvc_vector[0].max_age);
199 EXPECT_EQ(expected_altsvc.version, altsvc_vector[0].version);
200
201 // Roundtrip test starting with |altsvc_vector|.
202 std::string reserialized_header_field_value =
203 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector);
204 SpdyAltSvcWireFormat::AlternativeServiceVector roundtrip_altsvc_vector;
205 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
206 reserialized_header_field_value, &roundtrip_altsvc_vector));
207 ASSERT_EQ(1u, roundtrip_altsvc_vector.size());
208 EXPECT_EQ(expected_altsvc.protocol_id,
209 roundtrip_altsvc_vector[0].protocol_id);
210 EXPECT_EQ(expected_altsvc.host, roundtrip_altsvc_vector[0].host);
211 EXPECT_EQ(expected_altsvc.port, roundtrip_altsvc_vector[0].port);
212 EXPECT_EQ(expected_altsvc.max_age, roundtrip_altsvc_vector[0].max_age);
213 EXPECT_EQ(expected_altsvc.version, roundtrip_altsvc_vector[0].version);
214 }
215 }
216
217 // Fuzz test of ParseHeaderFieldValue() with optional whitespaces, ignored
218 // parameters, duplicate parameters, trailing space, trailing alternate service
219 // separator, etc. Possibly multiple alternative service at a time.
TEST(SpdyAltSvcWireFormatTest,ParseHeaderFieldValueMultiple)220 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueMultiple) {
221 for (int i = 0; i < 1 << 13;) {
222 std::string header_field_value;
223 SpdyAltSvcWireFormat::AlternativeServiceVector expected_altsvc_vector;
224 // This will generate almost two hundred header field values with two,
225 // three, four, five, six, and seven alternative services each, and
226 // thousands with a single one.
227 do {
228 SpdyAltSvcWireFormat::AlternativeService expected_altsvc;
229 FuzzHeaderFieldValue(i, &header_field_value, &expected_altsvc);
230 expected_altsvc_vector.push_back(expected_altsvc);
231 ++i;
232 } while (i % 6 < i % 7);
233 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
234 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(header_field_value,
235 &altsvc_vector));
236 ASSERT_EQ(expected_altsvc_vector.size(), altsvc_vector.size());
237 for (unsigned int j = 0; j < altsvc_vector.size(); ++j) {
238 EXPECT_EQ(expected_altsvc_vector[j].protocol_id,
239 altsvc_vector[j].protocol_id);
240 EXPECT_EQ(expected_altsvc_vector[j].host, altsvc_vector[j].host);
241 EXPECT_EQ(expected_altsvc_vector[j].port, altsvc_vector[j].port);
242 EXPECT_EQ(expected_altsvc_vector[j].max_age, altsvc_vector[j].max_age);
243 EXPECT_EQ(expected_altsvc_vector[j].version, altsvc_vector[j].version);
244 }
245
246 // Roundtrip test starting with |altsvc_vector|.
247 std::string reserialized_header_field_value =
248 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector);
249 SpdyAltSvcWireFormat::AlternativeServiceVector roundtrip_altsvc_vector;
250 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
251 reserialized_header_field_value, &roundtrip_altsvc_vector));
252 ASSERT_EQ(expected_altsvc_vector.size(), roundtrip_altsvc_vector.size());
253 for (unsigned int j = 0; j < roundtrip_altsvc_vector.size(); ++j) {
254 EXPECT_EQ(expected_altsvc_vector[j].protocol_id,
255 roundtrip_altsvc_vector[j].protocol_id);
256 EXPECT_EQ(expected_altsvc_vector[j].host,
257 roundtrip_altsvc_vector[j].host);
258 EXPECT_EQ(expected_altsvc_vector[j].port,
259 roundtrip_altsvc_vector[j].port);
260 EXPECT_EQ(expected_altsvc_vector[j].max_age,
261 roundtrip_altsvc_vector[j].max_age);
262 EXPECT_EQ(expected_altsvc_vector[j].version,
263 roundtrip_altsvc_vector[j].version);
264 }
265 }
266 }
267
TEST(SpdyAltSvcWireFormatTest,SerializeEmptyHeaderFieldValue)268 TEST(SpdyAltSvcWireFormatTest, SerializeEmptyHeaderFieldValue) {
269 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
270 EXPECT_EQ("clear",
271 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector));
272 }
273
274 // Test ParseHeaderFieldValue() and SerializeHeaderFieldValue() on the same pair
275 // of |expected_header_field_value| and |altsvc|, with and without hostname and
276 // each
277 // parameter. Single alternative service at a time.
TEST(SpdyAltSvcWireFormatTest,RoundTrip)278 TEST(SpdyAltSvcWireFormatTest, RoundTrip) {
279 for (int i = 0; i < 1 << 3; ++i) {
280 SpdyAltSvcWireFormat::AlternativeService altsvc;
281 std::string expected_header_field_value;
282 FuzzAlternativeService(i, &altsvc, &expected_header_field_value);
283
284 // Test ParseHeaderFieldValue().
285 SpdyAltSvcWireFormat::AlternativeServiceVector parsed_altsvc_vector;
286 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
287 expected_header_field_value, &parsed_altsvc_vector));
288 ASSERT_EQ(1u, parsed_altsvc_vector.size());
289 EXPECT_EQ(altsvc.protocol_id, parsed_altsvc_vector[0].protocol_id);
290 EXPECT_EQ(altsvc.host, parsed_altsvc_vector[0].host);
291 EXPECT_EQ(altsvc.port, parsed_altsvc_vector[0].port);
292 EXPECT_EQ(altsvc.max_age, parsed_altsvc_vector[0].max_age);
293 EXPECT_EQ(altsvc.version, parsed_altsvc_vector[0].version);
294
295 // Test SerializeHeaderFieldValue().
296 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
297 altsvc_vector.push_back(altsvc);
298 EXPECT_EQ(expected_header_field_value,
299 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector));
300 }
301 }
302
303 // Test ParseHeaderFieldValue() and SerializeHeaderFieldValue() on the same pair
304 // of |expected_header_field_value| and |altsvc|, with and without hostname and
305 // each
306 // parameter. Multiple alternative services at a time.
TEST(SpdyAltSvcWireFormatTest,RoundTripMultiple)307 TEST(SpdyAltSvcWireFormatTest, RoundTripMultiple) {
308 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
309 std::string expected_header_field_value;
310 for (int i = 0; i < 1 << 3; ++i) {
311 SpdyAltSvcWireFormat::AlternativeService altsvc;
312 FuzzAlternativeService(i, &altsvc, &expected_header_field_value);
313 altsvc_vector.push_back(altsvc);
314 }
315
316 // Test ParseHeaderFieldValue().
317 SpdyAltSvcWireFormat::AlternativeServiceVector parsed_altsvc_vector;
318 ASSERT_TRUE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
319 expected_header_field_value, &parsed_altsvc_vector));
320 ASSERT_EQ(altsvc_vector.size(), parsed_altsvc_vector.size());
321 auto expected_it = altsvc_vector.begin();
322 auto parsed_it = parsed_altsvc_vector.begin();
323 for (; expected_it != altsvc_vector.end(); ++expected_it, ++parsed_it) {
324 EXPECT_EQ(expected_it->protocol_id, parsed_it->protocol_id);
325 EXPECT_EQ(expected_it->host, parsed_it->host);
326 EXPECT_EQ(expected_it->port, parsed_it->port);
327 EXPECT_EQ(expected_it->max_age, parsed_it->max_age);
328 EXPECT_EQ(expected_it->version, parsed_it->version);
329 }
330
331 // Test SerializeHeaderFieldValue().
332 EXPECT_EQ(expected_header_field_value,
333 SpdyAltSvcWireFormat::SerializeHeaderFieldValue(altsvc_vector));
334 }
335
336 // ParseHeaderFieldValue() should return false on malformed field values:
337 // invalid percent encoding, unmatched quotation mark, empty port, non-numeric
338 // characters in numeric fields.
TEST(SpdyAltSvcWireFormatTest,ParseHeaderFieldValueInvalid)339 TEST(SpdyAltSvcWireFormatTest, ParseHeaderFieldValueInvalid) {
340 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
341 const char* invalid_field_value_array[] = {"a%",
342 "a%x",
343 "a%b",
344 "a%9z",
345 "a=",
346 "a=\"",
347 "a=\"b\"",
348 "a=\":\"",
349 "a=\"c:\"",
350 "a=\"c:foo\"",
351 "a=\"c:42foo\"",
352 "a=\"b:42\"bar",
353 "a=\"b:42\" ; m",
354 "a=\"b:42\" ; min-age",
355 "a=\"b:42\" ; ma",
356 "a=\"b:42\" ; ma=",
357 "a=\"b:42\" ; v=\"..\"",
358 "a=\"b:42\" ; ma=ma",
359 "a=\"b:42\" ; ma=123bar",
360 "a=\"b:42\" ; v=24",
361 "a=\"b:42\" ; v=24,25",
362 "a=\"b:42\" ; v=\"-3\"",
363 "a=\"b:42\" ; v=\"1.2\"",
364 "a=\"b:42\" ; v=\"24,\""};
365 for (const char* invalid_field_value : invalid_field_value_array) {
366 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
367 invalid_field_value, &altsvc_vector))
368 << invalid_field_value;
369 }
370 }
371
372 // ParseHeaderFieldValue() should return false on a field values truncated
373 // before closing quotation mark, without trying to access memory beyond the end
374 // of the input.
TEST(SpdyAltSvcWireFormatTest,ParseTruncatedHeaderFieldValue)375 TEST(SpdyAltSvcWireFormatTest, ParseTruncatedHeaderFieldValue) {
376 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
377 const char* field_value_array[] = {"a=\":137\"", "a=\"foo:137\"",
378 "a%25=\"foo\\\"bar\\\\baz:137\""};
379 for (const std::string& field_value : field_value_array) {
380 for (size_t len = 1; len < field_value.size(); ++len) {
381 EXPECT_FALSE(SpdyAltSvcWireFormat::ParseHeaderFieldValue(
382 field_value.substr(0, len), &altsvc_vector))
383 << len;
384 }
385 }
386 }
387
388 // Tests of private methods.
389
390 // Test SkipWhiteSpace().
TEST(SpdyAltSvcWireFormatTest,SkipWhiteSpace)391 TEST(SpdyAltSvcWireFormatTest, SkipWhiteSpace) {
392 quiche::QuicheStringPiece input("a \tb ");
393 quiche::QuicheStringPiece::const_iterator c = input.begin();
394 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
395 ASSERT_EQ(input.begin(), c);
396 ++c;
397 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
398 ASSERT_EQ(input.begin() + 3, c);
399 ++c;
400 test::SpdyAltSvcWireFormatPeer::SkipWhiteSpace(&c, input.end());
401 ASSERT_EQ(input.end(), c);
402 }
403
404 // Test PercentDecode() on valid input.
TEST(SpdyAltSvcWireFormatTest,PercentDecodeValid)405 TEST(SpdyAltSvcWireFormatTest, PercentDecodeValid) {
406 quiche::QuicheStringPiece input("");
407 std::string output;
408 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
409 input.begin(), input.end(), &output));
410 EXPECT_EQ("", output);
411
412 input = quiche::QuicheStringPiece("foo");
413 output.clear();
414 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
415 input.begin(), input.end(), &output));
416 EXPECT_EQ("foo", output);
417
418 input = quiche::QuicheStringPiece("%2ca%5Cb");
419 output.clear();
420 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
421 input.begin(), input.end(), &output));
422 EXPECT_EQ(",a\\b", output);
423 }
424
425 // Test PercentDecode() on invalid input.
TEST(SpdyAltSvcWireFormatTest,PercentDecodeInvalid)426 TEST(SpdyAltSvcWireFormatTest, PercentDecodeInvalid) {
427 const char* invalid_input_array[] = {"a%", "a%x", "a%b", "%J22", "%9z"};
428 for (const char* invalid_input : invalid_input_array) {
429 quiche::QuicheStringPiece input(invalid_input);
430 std::string output;
431 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::PercentDecode(
432 input.begin(), input.end(), &output))
433 << input;
434 }
435 }
436
437 // Test ParseAltAuthority() on valid input.
TEST(SpdyAltSvcWireFormatTest,ParseAltAuthorityValid)438 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityValid) {
439 quiche::QuicheStringPiece input(":42");
440 std::string host;
441 uint16_t port;
442 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
443 input.begin(), input.end(), &host, &port));
444 EXPECT_TRUE(host.empty());
445 EXPECT_EQ(42, port);
446
447 input = quiche::QuicheStringPiece("foo:137");
448 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
449 input.begin(), input.end(), &host, &port));
450 EXPECT_EQ("foo", host);
451 EXPECT_EQ(137, port);
452
453 input = quiche::QuicheStringPiece("[2003:8:0:16::509d:9615]:443");
454 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
455 input.begin(), input.end(), &host, &port));
456 EXPECT_EQ("[2003:8:0:16::509d:9615]", host);
457 EXPECT_EQ(443, port);
458 }
459
460 // Test ParseAltAuthority() on invalid input: empty string, no port, zero port,
461 // non-digit characters following port.
TEST(SpdyAltSvcWireFormatTest,ParseAltAuthorityInvalid)462 TEST(SpdyAltSvcWireFormatTest, ParseAltAuthorityInvalid) {
463 const char* invalid_input_array[] = {"",
464 ":",
465 "foo:",
466 ":bar",
467 ":0",
468 "foo:0",
469 ":12bar",
470 "foo:23bar",
471 " ",
472 ":12 ",
473 "foo:12 ",
474 "[2003:8:0:16::509d:9615]",
475 "[2003:8:0:16::509d:9615]:",
476 "[2003:8:0:16::509d:9615]foo:443",
477 "[2003:8:0:16::509d:9615:443",
478 "2003:8:0:16::509d:9615]:443"};
479 for (const char* invalid_input : invalid_input_array) {
480 quiche::QuicheStringPiece input(invalid_input);
481 std::string host;
482 uint16_t port;
483 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParseAltAuthority(
484 input.begin(), input.end(), &host, &port))
485 << input;
486 }
487 }
488
489 // Test ParseInteger() on valid input.
TEST(SpdyAltSvcWireFormatTest,ParseIntegerValid)490 TEST(SpdyAltSvcWireFormatTest, ParseIntegerValid) {
491 quiche::QuicheStringPiece input("3");
492 uint16_t value;
493 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
494 input.begin(), input.end(), &value));
495 EXPECT_EQ(3, value);
496
497 input = quiche::QuicheStringPiece("1337");
498 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
499 input.begin(), input.end(), &value));
500 EXPECT_EQ(1337, value);
501 }
502
503 // Test ParseIntegerValid() on invalid input: empty, zero, non-numeric, trailing
504 // non-numeric characters.
TEST(SpdyAltSvcWireFormatTest,ParseIntegerInvalid)505 TEST(SpdyAltSvcWireFormatTest, ParseIntegerInvalid) {
506 const char* invalid_input_array[] = {"", " ", "a", "0", "00", "1 ", "12b"};
507 for (const char* invalid_input : invalid_input_array) {
508 quiche::QuicheStringPiece input(invalid_input);
509 uint16_t value;
510 EXPECT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
511 input.begin(), input.end(), &value))
512 << input;
513 }
514 }
515
516 // Test ParseIntegerValid() around overflow limit.
TEST(SpdyAltSvcWireFormatTest,ParseIntegerOverflow)517 TEST(SpdyAltSvcWireFormatTest, ParseIntegerOverflow) {
518 // Largest possible uint16_t value.
519 quiche::QuicheStringPiece input("65535");
520 uint16_t value16;
521 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
522 input.begin(), input.end(), &value16));
523 EXPECT_EQ(65535, value16);
524
525 // Overflow uint16_t, ParsePositiveInteger16() should return false.
526 input = quiche::QuicheStringPiece("65536");
527 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
528 input.begin(), input.end(), &value16));
529
530 // However, even if overflow is not checked for, 65536 overflows to 0, which
531 // returns false anyway. Check for a larger number which overflows to 1.
532 input = quiche::QuicheStringPiece("65537");
533 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger16(
534 input.begin(), input.end(), &value16));
535
536 // Largest possible uint32_t value.
537 input = quiche::QuicheStringPiece("4294967295");
538 uint32_t value32;
539 ASSERT_TRUE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
540 input.begin(), input.end(), &value32));
541 EXPECT_EQ(4294967295, value32);
542
543 // Overflow uint32_t, ParsePositiveInteger32() should return false.
544 input = quiche::QuicheStringPiece("4294967296");
545 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
546 input.begin(), input.end(), &value32));
547
548 // However, even if overflow is not checked for, 4294967296 overflows to 0,
549 // which returns false anyway. Check for a larger number which overflows to
550 // 1.
551 input = quiche::QuicheStringPiece("4294967297");
552 ASSERT_FALSE(test::SpdyAltSvcWireFormatPeer::ParsePositiveInteger32(
553 input.begin(), input.end(), &value32));
554 }
555
556 // Test parsing an Alt-Svc entry with IP literal hostname.
557 // Regression test for https://crbug.com/664173.
TEST(SpdyAltSvcWireFormatTest,ParseIPLiteral)558 TEST(SpdyAltSvcWireFormatTest, ParseIPLiteral) {
559 const char* input =
560 "quic=\"[2003:8:0:16::509d:9615]:443\"; v=\"36,35\"; ma=60";
561 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
562 ASSERT_TRUE(
563 SpdyAltSvcWireFormat::ParseHeaderFieldValue(input, &altsvc_vector));
564 EXPECT_EQ(1u, altsvc_vector.size());
565 EXPECT_EQ("quic", altsvc_vector[0].protocol_id);
566 EXPECT_EQ("[2003:8:0:16::509d:9615]", altsvc_vector[0].host);
567 EXPECT_EQ(443u, altsvc_vector[0].port);
568 EXPECT_EQ(60u, altsvc_vector[0].max_age);
569 EXPECT_THAT(altsvc_vector[0].version, ::testing::ElementsAre(36, 35));
570 }
571
572 } // namespace
573
574 } // namespace spdy
575