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