xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/adapter/header_validator_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 #include "quiche/http2/adapter/header_validator.h"
2 
3 #include <optional>
4 #include <utility>
5 #include <vector>
6 
7 #include "absl/strings/str_cat.h"
8 #include "quiche/common/platform/api/quiche_test.h"
9 
10 namespace http2 {
11 namespace adapter {
12 namespace test {
13 
14 using ::testing::Optional;
15 
16 using Header = std::pair<absl::string_view, absl::string_view>;
17 constexpr Header kSampleRequestPseudoheaders[] = {{":authority", "www.foo.com"},
18                                                   {":method", "GET"},
19                                                   {":path", "/foo"},
20                                                   {":scheme", "https"}};
21 
TEST(HeaderValidatorTest,HeaderNameEmpty)22 TEST(HeaderValidatorTest, HeaderNameEmpty) {
23   HeaderValidator v;
24   HeaderValidator::HeaderStatus status = v.ValidateSingleHeader("", "value");
25   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
26 }
27 
TEST(HeaderValidatorTest,HeaderValueEmpty)28 TEST(HeaderValidatorTest, HeaderValueEmpty) {
29   HeaderValidator v;
30   HeaderValidator::HeaderStatus status = v.ValidateSingleHeader("name", "");
31   EXPECT_EQ(HeaderValidator::HEADER_OK, status);
32 }
33 
TEST(HeaderValidatorTest,ExceedsMaxSize)34 TEST(HeaderValidatorTest, ExceedsMaxSize) {
35   HeaderValidator v;
36   v.SetMaxFieldSize(64u);
37   HeaderValidator::HeaderStatus status =
38       v.ValidateSingleHeader("name", "value");
39   EXPECT_EQ(HeaderValidator::HEADER_OK, status);
40   status = v.ValidateSingleHeader(
41       "name2",
42       "Antidisestablishmentariansism is supercalifragilisticexpialodocious.");
43   EXPECT_EQ(HeaderValidator::HEADER_FIELD_TOO_LONG, status);
44 }
45 
TEST(HeaderValidatorTest,NameHasInvalidChar)46 TEST(HeaderValidatorTest, NameHasInvalidChar) {
47   HeaderValidator v;
48   for (const bool is_pseudo_header : {true, false}) {
49     // These characters should be allowed. (Not exhaustive.)
50     for (const char* c : {"!", "3", "a", "_", "|", "~"}) {
51       const std::string name = is_pseudo_header ? absl::StrCat(":met", c, "hod")
52                                                 : absl::StrCat("na", c, "me");
53       HeaderValidator::HeaderStatus status =
54           v.ValidateSingleHeader(name, "value");
55       EXPECT_EQ(HeaderValidator::HEADER_OK, status);
56     }
57     // These should not. (Not exhaustive.)
58     for (const char* c : {"\\", "<", ";", "[", "=", " ", "\r", "\n", ",", "\"",
59                           "\x1F", "\x91"}) {
60       const std::string name = is_pseudo_header ? absl::StrCat(":met", c, "hod")
61                                                 : absl::StrCat("na", c, "me");
62       HeaderValidator::HeaderStatus status =
63           v.ValidateSingleHeader(name, "value");
64       EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status)
65           << "with name [" << name << "]";
66     }
67     // Test nul separately.
68     {
69       const absl::string_view name = is_pseudo_header
70                                          ? absl::string_view(":met\0hod", 8)
71                                          : absl::string_view("na\0me", 5);
72       HeaderValidator::HeaderStatus status =
73           v.ValidateSingleHeader(name, "value");
74       EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
75     }
76     // Uppercase characters in header names should not be allowed.
77     const std::string uc_name = is_pseudo_header ? ":Method" : "Name";
78     HeaderValidator::HeaderStatus status =
79         v.ValidateSingleHeader(uc_name, "value");
80     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
81   }
82 }
83 
TEST(HeaderValidatorTest,ValueHasInvalidChar)84 TEST(HeaderValidatorTest, ValueHasInvalidChar) {
85   HeaderValidator v;
86   // These characters should be allowed. (Not exhaustive.)
87   for (const char* c :
88        {"!", "3", "a", "_", "|", "~", "\\", "<", ";", "[", "=", "A", "\t"}) {
89     const std::string value = absl::StrCat("val", c, "ue");
90     EXPECT_TRUE(
91         HeaderValidator::IsValidHeaderValue(value, ObsTextOption::kDisallow));
92     HeaderValidator::HeaderStatus status =
93         v.ValidateSingleHeader("name", value);
94     EXPECT_EQ(HeaderValidator::HEADER_OK, status);
95   }
96   // These should not.
97   for (const char* c : {"\r", "\n"}) {
98     const std::string value = absl::StrCat("val", c, "ue");
99     EXPECT_FALSE(
100         HeaderValidator::IsValidHeaderValue(value, ObsTextOption::kDisallow));
101     HeaderValidator::HeaderStatus status =
102         v.ValidateSingleHeader("name", value);
103     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
104   }
105   // Test nul separately.
106   {
107     const std::string value("val\0ue", 6);
108     EXPECT_FALSE(
109         HeaderValidator::IsValidHeaderValue(value, ObsTextOption::kDisallow));
110     HeaderValidator::HeaderStatus status =
111         v.ValidateSingleHeader("name", value);
112     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
113   }
114   {
115     const std::string obs_text_value = "val\xa9ue";
116     // Test that obs-text is disallowed by default.
117     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
118               v.ValidateSingleHeader("name", obs_text_value));
119     // Test that obs-text is disallowed when configured.
120     v.SetObsTextOption(ObsTextOption::kDisallow);
121     EXPECT_FALSE(HeaderValidator::IsValidHeaderValue(obs_text_value,
122                                                      ObsTextOption::kDisallow));
123     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
124               v.ValidateSingleHeader("name", obs_text_value));
125     // Test that obs-text is allowed when configured.
126     v.SetObsTextOption(ObsTextOption::kAllow);
127     EXPECT_TRUE(HeaderValidator::IsValidHeaderValue(obs_text_value,
128                                                     ObsTextOption::kAllow));
129     EXPECT_EQ(HeaderValidator::HEADER_OK,
130               v.ValidateSingleHeader("name", obs_text_value));
131   }
132 }
133 
TEST(HeaderValidatorTest,StatusHasInvalidChar)134 TEST(HeaderValidatorTest, StatusHasInvalidChar) {
135   HeaderValidator v;
136 
137   for (HeaderType type : {HeaderType::RESPONSE, HeaderType::RESPONSE_100}) {
138     // When `:status` has a non-digit value, validation will fail.
139     v.StartHeaderBlock();
140     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
141               v.ValidateSingleHeader(":status", "bar"));
142     EXPECT_FALSE(v.FinishHeaderBlock(type));
143 
144     // When `:status` is too short, validation will fail.
145     v.StartHeaderBlock();
146     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
147               v.ValidateSingleHeader(":status", "10"));
148     EXPECT_FALSE(v.FinishHeaderBlock(type));
149 
150     // When `:status` is too long, validation will fail.
151     v.StartHeaderBlock();
152     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
153               v.ValidateSingleHeader(":status", "9000"));
154     EXPECT_FALSE(v.FinishHeaderBlock(type));
155 
156     // When `:status` is just right, validation will succeed.
157     v.StartHeaderBlock();
158     EXPECT_EQ(HeaderValidator::HEADER_OK,
159               v.ValidateSingleHeader(":status", "400"));
160     EXPECT_TRUE(v.FinishHeaderBlock(type));
161   }
162 }
163 
TEST(HeaderValidatorTest,AuthorityHasInvalidChar)164 TEST(HeaderValidatorTest, AuthorityHasInvalidChar) {
165   for (absl::string_view key : {":authority", "host"}) {
166     // These characters should be allowed. (Not exhaustive.)
167     for (const absl::string_view c : {"1", "-", "!", ":", "+", "=", ","}) {
168       const std::string value = absl::StrCat("ho", c, "st.example.com");
169       EXPECT_TRUE(HeaderValidator::IsValidAuthority(value));
170 
171       HeaderValidator v;
172       v.StartHeaderBlock();
173       HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value);
174       EXPECT_EQ(HeaderValidator::HEADER_OK, status)
175           << " with name [" << key << "] and value [" << value << "]";
176     }
177     // These should not.
178     for (const absl::string_view c : {"\r", "\n", "|", "\\", "`"}) {
179       const std::string value = absl::StrCat("ho", c, "st.example.com");
180       EXPECT_FALSE(HeaderValidator::IsValidAuthority(value));
181 
182       HeaderValidator v;
183       v.StartHeaderBlock();
184       HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value);
185       EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID, status);
186     }
187 
188     {
189       // IPv4 example
190       const std::string value = "123.45.67.89";
191       EXPECT_TRUE(HeaderValidator::IsValidAuthority(value));
192 
193       HeaderValidator v;
194       v.StartHeaderBlock();
195       HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, value);
196       EXPECT_EQ(HeaderValidator::HEADER_OK, status);
197     }
198 
199     {
200       // IPv6 examples
201       const std::string value1 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
202       EXPECT_TRUE(HeaderValidator::IsValidAuthority(value1));
203 
204       HeaderValidator v;
205       v.StartHeaderBlock();
206       HeaderValidator::HeaderStatus status =
207           v.ValidateSingleHeader(key, value1);
208       EXPECT_EQ(HeaderValidator::HEADER_OK, status);
209 
210       const std::string value2 = "[::1]:80";
211       EXPECT_TRUE(HeaderValidator::IsValidAuthority(value2));
212       HeaderValidator v2;
213       v2.StartHeaderBlock();
214       status = v2.ValidateSingleHeader(key, value2);
215       EXPECT_EQ(HeaderValidator::HEADER_OK, status);
216     }
217 
218     {
219       // Empty field
220       EXPECT_TRUE(HeaderValidator::IsValidAuthority(""));
221 
222       HeaderValidator v;
223       v.StartHeaderBlock();
224       HeaderValidator::HeaderStatus status = v.ValidateSingleHeader(key, "");
225       EXPECT_EQ(HeaderValidator::HEADER_OK, status);
226     }
227   }
228 }
229 
TEST(HeaderValidatorTest,RequestHostAndAuthority)230 TEST(HeaderValidatorTest, RequestHostAndAuthority) {
231   HeaderValidator v;
232   v.StartHeaderBlock();
233   for (Header to_add : kSampleRequestPseudoheaders) {
234     EXPECT_EQ(HeaderValidator::HEADER_OK,
235               v.ValidateSingleHeader(to_add.first, to_add.second));
236   }
237   // If both "host" and ":authority" have the same value, validation succeeds.
238   EXPECT_EQ(HeaderValidator::HEADER_OK,
239             v.ValidateSingleHeader("host", "www.foo.com"));
240   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
241 
242   v.StartHeaderBlock();
243   for (Header to_add : kSampleRequestPseudoheaders) {
244     EXPECT_EQ(HeaderValidator::HEADER_OK,
245               v.ValidateSingleHeader(to_add.first, to_add.second));
246   }
247   // If "host" and ":authority" have different values, validation fails.
248   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
249             v.ValidateSingleHeader("host", "www.bar.com"));
250 }
251 
TEST(HeaderValidatorTest,RequestHostAndAuthorityLax)252 TEST(HeaderValidatorTest, RequestHostAndAuthorityLax) {
253   HeaderValidator v;
254   v.SetAllowDifferentHostAndAuthority();
255   v.StartHeaderBlock();
256   for (Header to_add : kSampleRequestPseudoheaders) {
257     EXPECT_EQ(HeaderValidator::HEADER_OK,
258               v.ValidateSingleHeader(to_add.first, to_add.second));
259   }
260   // Since the option is set, validation succeeds even if "host" and
261   // ":authority" have different values.
262   EXPECT_EQ(HeaderValidator::HEADER_OK,
263             v.ValidateSingleHeader("host", "www.bar.com"));
264 }
265 
TEST(HeaderValidatorTest,MethodHasInvalidChar)266 TEST(HeaderValidatorTest, MethodHasInvalidChar) {
267   HeaderValidator v;
268   v.StartHeaderBlock();
269 
270   std::vector<absl::string_view> bad_methods = {
271       "In[]valid{}",   "co,mma", "spac e",     "a@t",    "equals=",
272       "question?mark", "co:lon", "semi;colon", "sla/sh", "back\\slash",
273   };
274 
275   std::vector<absl::string_view> good_methods = {
276       "lowercase",   "MiXeDcAsE", "NONCANONICAL", "HASH#",
277       "under_score", "PI|PE",     "Tilde~",       "quote'",
278   };
279 
280   for (absl::string_view value : bad_methods) {
281     v.StartHeaderBlock();
282     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
283               v.ValidateSingleHeader(":method", value));
284   }
285 
286   for (absl::string_view value : good_methods) {
287     v.StartHeaderBlock();
288     EXPECT_EQ(HeaderValidator::HEADER_OK,
289               v.ValidateSingleHeader(":method", value));
290     for (Header to_add : kSampleRequestPseudoheaders) {
291       if (to_add.first == ":method") {
292         continue;
293       }
294       EXPECT_EQ(HeaderValidator::HEADER_OK,
295                 v.ValidateSingleHeader(to_add.first, to_add.second));
296     }
297     EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
298   }
299 }
300 
TEST(HeaderValidatorTest,RequestPseudoHeaders)301 TEST(HeaderValidatorTest, RequestPseudoHeaders) {
302   HeaderValidator v;
303   for (Header to_skip : kSampleRequestPseudoheaders) {
304     v.StartHeaderBlock();
305     for (Header to_add : kSampleRequestPseudoheaders) {
306       if (to_add != to_skip) {
307         EXPECT_EQ(HeaderValidator::HEADER_OK,
308                   v.ValidateSingleHeader(to_add.first, to_add.second));
309       }
310     }
311     // When any pseudo-header is missing, final validation will fail.
312     EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
313   }
314 
315   // When all pseudo-headers are present, final validation will succeed.
316   v.StartHeaderBlock();
317   for (Header to_add : kSampleRequestPseudoheaders) {
318     EXPECT_EQ(HeaderValidator::HEADER_OK,
319               v.ValidateSingleHeader(to_add.first, to_add.second));
320   }
321   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
322 
323   // When an extra pseudo-header is present, final validation will fail.
324   v.StartHeaderBlock();
325   for (Header to_add : kSampleRequestPseudoheaders) {
326     EXPECT_EQ(HeaderValidator::HEADER_OK,
327               v.ValidateSingleHeader(to_add.first, to_add.second));
328   }
329   EXPECT_EQ(HeaderValidator::HEADER_OK,
330             v.ValidateSingleHeader(":extra", "blah"));
331   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
332 
333   // When a required pseudo-header is repeated, final validation will fail.
334   for (Header to_repeat : kSampleRequestPseudoheaders) {
335     v.StartHeaderBlock();
336     for (Header to_add : kSampleRequestPseudoheaders) {
337       EXPECT_EQ(HeaderValidator::HEADER_OK,
338                 v.ValidateSingleHeader(to_add.first, to_add.second));
339       if (to_add == to_repeat) {
340         EXPECT_EQ(HeaderValidator::HEADER_OK,
341                   v.ValidateSingleHeader(to_add.first, to_add.second));
342       }
343     }
344     EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
345   }
346 }
347 
TEST(HeaderValidatorTest,ConnectHeaders)348 TEST(HeaderValidatorTest, ConnectHeaders) {
349   // Too few headers.
350   HeaderValidator v;
351   v.StartHeaderBlock();
352   EXPECT_EQ(HeaderValidator::HEADER_OK,
353             v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
354   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
355 
356   v.StartHeaderBlock();
357   EXPECT_EQ(HeaderValidator::HEADER_OK,
358             v.ValidateSingleHeader(":method", "CONNECT"));
359   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
360 
361   // Too many headers.
362   v.StartHeaderBlock();
363   EXPECT_EQ(HeaderValidator::HEADER_OK,
364             v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
365   EXPECT_EQ(HeaderValidator::HEADER_OK,
366             v.ValidateSingleHeader(":method", "CONNECT"));
367   EXPECT_EQ(HeaderValidator::HEADER_OK, v.ValidateSingleHeader(":path", "/"));
368   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
369 
370   // Empty :authority
371   v.StartHeaderBlock();
372   EXPECT_EQ(HeaderValidator::HEADER_OK,
373             v.ValidateSingleHeader(":authority", ""));
374   EXPECT_EQ(HeaderValidator::HEADER_OK,
375             v.ValidateSingleHeader(":method", "CONNECT"));
376   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
377 
378   // Just right.
379   v.StartHeaderBlock();
380   EXPECT_EQ(HeaderValidator::HEADER_OK,
381             v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
382   EXPECT_EQ(HeaderValidator::HEADER_OK,
383             v.ValidateSingleHeader(":method", "CONNECT"));
384   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
385 
386   v.SetAllowExtendedConnect();
387   // "Classic" CONNECT headers should still be accepted.
388   v.StartHeaderBlock();
389   EXPECT_EQ(HeaderValidator::HEADER_OK,
390             v.ValidateSingleHeader(":authority", "athena.dialup.mit.edu:23"));
391   EXPECT_EQ(HeaderValidator::HEADER_OK,
392             v.ValidateSingleHeader(":method", "CONNECT"));
393   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
394 }
395 
TEST(HeaderValidatorTest,WebsocketPseudoHeaders)396 TEST(HeaderValidatorTest, WebsocketPseudoHeaders) {
397   HeaderValidator v;
398   v.StartHeaderBlock();
399   for (Header to_add : kSampleRequestPseudoheaders) {
400     EXPECT_EQ(HeaderValidator::HEADER_OK,
401               v.ValidateSingleHeader(to_add.first, to_add.second));
402   }
403   EXPECT_EQ(HeaderValidator::HEADER_OK,
404             v.ValidateSingleHeader(":protocol", "websocket"));
405   // At this point, `:protocol` is treated as an extra pseudo-header.
406   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
407 
408   // Future header blocks may send the `:protocol` pseudo-header for CONNECT
409   // requests.
410   v.SetAllowExtendedConnect();
411 
412   v.StartHeaderBlock();
413   for (Header to_add : kSampleRequestPseudoheaders) {
414     EXPECT_EQ(HeaderValidator::HEADER_OK,
415               v.ValidateSingleHeader(to_add.first, to_add.second));
416   }
417   EXPECT_EQ(HeaderValidator::HEADER_OK,
418             v.ValidateSingleHeader(":protocol", "websocket"));
419   // The method is not "CONNECT", so `:protocol` is still treated as an extra
420   // pseudo-header.
421   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
422 
423   v.StartHeaderBlock();
424   for (Header to_add : kSampleRequestPseudoheaders) {
425     if (to_add.first == ":method") {
426       EXPECT_EQ(HeaderValidator::HEADER_OK,
427                 v.ValidateSingleHeader(to_add.first, "CONNECT"));
428     } else {
429       EXPECT_EQ(HeaderValidator::HEADER_OK,
430                 v.ValidateSingleHeader(to_add.first, to_add.second));
431     }
432   }
433   EXPECT_EQ(HeaderValidator::HEADER_OK,
434             v.ValidateSingleHeader(":protocol", "websocket"));
435   // After allowing the method, `:protocol` is acepted for CONNECT requests.
436   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
437 }
438 
TEST(HeaderValidatorTest,AsteriskPathPseudoHeader)439 TEST(HeaderValidatorTest, AsteriskPathPseudoHeader) {
440   HeaderValidator v;
441 
442   // An asterisk :path should not be allowed for non-OPTIONS requests.
443   v.StartHeaderBlock();
444   for (Header to_add : kSampleRequestPseudoheaders) {
445     if (to_add.first == ":path") {
446       EXPECT_EQ(HeaderValidator::HEADER_OK,
447                 v.ValidateSingleHeader(to_add.first, "*"));
448     } else {
449       EXPECT_EQ(HeaderValidator::HEADER_OK,
450                 v.ValidateSingleHeader(to_add.first, to_add.second));
451     }
452   }
453   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
454 
455   // An asterisk :path should be allowed for OPTIONS requests.
456   v.StartHeaderBlock();
457   for (Header to_add : kSampleRequestPseudoheaders) {
458     if (to_add.first == ":path") {
459       EXPECT_EQ(HeaderValidator::HEADER_OK,
460                 v.ValidateSingleHeader(to_add.first, "*"));
461     } else if (to_add.first == ":method") {
462       EXPECT_EQ(HeaderValidator::HEADER_OK,
463                 v.ValidateSingleHeader(to_add.first, "OPTIONS"));
464     } else {
465       EXPECT_EQ(HeaderValidator::HEADER_OK,
466                 v.ValidateSingleHeader(to_add.first, to_add.second));
467     }
468   }
469   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::REQUEST));
470 }
471 
TEST(HeaderValidatorTest,InvalidPathPseudoHeader)472 TEST(HeaderValidatorTest, InvalidPathPseudoHeader) {
473   HeaderValidator v;
474 
475   // An empty path should fail on single header validation and finish.
476   v.StartHeaderBlock();
477   for (Header to_add : kSampleRequestPseudoheaders) {
478     if (to_add.first == ":path") {
479       EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
480                 v.ValidateSingleHeader(to_add.first, ""));
481     } else {
482       EXPECT_EQ(HeaderValidator::HEADER_OK,
483                 v.ValidateSingleHeader(to_add.first, to_add.second));
484     }
485   }
486   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
487 
488   // The remainder of the checks require enabling path validation.
489   v.SetValidatePath();
490 
491   // A path that does not start with a slash should fail on finish.
492   v.StartHeaderBlock();
493   for (Header to_add : kSampleRequestPseudoheaders) {
494     if (to_add.first == ":path") {
495       EXPECT_EQ(HeaderValidator::HEADER_OK,
496                 v.ValidateSingleHeader(to_add.first, "shawarma"));
497     } else {
498       EXPECT_EQ(HeaderValidator::HEADER_OK,
499                 v.ValidateSingleHeader(to_add.first, to_add.second));
500     }
501   }
502   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::REQUEST));
503 
504   // Various valid path characters.
505   for (const absl::string_view c :
506        {"/", "?", "_", "'", "9", "&", "(", "@", ":"}) {
507     const std::string value = absl::StrCat("/shawa", c, "rma");
508 
509     HeaderValidator validator;
510     validator.SetValidatePath();
511     validator.StartHeaderBlock();
512     for (Header to_add : kSampleRequestPseudoheaders) {
513       if (to_add.first == ":path") {
514         EXPECT_EQ(HeaderValidator::HEADER_OK,
515                   validator.ValidateSingleHeader(to_add.first, value))
516             << "Problematic char: [" << c << "]";
517       } else {
518         EXPECT_EQ(HeaderValidator::HEADER_OK,
519                   validator.ValidateSingleHeader(to_add.first, to_add.second));
520       }
521     }
522     EXPECT_TRUE(validator.FinishHeaderBlock(HeaderType::REQUEST));
523   }
524 
525   // Various invalid path characters.
526   for (const absl::string_view c : {"[", "<", "}", "`", "\\", " ", "\t", "#"}) {
527     const std::string value = absl::StrCat("/shawa", c, "rma");
528 
529     HeaderValidator validator;
530     validator.SetValidatePath();
531     validator.StartHeaderBlock();
532     for (Header to_add : kSampleRequestPseudoheaders) {
533       if (to_add.first == ":path") {
534         EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
535                   validator.ValidateSingleHeader(to_add.first, value));
536       } else {
537         EXPECT_EQ(HeaderValidator::HEADER_OK,
538                   validator.ValidateSingleHeader(to_add.first, to_add.second));
539       }
540     }
541     EXPECT_FALSE(validator.FinishHeaderBlock(HeaderType::REQUEST));
542   }
543 
544   // The fragment initial character can be explicitly allowed.
545   {
546     HeaderValidator validator;
547     validator.SetValidatePath();
548     validator.SetAllowFragmentInPath();
549     validator.StartHeaderBlock();
550     for (Header to_add : kSampleRequestPseudoheaders) {
551       if (to_add.first == ":path") {
552         EXPECT_EQ(HeaderValidator::HEADER_OK,
553                   validator.ValidateSingleHeader(to_add.first, "/shawa#rma"));
554       } else {
555         EXPECT_EQ(HeaderValidator::HEADER_OK,
556                   validator.ValidateSingleHeader(to_add.first, to_add.second));
557       }
558     }
559     EXPECT_TRUE(validator.FinishHeaderBlock(HeaderType::REQUEST));
560   }
561 }
562 
TEST(HeaderValidatorTest,ResponsePseudoHeaders)563 TEST(HeaderValidatorTest, ResponsePseudoHeaders) {
564   HeaderValidator v;
565 
566   for (HeaderType type : {HeaderType::RESPONSE, HeaderType::RESPONSE_100}) {
567     // When `:status` is missing, validation will fail.
568     v.StartHeaderBlock();
569     EXPECT_EQ(HeaderValidator::HEADER_OK, v.ValidateSingleHeader("foo", "bar"));
570     EXPECT_FALSE(v.FinishHeaderBlock(type));
571 
572     // When all pseudo-headers are present, final validation will succeed.
573     v.StartHeaderBlock();
574     EXPECT_EQ(HeaderValidator::HEADER_OK,
575               v.ValidateSingleHeader(":status", "199"));
576     EXPECT_TRUE(v.FinishHeaderBlock(type));
577     EXPECT_EQ("199", v.status_header());
578 
579     // When `:status` is repeated, validation will fail.
580     v.StartHeaderBlock();
581     EXPECT_EQ(HeaderValidator::HEADER_OK,
582               v.ValidateSingleHeader(":status", "199"));
583     EXPECT_EQ(HeaderValidator::HEADER_OK,
584               v.ValidateSingleHeader(":status", "299"));
585     EXPECT_FALSE(v.FinishHeaderBlock(type));
586 
587     // When an extra pseudo-header is present, final validation will fail.
588     v.StartHeaderBlock();
589     EXPECT_EQ(HeaderValidator::HEADER_OK,
590               v.ValidateSingleHeader(":status", "199"));
591     EXPECT_EQ(HeaderValidator::HEADER_OK,
592               v.ValidateSingleHeader(":extra", "blorp"));
593     EXPECT_FALSE(v.FinishHeaderBlock(type));
594   }
595 }
596 
TEST(HeaderValidatorTest,ResponseWithHost)597 TEST(HeaderValidatorTest, ResponseWithHost) {
598   HeaderValidator v;
599 
600   v.StartHeaderBlock();
601   EXPECT_EQ(HeaderValidator::HEADER_OK,
602             v.ValidateSingleHeader(":status", "200"));
603   EXPECT_EQ(HeaderValidator::HEADER_OK,
604             v.ValidateSingleHeader("host", "myserver.com"));
605   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE));
606 }
607 
TEST(HeaderValidatorTest,Response204)608 TEST(HeaderValidatorTest, Response204) {
609   HeaderValidator v;
610 
611   v.StartHeaderBlock();
612   EXPECT_EQ(HeaderValidator::HEADER_OK,
613             v.ValidateSingleHeader(":status", "204"));
614   EXPECT_EQ(HeaderValidator::HEADER_OK,
615             v.ValidateSingleHeader("x-content", "is not present"));
616   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE));
617 }
618 
TEST(HeaderValidatorTest,ResponseWithMultipleIdenticalContentLength)619 TEST(HeaderValidatorTest, ResponseWithMultipleIdenticalContentLength) {
620   HeaderValidator v;
621 
622   v.StartHeaderBlock();
623   EXPECT_EQ(HeaderValidator::HEADER_OK,
624             v.ValidateSingleHeader(":status", "200"));
625   EXPECT_EQ(HeaderValidator::HEADER_OK,
626             v.ValidateSingleHeader("content-length", "13"));
627   EXPECT_EQ(HeaderValidator::HEADER_SKIP,
628             v.ValidateSingleHeader("content-length", "13"));
629 }
630 
TEST(HeaderValidatorTest,ResponseWithMultipleDifferingContentLength)631 TEST(HeaderValidatorTest, ResponseWithMultipleDifferingContentLength) {
632   HeaderValidator v;
633 
634   v.StartHeaderBlock();
635   EXPECT_EQ(HeaderValidator::HEADER_OK,
636             v.ValidateSingleHeader(":status", "200"));
637   EXPECT_EQ(HeaderValidator::HEADER_OK,
638             v.ValidateSingleHeader("content-length", "13"));
639   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
640             v.ValidateSingleHeader("content-length", "17"));
641 }
642 
TEST(HeaderValidatorTest,Response204WithContentLengthZero)643 TEST(HeaderValidatorTest, Response204WithContentLengthZero) {
644   HeaderValidator v;
645 
646   v.StartHeaderBlock();
647   EXPECT_EQ(HeaderValidator::HEADER_OK,
648             v.ValidateSingleHeader(":status", "204"));
649   EXPECT_EQ(HeaderValidator::HEADER_OK,
650             v.ValidateSingleHeader("x-content", "is not present"));
651   EXPECT_EQ(HeaderValidator::HEADER_OK,
652             v.ValidateSingleHeader("content-length", "0"));
653   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE));
654 }
655 
TEST(HeaderValidatorTest,Response204WithContentLength)656 TEST(HeaderValidatorTest, Response204WithContentLength) {
657   HeaderValidator v;
658 
659   v.StartHeaderBlock();
660   EXPECT_EQ(HeaderValidator::HEADER_OK,
661             v.ValidateSingleHeader(":status", "204"));
662   EXPECT_EQ(HeaderValidator::HEADER_OK,
663             v.ValidateSingleHeader("x-content", "is not present"));
664   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
665             v.ValidateSingleHeader("content-length", "1"));
666 }
667 
TEST(HeaderValidatorTest,Response100)668 TEST(HeaderValidatorTest, Response100) {
669   HeaderValidator v;
670 
671   v.StartHeaderBlock();
672   EXPECT_EQ(HeaderValidator::HEADER_OK,
673             v.ValidateSingleHeader(":status", "100"));
674   EXPECT_EQ(HeaderValidator::HEADER_OK,
675             v.ValidateSingleHeader("x-content", "is not present"));
676   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE));
677 }
678 
TEST(HeaderValidatorTest,Response100WithContentLengthZero)679 TEST(HeaderValidatorTest, Response100WithContentLengthZero) {
680   HeaderValidator v;
681 
682   v.StartHeaderBlock();
683   EXPECT_EQ(HeaderValidator::HEADER_OK,
684             v.ValidateSingleHeader(":status", "100"));
685   EXPECT_EQ(HeaderValidator::HEADER_OK,
686             v.ValidateSingleHeader("x-content", "is not present"));
687   EXPECT_EQ(HeaderValidator::HEADER_OK,
688             v.ValidateSingleHeader("content-length", "0"));
689   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE));
690 }
691 
TEST(HeaderValidatorTest,Response100WithContentLength)692 TEST(HeaderValidatorTest, Response100WithContentLength) {
693   HeaderValidator v;
694 
695   v.StartHeaderBlock();
696   EXPECT_EQ(HeaderValidator::HEADER_OK,
697             v.ValidateSingleHeader(":status", "100"));
698   EXPECT_EQ(HeaderValidator::HEADER_OK,
699             v.ValidateSingleHeader("x-content", "is not present"));
700   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
701             v.ValidateSingleHeader("content-length", "1"));
702 }
703 
TEST(HeaderValidatorTest,ResponseTrailerPseudoHeaders)704 TEST(HeaderValidatorTest, ResponseTrailerPseudoHeaders) {
705   HeaderValidator v;
706 
707   // When no pseudo-headers are present, validation will succeed.
708   v.StartHeaderBlock();
709   EXPECT_EQ(HeaderValidator::HEADER_OK, v.ValidateSingleHeader("foo", "bar"));
710   EXPECT_TRUE(v.FinishHeaderBlock(HeaderType::RESPONSE_TRAILER));
711 
712   // When any pseudo-header is present, final validation will fail.
713   v.StartHeaderBlock();
714   EXPECT_EQ(HeaderValidator::HEADER_OK,
715             v.ValidateSingleHeader(":status", "200"));
716   EXPECT_EQ(HeaderValidator::HEADER_OK, v.ValidateSingleHeader("foo", "bar"));
717   EXPECT_FALSE(v.FinishHeaderBlock(HeaderType::RESPONSE_TRAILER));
718 }
719 
TEST(HeaderValidatorTest,ValidContentLength)720 TEST(HeaderValidatorTest, ValidContentLength) {
721   HeaderValidator v;
722 
723   v.StartHeaderBlock();
724   EXPECT_EQ(v.content_length(), std::nullopt);
725   EXPECT_EQ(HeaderValidator::HEADER_OK,
726             v.ValidateSingleHeader("content-length", "41"));
727   EXPECT_THAT(v.content_length(), Optional(41));
728 
729   v.StartHeaderBlock();
730   EXPECT_EQ(v.content_length(), std::nullopt);
731   EXPECT_EQ(HeaderValidator::HEADER_OK,
732             v.ValidateSingleHeader("content-length", "42"));
733   EXPECT_THAT(v.content_length(), Optional(42));
734 }
735 
TEST(HeaderValidatorTest,InvalidContentLength)736 TEST(HeaderValidatorTest, InvalidContentLength) {
737   HeaderValidator v;
738 
739   v.StartHeaderBlock();
740   EXPECT_EQ(v.content_length(), std::nullopt);
741   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
742             v.ValidateSingleHeader("content-length", ""));
743   EXPECT_EQ(v.content_length(), std::nullopt);
744   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
745             v.ValidateSingleHeader("content-length", "nan"));
746   EXPECT_EQ(v.content_length(), std::nullopt);
747   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
748             v.ValidateSingleHeader("content-length", "-42"));
749   EXPECT_EQ(v.content_length(), std::nullopt);
750   // End on a positive note.
751   EXPECT_EQ(HeaderValidator::HEADER_OK,
752             v.ValidateSingleHeader("content-length", "42"));
753   EXPECT_THAT(v.content_length(), Optional(42));
754 }
755 
TEST(HeaderValidatorTest,TeHeader)756 TEST(HeaderValidatorTest, TeHeader) {
757   HeaderValidator v;
758 
759   v.StartHeaderBlock();
760   EXPECT_EQ(HeaderValidator::HEADER_OK,
761             v.ValidateSingleHeader("te", "trailers"));
762 
763   v.StartHeaderBlock();
764   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
765             v.ValidateSingleHeader("te", "trailers, deflate"));
766 }
767 
TEST(HeaderValidatorTest,ConnectionSpecificHeaders)768 TEST(HeaderValidatorTest, ConnectionSpecificHeaders) {
769   const std::vector<Header> connection_headers = {
770       {"connection", "keep-alive"}, {"proxy-connection", "keep-alive"},
771       {"keep-alive", "timeout=42"}, {"transfer-encoding", "chunked"},
772       {"upgrade", "h2c"},
773   };
774   for (const auto& [connection_key, connection_value] : connection_headers) {
775     HeaderValidator v;
776     v.StartHeaderBlock();
777     for (const auto& [sample_key, sample_value] : kSampleRequestPseudoheaders) {
778       EXPECT_EQ(HeaderValidator::HEADER_OK,
779                 v.ValidateSingleHeader(sample_key, sample_value));
780     }
781     EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
782               v.ValidateSingleHeader(connection_key, connection_value));
783   }
784 }
785 
TEST(HeaderValidatorTest,MixedCaseHeaderName)786 TEST(HeaderValidatorTest, MixedCaseHeaderName) {
787   HeaderValidator v;
788   v.SetAllowUppercaseInHeaderNames();
789   EXPECT_EQ(HeaderValidator::HEADER_OK,
790             v.ValidateSingleHeader("MixedCaseName", "value"));
791 }
792 
793 // SetAllowUppercaseInHeaderNames() only applies to non-pseudo-headers.
TEST(HeaderValidatorTest,MixedCasePseudoHeader)794 TEST(HeaderValidatorTest, MixedCasePseudoHeader) {
795   HeaderValidator v;
796   v.SetAllowUppercaseInHeaderNames();
797   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
798             v.ValidateSingleHeader(":PATH", "/"));
799 }
800 
801 // Matching `host` is case-insensitive.
TEST(HeaderValidatorTest,MixedCaseHost)802 TEST(HeaderValidatorTest, MixedCaseHost) {
803   HeaderValidator v;
804   v.SetAllowUppercaseInHeaderNames();
805   for (Header to_add : kSampleRequestPseudoheaders) {
806     EXPECT_EQ(HeaderValidator::HEADER_OK,
807               v.ValidateSingleHeader(to_add.first, to_add.second));
808   }
809   // Validation fails, because "host" and ":authority" have different values.
810   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
811             v.ValidateSingleHeader("Host", "www.bar.com"));
812 }
813 
814 // Matching `content-length` is case-insensitive.
TEST(HeaderValidatorTest,MixedCaseContentLength)815 TEST(HeaderValidatorTest, MixedCaseContentLength) {
816   HeaderValidator v;
817   v.SetAllowUppercaseInHeaderNames();
818   EXPECT_EQ(v.content_length(), std::nullopt);
819   EXPECT_EQ(HeaderValidator::HEADER_OK,
820             v.ValidateSingleHeader("Content-Length", "42"));
821   EXPECT_THAT(v.content_length(), Optional(42));
822 }
823 
824 }  // namespace test
825 }  // namespace adapter
826 }  // namespace http2
827