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