• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/websockets/websocket_frame_parser.h"
11 
12 #include <stdint.h>
13 
14 #include <algorithm>
15 #include <iterator>
16 #include <string>
17 #include <string_view>
18 #include <vector>
19 
20 #include "base/containers/span.h"
21 #include "base/containers/to_vector.h"
22 #include "net/websockets/websocket_frame.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace net {
26 
27 namespace {
28 
29 constexpr char kHello[] = "Hello, world!";
30 constexpr uint64_t kHelloLength = std::size(kHello) - 1;
31 constexpr char kHelloFrame[] = "\x81\x0DHello, world!";
32 constexpr char kMaskedHelloFrame[] =
33     "\x81\x8D\xDE\xAD\xBE\xEF"
34     "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF";
35 
ConvertToUint8Vector(std::string_view input)36 std::vector<uint8_t> ConvertToUint8Vector(std::string_view input) {
37   return base::ToVector(input, [](char c) { return static_cast<uint8_t>(c); });
38 }
39 
40 struct FrameHeaderTestCase {
41   const std::string_view frame_header;
42   uint64_t frame_length;
43   WebSocketError error_code;
44 };
45 
46 constexpr FrameHeaderTestCase kFrameHeaderTests[] = {
47     {{"\x81\x00", 2}, UINT64_C(0), kWebSocketNormalClosure},
48     {{"\x81\x7D", 2}, UINT64_C(125), kWebSocketNormalClosure},
49     {{"\x81\x7E\x00\x7E", 4}, UINT64_C(126), kWebSocketNormalClosure},
50     {{"\x81\x7E\xFF\xFF", 4}, UINT64_C(0xFFFF), kWebSocketNormalClosure},
51     {{"\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10},
52      UINT64_C(0x10000),
53      kWebSocketNormalClosure},
54     {{"\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10},
55      UINT64_C(0x7FFFFFFF),
56      kWebSocketNormalClosure},
57     {{"\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10},
58      UINT64_C(0x80000000),
59      kWebSocketErrorMessageTooBig},
60     {{"\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10},
61      UINT64_C(0x7FFFFFFFFFFFFFFF),
62      kWebSocketErrorMessageTooBig}};
63 constexpr int kNumFrameHeaderTests = std::size(kFrameHeaderTests);
64 
TEST(WebSocketFrameParserTest,DecodeNormalFrame)65 TEST(WebSocketFrameParserTest, DecodeNormalFrame) {
66   WebSocketFrameParser parser;
67 
68   std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
69 
70   auto frame_data = ConvertToUint8Vector(kHelloFrame);
71   EXPECT_TRUE(parser.Decode(frame_data, &frames));
72   EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
73   ASSERT_EQ(1u, frames.size());
74   WebSocketFrameChunk* frame = frames[0].get();
75   ASSERT_TRUE(frame != nullptr);
76   const WebSocketFrameHeader* header = frame->header.get();
77   EXPECT_TRUE(header != nullptr);
78   if (header) {
79     EXPECT_TRUE(header->final);
80     EXPECT_FALSE(header->reserved1);
81     EXPECT_FALSE(header->reserved2);
82     EXPECT_FALSE(header->reserved3);
83     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
84     EXPECT_FALSE(header->masked);
85     EXPECT_EQ(kHelloLength, header->payload_length);
86   }
87   EXPECT_TRUE(frame->final_chunk);
88 
89   ASSERT_EQ(static_cast<size_t>(kHelloLength), frame->payload.size());
90   EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->payload.data()));
91 }
92 
TEST(WebSocketFrameParserTest,DecodeMaskedFrame)93 TEST(WebSocketFrameParserTest, DecodeMaskedFrame) {
94   WebSocketFrameParser parser;
95 
96   std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
97 
98   auto frame_data = ConvertToUint8Vector(kMaskedHelloFrame);
99   EXPECT_TRUE(parser.Decode(frame_data, &frames));
100   EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
101   ASSERT_EQ(1u, frames.size());
102   WebSocketFrameChunk* frame = frames[0].get();
103   ASSERT_TRUE(frame != nullptr);
104   const WebSocketFrameHeader* header = frame->header.get();
105   EXPECT_TRUE(header != nullptr);
106   if (header) {
107     EXPECT_TRUE(header->final);
108     EXPECT_FALSE(header->reserved1);
109     EXPECT_FALSE(header->reserved2);
110     EXPECT_FALSE(header->reserved3);
111     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
112     EXPECT_TRUE(header->masked);
113     EXPECT_EQ(kHelloLength, header->payload_length);
114   }
115   EXPECT_TRUE(frame->final_chunk);
116 
117   ASSERT_EQ(static_cast<size_t>(kHelloLength), frame->payload.size());
118 
119   std::string payload(frame->payload.data(), frame->payload.size());
120   MaskWebSocketFramePayload(header->masking_key, 0,
121                             base::as_writable_byte_span(payload));
122   EXPECT_EQ(payload, kHello);
123 }
124 
TEST(WebSocketFrameParserTest,DecodeManyFrames)125 TEST(WebSocketFrameParserTest, DecodeManyFrames) {
126   struct Input {
127     const char* frame;
128     size_t frame_length;
129     const char* expected_payload;
130     size_t expected_payload_length;
131   };
132   static constexpr Input kInputs[] = {
133       // Each |frame| data is split into two string literals because C++ lexers
134       // consume unlimited number of hex characters in a hex character escape
135       // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as
136       // { '\x5F', '\0' }).
137       {"\x81\x05"
138        "First",
139        7, "First", 5},
140       {"\x81\x06"
141        "Second",
142        8, "Second", 6},
143       {"\x81\x05"
144        "Third",
145        7, "Third", 5},
146       {"\x81\x06"
147        "Fourth",
148        8, "Fourth", 6},
149       {"\x81\x05"
150        "Fifth",
151        7, "Fifth", 5},
152       {"\x81\x05"
153        "Sixth",
154        7, "Sixth", 5},
155       {"\x81\x07"
156        "Seventh",
157        9, "Seventh", 7},
158       {"\x81\x06"
159        "Eighth",
160        8, "Eighth", 6},
161       {"\x81\x05"
162        "Ninth",
163        7, "Ninth", 5},
164       {"\x81\x05"
165        "Tenth",
166        7, "Tenth", 5}};
167   static constexpr int kNumInputs = std::size(kInputs);
168 
169   std::vector<uint8_t> input;
170   // Concatenate all frames.
171   for (const auto& data : kInputs) {
172     input.insert(input.end(), data.frame, data.frame + data.frame_length);
173   }
174 
175   WebSocketFrameParser parser;
176 
177   std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
178   EXPECT_TRUE(parser.Decode(input, &frames));
179   EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
180   ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size());
181 
182   for (int i = 0; i < kNumInputs; ++i) {
183     WebSocketFrameChunk* frame = frames[i].get();
184     EXPECT_TRUE(frame != nullptr);
185     if (!frame)
186       continue;
187     EXPECT_TRUE(frame->final_chunk);
188     ASSERT_EQ(kInputs[i].expected_payload_length,
189               static_cast<uint64_t>(frame->payload.size()));
190     EXPECT_TRUE(std::equal(
191         kInputs[i].expected_payload,
192         kInputs[i].expected_payload + kInputs[i].expected_payload_length,
193         frame->payload.data()));
194 
195     const WebSocketFrameHeader* header = frame->header.get();
196     EXPECT_TRUE(header != nullptr);
197     if (!header)
198       continue;
199     EXPECT_TRUE(header->final);
200     EXPECT_FALSE(header->reserved1);
201     EXPECT_FALSE(header->reserved2);
202     EXPECT_FALSE(header->reserved3);
203     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
204     EXPECT_FALSE(header->masked);
205     EXPECT_EQ(kInputs[i].expected_payload_length, header->payload_length);
206   }
207 }
208 
TEST(WebSocketFrameParserTest,DecodePartialFrame)209 TEST(WebSocketFrameParserTest, DecodePartialFrame) {
210   static constexpr size_t kFrameHeaderSize = 2;
211 
212   std::vector<uint8_t> hello_frame_data = ConvertToUint8Vector(kHelloFrame);
213 
214   for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) {
215     auto [input1, input2] =
216         base::span(hello_frame_data).split_at(kFrameHeaderSize + cutting_pos);
217 
218     std::vector<char> expected1(kHello, kHello + cutting_pos);
219     std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
220 
221     WebSocketFrameParser parser;
222 
223     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames1;
224     EXPECT_TRUE(parser.Decode(input1, &frames1));
225     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
226     EXPECT_EQ(1u, frames1.size());
227     if (frames1.size() != 1u)
228       continue;
229     WebSocketFrameChunk* frame1 = frames1[0].get();
230     EXPECT_TRUE(frame1 != nullptr);
231     if (!frame1)
232       continue;
233     EXPECT_FALSE(frame1->final_chunk);
234     if (expected1.size() == 0) {
235       EXPECT_EQ(nullptr, frame1->payload.data());
236     } else {
237       ASSERT_EQ(cutting_pos, static_cast<size_t>(frame1->payload.size()));
238       EXPECT_TRUE(std::equal(expected1.begin(), expected1.end(),
239                              frame1->payload.data()));
240     }
241     const WebSocketFrameHeader* header1 = frame1->header.get();
242     EXPECT_TRUE(header1 != nullptr);
243     if (!header1)
244       continue;
245     EXPECT_TRUE(header1->final);
246     EXPECT_FALSE(header1->reserved1);
247     EXPECT_FALSE(header1->reserved2);
248     EXPECT_FALSE(header1->reserved3);
249     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
250     EXPECT_FALSE(header1->masked);
251     EXPECT_EQ(kHelloLength, header1->payload_length);
252 
253     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames2;
254     EXPECT_TRUE(parser.Decode(input2, &frames2));
255     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
256     EXPECT_EQ(1u, frames2.size());
257     if (frames2.size() != 1u)
258       continue;
259     WebSocketFrameChunk* frame2 = frames2[0].get();
260     EXPECT_TRUE(frame2 != nullptr);
261     if (!frame2)
262       continue;
263     EXPECT_TRUE(frame2->final_chunk);
264     if (expected2.size() == 0) {
265       EXPECT_EQ(nullptr, frame2->payload.data());
266     } else {
267       ASSERT_EQ(expected2.size(),
268                 static_cast<uint64_t>(frame2->payload.size()));
269       EXPECT_TRUE(std::equal(expected2.begin(), expected2.end(),
270                              frame2->payload.data()));
271     }
272     const WebSocketFrameHeader* header2 = frame2->header.get();
273     EXPECT_TRUE(header2 == nullptr);
274   }
275 }
276 
TEST(WebSocketFrameParserTest,DecodePartialMaskedFrame)277 TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
278   static constexpr size_t kFrameHeaderSize = 6;
279 
280   std::vector<uint8_t> masked_hello_frame_data =
281       ConvertToUint8Vector(kMaskedHelloFrame);
282 
283   for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) {
284     auto [input1, input2] = base::span(masked_hello_frame_data)
285                                 .split_at(kFrameHeaderSize + cutting_pos);
286 
287     std::vector<char> expected1(kHello, kHello + cutting_pos);
288     std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength);
289 
290     WebSocketFrameParser parser;
291 
292     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames1;
293     EXPECT_TRUE(parser.Decode(input1, &frames1));
294     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
295     EXPECT_EQ(1u, frames1.size());
296     if (frames1.size() != 1u)
297       continue;
298     WebSocketFrameChunk* frame1 = frames1[0].get();
299     EXPECT_TRUE(frame1 != nullptr);
300     if (!frame1)
301       continue;
302     EXPECT_FALSE(frame1->final_chunk);
303     const WebSocketFrameHeader* header1 = frame1->header.get();
304     EXPECT_TRUE(header1 != nullptr);
305     if (!header1)
306       continue;
307     if (expected1.size() == 0) {
308       EXPECT_EQ(nullptr, frame1->payload.data());
309     } else {
310       ASSERT_EQ(expected1.size(),
311                 static_cast<uint64_t>(frame1->payload.size()));
312       std::vector<char> payload1(
313           frame1->payload.data(),
314           frame1->payload.data() + frame1->payload.size());
315       MaskWebSocketFramePayload(header1->masking_key, 0,
316                                 base::as_writable_byte_span(payload1));
317       EXPECT_EQ(expected1, payload1);
318     }
319     EXPECT_TRUE(header1->final);
320     EXPECT_FALSE(header1->reserved1);
321     EXPECT_FALSE(header1->reserved2);
322     EXPECT_FALSE(header1->reserved3);
323     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode);
324     EXPECT_TRUE(header1->masked);
325     EXPECT_EQ(kHelloLength, header1->payload_length);
326 
327     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames2;
328     EXPECT_TRUE(parser.Decode(input2, &frames2));
329     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
330     EXPECT_EQ(1u, frames2.size());
331     if (frames2.size() != 1u)
332       continue;
333     WebSocketFrameChunk* frame2 = frames2[0].get();
334     EXPECT_TRUE(frame2 != nullptr);
335     if (!frame2)
336       continue;
337     EXPECT_TRUE(frame2->final_chunk);
338     if (expected2.size() == 0) {
339       EXPECT_EQ(nullptr, frame2->payload.data());
340     } else {
341       ASSERT_EQ(expected2.size(),
342                 static_cast<uint64_t>(frame2->payload.size()));
343       std::vector<char> payload2(
344           frame2->payload.data(),
345           frame2->payload.data() + frame2->payload.size());
346       MaskWebSocketFramePayload(header1->masking_key, cutting_pos,
347                                 base::as_writable_byte_span(payload2));
348       EXPECT_EQ(expected2, payload2);
349     }
350     const WebSocketFrameHeader* header2 = frame2->header.get();
351     EXPECT_TRUE(header2 == nullptr);
352   }
353 }
354 
TEST(WebSocketFrameParserTest,DecodeFramesOfVariousLengths)355 TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) {
356   for (const auto& test : kFrameHeaderTests) {
357     auto frame_header = ConvertToUint8Vector(test.frame_header);
358     uint64_t frame_length = test.frame_length;
359 
360     std::vector<uint8_t> input(frame_header);
361     static constexpr uint64_t kMaxPayloadSize = 200;
362     uint64_t input_payload_size = std::min(frame_length, kMaxPayloadSize);
363     input.insert(input.end(), input_payload_size, 'a');
364 
365     WebSocketFrameParser parser;
366 
367     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
368     EXPECT_EQ(test.error_code == kWebSocketNormalClosure,
369               parser.Decode(input, &frames));
370     EXPECT_EQ(test.error_code, parser.websocket_error());
371     if (test.error_code != kWebSocketNormalClosure) {
372       EXPECT_EQ(0u, frames.size());
373     } else {
374       EXPECT_EQ(1u, frames.size());
375     }
376     if (frames.size() != 1u)
377       continue;
378     WebSocketFrameChunk* frame = frames[0].get();
379     EXPECT_TRUE(frame != nullptr);
380     if (!frame)
381       continue;
382     if (frame_length == input_payload_size) {
383       EXPECT_TRUE(frame->final_chunk);
384     } else {
385       EXPECT_FALSE(frame->final_chunk);
386     }
387     std::vector<char> expected_payload(input_payload_size, 'a');
388     if (expected_payload.size() == 0) {
389       EXPECT_EQ(nullptr, frame->payload.data());
390     } else {
391       ASSERT_EQ(expected_payload.size(),
392                 static_cast<uint64_t>(frame->payload.size()));
393       EXPECT_TRUE(std::equal(expected_payload.begin(), expected_payload.end(),
394                              frame->payload.data()));
395     }
396     const WebSocketFrameHeader* header = frame->header.get();
397     EXPECT_TRUE(header != nullptr);
398     if (!header)
399       continue;
400     EXPECT_TRUE(header->final);
401     EXPECT_FALSE(header->reserved1);
402     EXPECT_FALSE(header->reserved2);
403     EXPECT_FALSE(header->reserved3);
404     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
405     EXPECT_FALSE(header->masked);
406     EXPECT_EQ(frame_length, header->payload_length);
407   }
408 }
409 
TEST(WebSocketFrameParserTest,DecodePartialHeader)410 TEST(WebSocketFrameParserTest, DecodePartialHeader) {
411   for (int i = 0; i < kNumFrameHeaderTests; ++i) {
412     auto frame_header = ConvertToUint8Vector(kFrameHeaderTests[i].frame_header);
413     size_t frame_header_length = frame_header.size();
414     uint64_t frame_length = kFrameHeaderTests[i].frame_length;
415 
416     WebSocketFrameParser parser;
417 
418     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
419     // Feed each byte to the parser to see if the parser behaves correctly
420     // when it receives partial frame header.
421     size_t last_byte_offset = frame_header_length - 1;
422     for (size_t j = 0; j < frame_header_length; ++j) {
423       bool failed =
424           kFrameHeaderTests[i].error_code != kWebSocketNormalClosure &&
425           j == last_byte_offset;
426       EXPECT_EQ(!failed, parser.Decode(base::span(frame_header).subspan(j, 1u),
427                                        &frames));
428       if (failed) {
429         EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
430       } else {
431         EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
432       }
433       if (kFrameHeaderTests[i].error_code == kWebSocketNormalClosure &&
434           j == last_byte_offset) {
435         EXPECT_EQ(1u, frames.size()) << "i=" << i << ", j=" << j;
436       } else {
437         EXPECT_EQ(0u, frames.size()) << "i=" << i << ", j=" << j;
438       }
439     }
440     if (frames.size() != 1u)
441       continue;
442     WebSocketFrameChunk* frame = frames[0].get();
443     EXPECT_TRUE(frame != nullptr);
444     if (!frame)
445       continue;
446     if (frame_length == 0u) {
447       EXPECT_TRUE(frame->final_chunk);
448     } else {
449       EXPECT_FALSE(frame->final_chunk);
450     }
451     EXPECT_EQ(nullptr, frame->payload.data());
452     const WebSocketFrameHeader* header = frame->header.get();
453     EXPECT_TRUE(header != nullptr);
454     if (!header)
455       continue;
456     EXPECT_TRUE(header->final);
457     EXPECT_FALSE(header->reserved1);
458     EXPECT_FALSE(header->reserved2);
459     EXPECT_FALSE(header->reserved3);
460     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
461     EXPECT_FALSE(header->masked);
462     EXPECT_EQ(frame_length, header->payload_length);
463   }
464 }
465 
TEST(WebSocketFrameParserTest,InvalidLengthEncoding)466 TEST(WebSocketFrameParserTest, InvalidLengthEncoding) {
467   struct TestCase {
468     const std::string_view frame_header;
469   };
470   static constexpr TestCase kTests[] = {
471       // For frames with two-byte extended length field, the payload length
472       // should be 126 (0x7E) bytes or more.
473       {{"\x81\x7E\x00\x00", 4}},
474       {{"\x81\x7E\x00\x7D", 4}},
475       // For frames with eight-byte extended length field, the payload length
476       // should be 0x10000 bytes or more.
477       {{"\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10}},
478       {{"\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10}},
479   };
480 
481   for (const auto& test : kTests) {
482     auto frame_header = ConvertToUint8Vector(test.frame_header);
483 
484     WebSocketFrameParser parser;
485 
486     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
487     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
488     EXPECT_FALSE(parser.Decode(frame_header, &frames));
489     EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
490     EXPECT_EQ(0u, frames.size());
491 
492     std::vector<uint8_t> empty_frame_data;
493     EXPECT_FALSE(parser.Decode(empty_frame_data, &frames));
494     EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
495     EXPECT_EQ(0u, frames.size());
496   }
497 }
498 
TEST(WebSocketFrameParserTest,FrameTypes)499 TEST(WebSocketFrameParserTest, FrameTypes) {
500   struct TestCase {
501     const std::string_view frame_header;
502     WebSocketFrameHeader::OpCode opcode;
503   };
504   static constexpr TestCase kTests[] = {
505       {{"\x80\x00", 2}, WebSocketFrameHeader::kOpCodeContinuation},
506       {{"\x81\x00", 2}, WebSocketFrameHeader::kOpCodeText},
507       {{"\x82\x00", 2}, WebSocketFrameHeader::kOpCodeBinary},
508       {{"\x83\x00", 2}, WebSocketFrameHeader::kOpCodeDataUnused3},
509       {{"\x84\x00", 2}, WebSocketFrameHeader::kOpCodeDataUnused4},
510       {{"\x85\x00", 2}, WebSocketFrameHeader::kOpCodeDataUnused5},
511       {{"\x86\x00", 2}, WebSocketFrameHeader::kOpCodeDataUnused6},
512       {{"\x87\x00", 2}, WebSocketFrameHeader::kOpCodeDataUnused7},
513       {{"\x88\x00", 2}, WebSocketFrameHeader::kOpCodeClose},
514       {{"\x89\x00", 2}, WebSocketFrameHeader::kOpCodePing},
515       {{"\x8A\x00", 2}, WebSocketFrameHeader::kOpCodePong},
516       {{"\x8B\x00", 2}, WebSocketFrameHeader::kOpCodeControlUnusedB},
517       {{"\x8C\x00", 2}, WebSocketFrameHeader::kOpCodeControlUnusedC},
518       {{"\x8D\x00", 2}, WebSocketFrameHeader::kOpCodeControlUnusedD},
519       {{"\x8E\x00", 2}, WebSocketFrameHeader::kOpCodeControlUnusedE},
520       {{"\x8F\x00", 2}, WebSocketFrameHeader::kOpCodeControlUnusedF},
521   };
522 
523   for (const auto& test : kTests) {
524     auto frame_header = ConvertToUint8Vector(test.frame_header);
525 
526     WebSocketFrameHeader::OpCode opcode = test.opcode;
527 
528     WebSocketFrameParser parser;
529 
530     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
531     EXPECT_TRUE(parser.Decode(frame_header, &frames));
532     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
533     EXPECT_EQ(1u, frames.size());
534     if (frames.size() != 1u)
535       continue;
536     WebSocketFrameChunk* frame = frames[0].get();
537     EXPECT_TRUE(frame != nullptr);
538     if (!frame)
539       continue;
540     EXPECT_TRUE(frame->final_chunk);
541     EXPECT_EQ(nullptr, frame->payload.data());
542     const WebSocketFrameHeader* header = frame->header.get();
543     EXPECT_TRUE(header != nullptr);
544     if (!header)
545       continue;
546     EXPECT_TRUE(header->final);
547     EXPECT_FALSE(header->reserved1);
548     EXPECT_FALSE(header->reserved2);
549     EXPECT_FALSE(header->reserved3);
550     EXPECT_EQ(opcode, header->opcode);
551     EXPECT_FALSE(header->masked);
552     EXPECT_EQ(0u, header->payload_length);
553   }
554 }
555 
TEST(WebSocketFrameParserTest,FinalBitAndReservedBits)556 TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) {
557   struct TestCase {
558     const std::string_view frame_header;
559     bool final;
560     bool reserved1;
561     bool reserved2;
562     bool reserved3;
563   };
564   static constexpr TestCase kTests[] = {
565       {{"\x81\x00", 2}, true, false, false, false},
566       {{"\x01\x00", 2}, false, false, false, false},
567       {{"\xC1\x00", 2}, true, true, false, false},
568       {{"\xA1\x00", 2}, true, false, true, false},
569       {{"\x91\x00", 2}, true, false, false, true},
570       {{"\x71\x00", 2}, false, true, true, true},
571       {{"\xF1\x00", 2}, true, true, true, true}};
572 
573   for (const auto& test : kTests) {
574     auto frame_header = ConvertToUint8Vector(test.frame_header);
575 
576     bool final = test.final;
577     bool reserved1 = test.reserved1;
578     bool reserved2 = test.reserved2;
579     bool reserved3 = test.reserved3;
580 
581     WebSocketFrameParser parser;
582 
583     std::vector<std::unique_ptr<WebSocketFrameChunk>> frames;
584     EXPECT_TRUE(parser.Decode(frame_header, &frames));
585     EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
586     EXPECT_EQ(1u, frames.size());
587     if (frames.size() != 1u)
588       continue;
589     WebSocketFrameChunk* frame = frames[0].get();
590     EXPECT_TRUE(frame != nullptr);
591     if (!frame)
592       continue;
593     EXPECT_TRUE(frame->final_chunk);
594     EXPECT_EQ(nullptr, frame->payload.data());
595     const WebSocketFrameHeader* header = frame->header.get();
596     EXPECT_TRUE(header != nullptr);
597     if (!header)
598       continue;
599     EXPECT_EQ(final, header->final);
600     EXPECT_EQ(reserved1, header->reserved1);
601     EXPECT_EQ(reserved2, header->reserved2);
602     EXPECT_EQ(reserved3, header->reserved3);
603     EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode);
604     EXPECT_FALSE(header->masked);
605     EXPECT_EQ(0u, header->payload_length);
606   }
607 }
608 
609 }  // Unnamed namespace
610 
611 }  // namespace net
612