xref: /aosp_15_r20/external/cronet/net/spdy/alps_decoder_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2021 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/alps_decoder.h"
6 
7 #include "base/test/metrics/histogram_tester.h"
8 #include "base/test/scoped_feature_list.h"
9 #include "net/base/features.h"
10 #include "net/base/hex_utils.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 using ::spdy::AcceptChOriginValuePair;
15 using ::testing::ElementsAre;
16 using ::testing::IsEmpty;
17 using ::testing::Pair;
18 
19 namespace net {
20 namespace {
21 
TEST(AlpsDecoderTest,EmptyInput)22 TEST(AlpsDecoderTest, EmptyInput) {
23   AlpsDecoder decoder;
24   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
25   EXPECT_THAT(decoder.GetSettings(), IsEmpty());
26   EXPECT_EQ(0, decoder.settings_frame_count());
27 
28   AlpsDecoder::Error error = decoder.Decode({});
29   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
30 
31   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
32   EXPECT_THAT(decoder.GetSettings(), IsEmpty());
33   EXPECT_EQ(0, decoder.settings_frame_count());
34 }
35 
TEST(AlpsDecoderTest,EmptyAcceptChFrame)36 TEST(AlpsDecoderTest, EmptyAcceptChFrame) {
37   AlpsDecoder decoder;
38   AlpsDecoder::Error error =
39       decoder.Decode(HexDecode("000000"       // length
40                                "89"           // type ACCEPT_CH
41                                "00"           // flags
42                                "00000000"));  // stream ID
43 
44   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
45   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
46   EXPECT_THAT(decoder.GetSettings(), IsEmpty());
47   EXPECT_EQ(0, decoder.settings_frame_count());
48 }
49 
TEST(AlpsDecoderTest,EmptySettingsFrame)50 TEST(AlpsDecoderTest, EmptySettingsFrame) {
51   AlpsDecoder decoder;
52   AlpsDecoder::Error error =
53       decoder.Decode(HexDecode("000000"       // length
54                                "04"           // type SETTINGS
55                                "00"           // flags
56                                "00000000"));  // stream ID
57 
58   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
59   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
60   EXPECT_THAT(decoder.GetSettings(), IsEmpty());
61   EXPECT_EQ(1, decoder.settings_frame_count());
62 }
63 
TEST(AlpsDecoderTest,ParseSettingsAndAcceptChFrames)64 TEST(AlpsDecoderTest, ParseSettingsAndAcceptChFrames) {
65   AlpsDecoder decoder;
66   AlpsDecoder::Error error = decoder.Decode(HexDecode(
67       // ACCEPT_CH frame
68       "00003d"                    // length
69       "89"                        // type ACCEPT_CH
70       "00"                        // flags
71       "00000000"                  // stream ID
72       "0017"                      // origin length
73       "68747470733a2f2f7777772e"  //
74       "6578616d706c652e636f6d"    // origin "https://www.example.com"
75       "0003"                      // value length
76       "666f6f"                    // value "foo"
77       "0018"                      // origin length
78       "68747470733a2f2f6d61696c"  //
79       "2e6578616d706c652e636f6d"  // origin "https://mail.example.com"
80       "0003"                      // value length
81       "626172"                    // value "bar"
82       // SETTINGS frame
83       "00000c"       // length
84       "04"           // type
85       "00"           // flags
86       "00000000"     // stream ID
87       "0dab"         // identifier
88       "01020304"     // value
89       "1234"         // identifier
90       "fedcba98"));  // value
91 
92   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
93   EXPECT_THAT(
94       decoder.GetAcceptCh(),
95       ElementsAre(AcceptChOriginValuePair{"https://www.example.com", "foo"},
96                   AcceptChOriginValuePair{"https://mail.example.com", "bar"}));
97   EXPECT_THAT(decoder.GetSettings(),
98               ElementsAre(Pair(0x0dab, 0x01020304), Pair(0x1234, 0xfedcba98)));
99   EXPECT_EQ(1, decoder.settings_frame_count());
100 }
101 
TEST(AlpsDecoderTest,ParseLargeAcceptChFrame)102 TEST(AlpsDecoderTest, ParseLargeAcceptChFrame) {
103   std::string frame = HexDecode(
104       // ACCEPT_CH frame
105       "0001ab"                    // length: 427 total bytes
106       "89"                        // type ACCEPT_CH
107       "00"                        // flags
108       "00000000"                  // stream ID
109       "0017"                      // origin length
110       "68747470733a2f2f7777772e"  //
111       "6578616d706c652e636f6d"    // origin "https://www.example.com"
112       "0190"                      // value length (400 in hex)
113   );
114 
115   // The Accept-CH tokens payload is a string of 400 'x' characters.
116   const std::string accept_ch_tokens(400, 'x');
117   // Append the value bytes to the frame.
118   frame += accept_ch_tokens;
119 
120   AlpsDecoder decoder;
121   AlpsDecoder::Error error = decoder.Decode(frame);
122 
123   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
124   EXPECT_THAT(decoder.GetAcceptCh(),
125               ElementsAre(AcceptChOriginValuePair{"https://www.example.com",
126                                                   accept_ch_tokens}));
127 }
128 
TEST(AlpsDecoderTest,DisableAlpsParsing)129 TEST(AlpsDecoderTest, DisableAlpsParsing) {
130   base::test::ScopedFeatureList feature_list;
131   feature_list.InitAndDisableFeature(features::kAlpsParsing);
132   AlpsDecoder decoder;
133   AlpsDecoder::Error error = decoder.Decode(HexDecode(
134       // ACCEPT_CH frame
135       "00003d"                    // length
136       "89"                        // type ACCEPT_CH
137       "00"                        // flags
138       "00000000"                  // stream ID
139       "0017"                      // origin length
140       "68747470733a2f2f7777772e"  //
141       "6578616d706c652e636f6d"    // origin "https://www.example.com"
142       "0003"                      // value length
143       "666f6f"                    // value "foo"
144       "0018"                      // origin length
145       "68747470733a2f2f6d61696c"  //
146       "2e6578616d706c652e636f6d"  // origin "https://mail.example.com"
147       "0003"                      // value length
148       "626172"                    // value "bar"
149       ));
150 
151   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
152   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
153 }
154 
TEST(AlpsDecoderTest,DisableAlpsClientHintParsing)155 TEST(AlpsDecoderTest, DisableAlpsClientHintParsing) {
156   base::test::ScopedFeatureList feature_list;
157   feature_list.InitAndDisableFeature(features::kAlpsClientHintParsing);
158   AlpsDecoder decoder;
159   AlpsDecoder::Error error = decoder.Decode(HexDecode(
160       // ACCEPT_CH frame
161       "00003d"                    // length
162       "89"                        // type ACCEPT_CH
163       "00"                        // flags
164       "00000000"                  // stream ID
165       "0017"                      // origin length
166       "68747470733a2f2f7777772e"  //
167       "6578616d706c652e636f6d"    // origin "https://www.example.com"
168       "0003"                      // value length
169       "666f6f"                    // value "foo"
170       "0018"                      // origin length
171       "68747470733a2f2f6d61696c"  //
172       "2e6578616d706c652e636f6d"  // origin "https://mail.example.com"
173       "0003"                      // value length
174       "626172"                    // value "bar"
175       ));
176 
177   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
178   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
179 }
180 
TEST(AlpsDecoderTest,IncompleteFrame)181 TEST(AlpsDecoderTest, IncompleteFrame) {
182   AlpsDecoder decoder;
183   AlpsDecoder::Error error =
184       decoder.Decode(HexDecode("00000c"    // length
185                                "04"        // type
186                                "00"        // flags
187                                "00000000"  // stream ID
188                                "0dab"      // identifier
189                                "01"));     // first byte of value
190 
191   EXPECT_EQ(AlpsDecoder::Error::kNotOnFrameBoundary, error);
192 }
193 
TEST(AlpsDecoderTest,TwoSettingsFrames)194 TEST(AlpsDecoderTest, TwoSettingsFrames) {
195   AlpsDecoder decoder;
196   AlpsDecoder::Error error =
197       decoder.Decode(HexDecode("000006"       // length
198                                "04"           // type SETTINGS
199                                "00"           // flags
200                                "00000000"     // stream ID
201                                "0dab"         // identifier
202                                "01020304"     // value
203                                "000006"       // length
204                                "04"           // type SETTINGS
205                                "00"           // flags
206                                "00000000"     // stream ID
207                                "1234"         // identifier
208                                "fedcba98"));  // value
209 
210   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
211   EXPECT_EQ(2, decoder.settings_frame_count());
212   EXPECT_THAT(decoder.GetSettings(),
213               ElementsAre(Pair(0x0dab, 0x01020304), Pair(0x1234, 0xfedcba98)));
214 }
215 
TEST(AlpsDecoderTest,AcceptChOnInvalidStream)216 TEST(AlpsDecoderTest, AcceptChOnInvalidStream) {
217   AlpsDecoder decoder;
218   AlpsDecoder::Error error = decoder.Decode(
219       HexDecode("00001e"                    // length
220                 "89"                        // type ACCEPT_CH
221                 "00"                        // flags
222                 "00000001"                  // invalid stream ID: should be zero
223                 "0017"                      // origin length
224                 "68747470733a2f2f7777772e"  //
225                 "6578616d706c652e636f6d"    // origin "https://www.example.com"
226                 "0003"                      // value length
227                 "666f6f"));                 // value "foo"
228 
229   EXPECT_EQ(AlpsDecoder::Error::kAcceptChInvalidStream, error);
230 }
231 
232 // According to
233 // https://davidben.github.io/http-client-hint-reliability/ \
234 // draft-davidben-http-client-hint-reliability.html#name-http-2-accept_ch-frame
235 // "If a user agent receives an ACCEPT_CH frame whose stream [...] flags
236 // field is non-zero, it MUST respond with a connection error [...]."
TEST(AlpsDecoderTest,AcceptChWithInvalidFlags)237 TEST(AlpsDecoderTest, AcceptChWithInvalidFlags) {
238   AlpsDecoder decoder;
239   AlpsDecoder::Error error = decoder.Decode(
240       HexDecode("00001e"                    // length
241                 "89"                        // type ACCEPT_CH
242                 "02"                        // invalid flags: should be zero
243                 "00000000"                  // stream ID
244                 "0017"                      // origin length
245                 "68747470733a2f2f7777772e"  //
246                 "6578616d706c652e636f6d"    // origin "https://www.example.com"
247                 "0003"                      // value length
248                 "666f6f"));                 // value "foo"
249 
250   EXPECT_EQ(AlpsDecoder::Error::kAcceptChWithFlags, error);
251 }
252 
TEST(AlpsDecoderTest,SettingsOnInvalidStream)253 TEST(AlpsDecoderTest, SettingsOnInvalidStream) {
254   AlpsDecoder decoder;
255   AlpsDecoder::Error error =
256       decoder.Decode(HexDecode("000006"    // length
257                                "04"        // type SETTINGS
258                                "00"        // flags
259                                "00000001"  // invalid stream ID: should be zero
260                                "1234"      // identifier
261                                "fedcba98"));  // value
262 
263   EXPECT_EQ(AlpsDecoder::Error::kFramingError, error);
264 }
265 
TEST(AlpsDecoderTest,SettingsAck)266 TEST(AlpsDecoderTest, SettingsAck) {
267   AlpsDecoder decoder;
268   AlpsDecoder::Error error =
269       decoder.Decode(HexDecode("000000"       // length
270                                "04"           // type SETTINGS
271                                "01"           // ACK flag
272                                "00000000"));  // stream ID
273 
274   EXPECT_EQ(AlpsDecoder::Error::kSettingsWithAck, error);
275 }
276 
277 // According to https://httpwg.org/specs/rfc7540.html#FrameHeader:
278 // "Flags that have no defined semantics for a particular frame type MUST be
279 // ignored [...]"
TEST(AlpsDecoderTest,SettingsWithInvalidFlags)280 TEST(AlpsDecoderTest, SettingsWithInvalidFlags) {
281   AlpsDecoder decoder;
282   AlpsDecoder::Error error =
283       decoder.Decode(HexDecode("000006"       // length
284                                "04"           // type SETTINGS
285                                "02"           // invalid flag
286                                "00000000"     // stream ID
287                                "1234"         // identifier
288                                "fedcba98"));  // value
289 
290   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
291 }
292 
TEST(AlpsDecoderTest,ForbiddenFrame)293 TEST(AlpsDecoderTest, ForbiddenFrame) {
294   AlpsDecoder decoder;
295   AlpsDecoder::Error error =
296       decoder.Decode(HexDecode("000003"     // length
297                                "00"         // frame type DATA
298                                "01"         // flags END_STREAM
299                                "00000001"   // stream ID
300                                "666f6f"));  // payload "foo"
301 
302   EXPECT_EQ(AlpsDecoder::Error::kForbiddenFrame, error);
303 }
304 
TEST(AlpsDecoderTest,UnknownFrame)305 TEST(AlpsDecoderTest, UnknownFrame) {
306   AlpsDecoder decoder;
307   AlpsDecoder::Error error =
308       decoder.Decode(HexDecode("000003"     // length
309                                "2a"         // unknown frame type
310                                "ff"         // flags
311                                "00000008"   // stream ID
312                                "666f6f"));  // payload "foo"
313 
314   EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
315   EXPECT_THAT(decoder.GetAcceptCh(), IsEmpty());
316   EXPECT_THAT(decoder.GetSettings(), IsEmpty());
317   EXPECT_EQ(0, decoder.settings_frame_count());
318 }
319 
320 class AlpsDecoderTestWithFeature : public ::testing::TestWithParam<bool> {
321  public:
ShouldKillSessionOnAcceptChMalformed()322   bool ShouldKillSessionOnAcceptChMalformed() { return GetParam(); }
323 
324  private:
SetUp()325   void SetUp() override {
326     feature_list_.InitWithFeatureState(
327         features::kShouldKillSessionOnAcceptChMalformed,
328         ShouldKillSessionOnAcceptChMalformed());
329   }
330 
331   base::test::ScopedFeatureList feature_list_;
332 };
333 
334 INSTANTIATE_TEST_SUITE_P(All, AlpsDecoderTestWithFeature, testing::Bool());
335 
TEST_P(AlpsDecoderTestWithFeature,MalformedAcceptChFrame)336 TEST_P(AlpsDecoderTestWithFeature, MalformedAcceptChFrame) {
337   // Correct, complete payload.
338   std::string payload = HexDecode(
339       "0017"  // origin length
340       "68747470733a2f2f7777772e"
341       "6578616d706c652e636f6d"  // origin "https://www.example.com"
342       "0003"                    // value length
343       "666f6f");                // value "foo"
344 
345   for (uint8_t payload_length = 1; payload_length < payload.length();
346        payload_length++) {
347     base::HistogramTester histogram_tester;
348     // First two bytes of length.
349     std::string frame = HexDecode("0000");
350     // Last byte of length.
351     frame.push_back(static_cast<char>(payload_length));
352 
353     frame.append(
354         HexDecode("89"           // type ACCEPT_CH
355                   "00"           // flags
356                   "00000000"));  // stream ID
357     // Incomplete, malformed payload.
358     frame.append(payload.data(), payload_length);
359 
360     AlpsDecoder decoder;
361     AlpsDecoder::Error error = decoder.Decode(frame);
362     if (ShouldKillSessionOnAcceptChMalformed()) {
363       EXPECT_EQ(AlpsDecoder::Error::kAcceptChMalformed, error);
364       histogram_tester.ExpectUniqueSample(
365           "Net.SpdySession.AlpsDecoderStatus.Bypassed",
366           static_cast<int>(AlpsDecoder::Error::kNoError), 1);
367     } else {
368       EXPECT_EQ(AlpsDecoder::Error::kNoError, error);
369       histogram_tester.ExpectUniqueSample(
370           "Net.SpdySession.AlpsDecoderStatus.Bypassed",
371           static_cast<int>(AlpsDecoder::Error::kAcceptChMalformed), 1);
372     }
373   }
374 }
375 
376 }  // namespace
377 }  // namespace net
378