• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
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/spdy/header_coalescer.h"
6 
7 #include <string>
8 #include <string_view>
9 #include <vector>
10 
11 #include "net/log/net_log.h"
12 #include "net/log/test_net_log.h"
13 #include "net/log/test_net_log_util.h"
14 #include "net/spdy/spdy_test_util_common.h"
15 #include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 using ::testing::ElementsAre;
20 using ::testing::Pair;
21 
22 namespace net::test {
23 
24 class HeaderCoalescerTest : public ::testing::Test {
25  public:
HeaderCoalescerTest()26   HeaderCoalescerTest()
27       : header_coalescer_(kMaxHeaderListSizeForTest, net_log_with_source_) {}
28 
ExpectEntry(std::string_view expected_header_name,std::string_view expected_header_value,std::string_view expected_error_message)29   void ExpectEntry(std::string_view expected_header_name,
30                    std::string_view expected_header_value,
31                    std::string_view expected_error_message) {
32     auto entry_list = net_log_observer_.GetEntries();
33     ASSERT_EQ(1u, entry_list.size());
34     EXPECT_EQ(entry_list[0].type,
35               NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER);
36     EXPECT_EQ(entry_list[0].source.id, net_log_with_source_.source().id);
37     std::string value;
38     EXPECT_EQ(expected_header_name,
39               GetStringValueFromParams(entry_list[0], "header_name"));
40     EXPECT_EQ(expected_header_value,
41               GetStringValueFromParams(entry_list[0], "header_value"));
42     EXPECT_EQ(expected_error_message,
43               GetStringValueFromParams(entry_list[0], "error"));
44   }
45 
46  protected:
47   NetLogWithSource net_log_with_source_{
48       NetLogWithSource::Make(NetLog::Get(), NetLogSourceType::NONE)};
49   RecordingNetLogObserver net_log_observer_;
50   HeaderCoalescer header_coalescer_;
51 };
52 
TEST_F(HeaderCoalescerTest,CorrectHeaders)53 TEST_F(HeaderCoalescerTest, CorrectHeaders) {
54   header_coalescer_.OnHeader(":foo", "bar");
55   header_coalescer_.OnHeader("baz", "qux");
56   EXPECT_FALSE(header_coalescer_.error_seen());
57 
58   quiche::HttpHeaderBlock header_block = header_coalescer_.release_headers();
59   EXPECT_THAT(header_block,
60               ElementsAre(Pair(":foo", "bar"), Pair("baz", "qux")));
61 }
62 
TEST_F(HeaderCoalescerTest,EmptyHeaderKey)63 TEST_F(HeaderCoalescerTest, EmptyHeaderKey) {
64   header_coalescer_.OnHeader("", "foo");
65   EXPECT_TRUE(header_coalescer_.error_seen());
66   ExpectEntry("", "foo", "Header name must not be empty.");
67 }
68 
TEST_F(HeaderCoalescerTest,HeaderBlockTooLarge)69 TEST_F(HeaderCoalescerTest, HeaderBlockTooLarge) {
70   // key + value + overhead = 3 + kMaxHeaderListSizeForTest - 40 + 32
71   // = kMaxHeaderListSizeForTest - 5
72   std::string data(kMaxHeaderListSizeForTest - 40, 'a');
73   header_coalescer_.OnHeader("foo", data);
74   EXPECT_FALSE(header_coalescer_.error_seen());
75 
76   // Another 3 + 4 + 32 bytes: too large.
77   header_coalescer_.OnHeader("bar", "abcd");
78   EXPECT_TRUE(header_coalescer_.error_seen());
79   ExpectEntry("bar", "abcd", "Header list too large.");
80 }
81 
TEST_F(HeaderCoalescerTest,PseudoHeadersMustNotFollowRegularHeaders)82 TEST_F(HeaderCoalescerTest, PseudoHeadersMustNotFollowRegularHeaders) {
83   header_coalescer_.OnHeader("foo", "bar");
84   EXPECT_FALSE(header_coalescer_.error_seen());
85   header_coalescer_.OnHeader(":baz", "qux");
86   EXPECT_TRUE(header_coalescer_.error_seen());
87   ExpectEntry(":baz", "qux", "Pseudo header must not follow regular headers.");
88 }
89 
TEST_F(HeaderCoalescerTest,Append)90 TEST_F(HeaderCoalescerTest, Append) {
91   header_coalescer_.OnHeader("foo", "bar");
92   header_coalescer_.OnHeader("cookie", "baz");
93   header_coalescer_.OnHeader("foo", "quux");
94   header_coalescer_.OnHeader("cookie", "qux");
95   EXPECT_FALSE(header_coalescer_.error_seen());
96 
97   quiche::HttpHeaderBlock header_block = header_coalescer_.release_headers();
98   EXPECT_THAT(header_block,
99               ElementsAre(Pair("foo", std::string_view("bar\0quux", 8)),
100                           Pair("cookie", "baz; qux")));
101 }
102 
TEST_F(HeaderCoalescerTest,HeaderNameNotValid)103 TEST_F(HeaderCoalescerTest, HeaderNameNotValid) {
104   std::string_view header_name("\x1\x7F\x80\xFF");
105   header_coalescer_.OnHeader(header_name, "foo");
106   EXPECT_TRUE(header_coalescer_.error_seen());
107   ExpectEntry("%ESCAPED:\xE2\x80\x8B \x1\x7F%80%FF", "foo",
108               "Invalid character in header name.");
109 }
110 
111 // RFC 7540 Section 8.1.2.6. Uppercase in header name is invalid.
TEST_F(HeaderCoalescerTest,HeaderNameHasUppercase)112 TEST_F(HeaderCoalescerTest, HeaderNameHasUppercase) {
113   std::string_view header_name("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
114   header_coalescer_.OnHeader(header_name, "foo");
115   EXPECT_TRUE(header_coalescer_.error_seen());
116   ExpectEntry("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "foo",
117               "Upper case characters in header name.");
118 }
119 
120 // RFC 7230 Section 3.2. Valid header name is defined as:
121 // field-name     = token
122 // token          = 1*tchar
123 // tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
124 //                  "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
TEST_F(HeaderCoalescerTest,HeaderNameValid)125 TEST_F(HeaderCoalescerTest, HeaderNameValid) {
126   // Due to RFC 7540 Section 8.1.2.6. Uppercase characters are not included.
127   std::string_view header_name(
128       "abcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+-."
129       "^_`|~");
130   header_coalescer_.OnHeader(header_name, "foo");
131   EXPECT_FALSE(header_coalescer_.error_seen());
132   quiche::HttpHeaderBlock header_block = header_coalescer_.release_headers();
133   EXPECT_THAT(header_block, ElementsAre(Pair(header_name, "foo")));
134 }
135 
136 // According to RFC 7540 Section 10.3 and RFC 7230 Section 3.2, allowed
137 // characters in header values are '\t', '  ', 0x21 to 0x7E, and 0x80 to 0xFF.
TEST_F(HeaderCoalescerTest,HeaderValueValid)138 TEST_F(HeaderCoalescerTest, HeaderValueValid) {
139   header_coalescer_.OnHeader("foo", " bar \x21 \x7e baz\tqux\x80\xff ");
140   EXPECT_FALSE(header_coalescer_.error_seen());
141 }
142 
TEST_F(HeaderCoalescerTest,HeaderValueContainsLF)143 TEST_F(HeaderCoalescerTest, HeaderValueContainsLF) {
144   header_coalescer_.OnHeader("foo", "bar\nbaz");
145   EXPECT_TRUE(header_coalescer_.error_seen());
146   ExpectEntry("foo", "bar\nbaz", "Invalid character 0x0A in header value.");
147 }
148 
TEST_F(HeaderCoalescerTest,HeaderValueContainsCR)149 TEST_F(HeaderCoalescerTest, HeaderValueContainsCR) {
150   header_coalescer_.OnHeader("foo", "bar\rbaz");
151   EXPECT_TRUE(header_coalescer_.error_seen());
152   ExpectEntry("foo", "bar\rbaz", "Invalid character 0x0D in header value.");
153 }
154 
TEST_F(HeaderCoalescerTest,HeaderValueContains0x7f)155 TEST_F(HeaderCoalescerTest, HeaderValueContains0x7f) {
156   header_coalescer_.OnHeader("foo", "bar\x7f baz");
157   EXPECT_TRUE(header_coalescer_.error_seen());
158   ExpectEntry("foo", "bar\x7F baz", "Invalid character 0x7F in header value.");
159 }
160 
161 }  // namespace net::test
162