1/****************************************************************************
2**
3** Copyright (C) 2016 Kurt Pattyn <pattyn.kurt@gmail.com>.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include <QtTest/QtTest>
29#include <QtTest/qtestcase.h>
30#include <QDebug>
31#include <QByteArray>
32#include <QtEndian>
33
34#include "private/qwebsocketframe_p.h"
35#include "private/qwebsocketprotocol_p.h"
36#include "qwebsocketprotocol.h"
37
38QT_USE_NAMESPACE
39
40Q_DECLARE_METATYPE(QWebSocketProtocol::CloseCode)
41Q_DECLARE_METATYPE(QWebSocketProtocol::OpCode)
42
43/*!
44 * \brief class FrameHelper is used to encode a single frame.
45 *
46 * \internal
47 */
48class FrameHelper
49{
50public:
51 FrameHelper();
52
53 QByteArray wireRepresentation();
54
55 void setRsv1(int value) { m_rsv1 = value; }
56 void setRsv2(int value) { m_rsv2 = value; }
57 void setRsv3(int value) { m_rsv3 = value; }
58 void setMask(quint32 mask) { m_mask = mask; }
59 void setOpCode(QWebSocketProtocol::OpCode opCode) { m_opCode = opCode; }
60 void setPayload(const QByteArray &payload) { m_payload = payload; }
61 void setFinalFrame(bool isFinal) { m_isFinalFrame = isFinal; }
62
63private:
64 int m_rsv1;
65 int m_rsv2;
66 int m_rsv3;
67 quint32 m_mask;
68 QWebSocketProtocol::OpCode m_opCode;
69 QByteArray m_payload;
70 bool m_isFinalFrame;
71};
72
73FrameHelper::FrameHelper() :
74 m_rsv1(0), m_rsv2(0), m_rsv3(0),
75 m_mask(0), m_opCode(QWebSocketProtocol::OpCodeReserved3),
76 m_payload(), m_isFinalFrame(false)
77{}
78
79QByteArray FrameHelper::wireRepresentation()
80{
81 quint8 byte = 0x00;
82 QByteArray wireRep;
83 quint64 payloadLength = m_payload.length();
84
85 //FIN, opcode
86 byte = static_cast<quint8>((m_opCode & 0x0F) | (m_isFinalFrame ? 0x80 : 0x00)); //FIN, opcode
87 //RSV1-3
88 byte |= static_cast<quint8>(((m_rsv1 & 0x01) << 6) | ((m_rsv2 & 0x01) << 5) |
89 ((m_rsv3 & 0x01) << 4));
90 wireRep.append(c: static_cast<char>(byte));
91
92 byte = 0x00;
93 if (m_mask != 0)
94 {
95 byte |= 0x80;
96 }
97 if (payloadLength <= 125)
98 {
99 byte |= static_cast<quint8>(payloadLength);
100 wireRep.append(c: static_cast<char>(byte));
101 }
102 else if (payloadLength <= 0xFFFFU)
103 {
104 byte |= 126;
105 wireRep.append(c: static_cast<char>(byte));
106 quint16 swapped = qToBigEndian<quint16>(source: static_cast<quint16>(payloadLength));
107 wireRep.append(s: static_cast<const char *>(static_cast<const void *>(&swapped)), len: 2);
108 }
109 else
110 {
111 byte |= 127;
112 wireRep.append(c: static_cast<char>(byte));
113 quint64 swapped = qToBigEndian<quint64>(source: payloadLength);
114 wireRep.append(s: static_cast<const char *>(static_cast<const void *>(&swapped)), len: 8);
115 }
116 //Write mask
117 if (m_mask != 0)
118 {
119 wireRep.append(s: static_cast<const char *>(static_cast<const void *>(&m_mask)),
120 len: sizeof(quint32));
121 }
122 QByteArray tmpData = m_payload;
123 if (m_mask)
124 {
125 tmpData.detach();
126 QWebSocketProtocol::mask(payload: &tmpData, maskingKey: m_mask);
127 }
128 wireRep.append(a: tmpData);
129 return wireRep;
130}
131
132class tst_WebSocketFrame : public QObject
133{
134 Q_OBJECT
135
136public:
137 tst_WebSocketFrame();
138
139private Q_SLOTS:
140 void initTestCase();
141 void cleanupTestCase();
142 void init();
143 void cleanup();
144
145 void tst_initialization();
146 void tst_copyConstructorAndAssignment();
147
148 void tst_goodFrames_data();
149 void tst_goodFrames();
150
151 void tst_invalidFrames_data();
152 void tst_invalidFrames();
153
154 void tst_malformedFrames_data();
155 void tst_malformedFrames();
156};
157
158tst_WebSocketFrame::tst_WebSocketFrame()
159{}
160
161void tst_WebSocketFrame::initTestCase()
162{
163}
164
165void tst_WebSocketFrame::cleanupTestCase()
166{}
167
168void tst_WebSocketFrame::init()
169{
170 qRegisterMetaType<QWebSocketProtocol::OpCode>(typeName: "QWebSocketProtocol::OpCode");
171 qRegisterMetaType<QWebSocketProtocol::CloseCode>(typeName: "QWebSocketProtocol::CloseCode");
172}
173
174void tst_WebSocketFrame::cleanup()
175{
176}
177
178void tst_WebSocketFrame::tst_initialization()
179{
180 QWebSocketFrame frame;
181 QVERIFY(!frame.isValid());
182 QCOMPARE(frame.payload().length(), 0);
183}
184
185void tst_WebSocketFrame::tst_copyConstructorAndAssignment()
186{
187 FrameHelper frameHelper;
188 frameHelper.setRsv1(0);
189 frameHelper.setRsv2(0);
190 frameHelper.setRsv3(0);
191 frameHelper.setFinalFrame(true);
192 frameHelper.setMask(1234u);
193 frameHelper.setOpCode(QWebSocketProtocol::OpCodeBinary);
194 frameHelper.setPayload(QByteArrayLiteral("12345"));
195
196 QByteArray payload = frameHelper.wireRepresentation();
197 QBuffer buffer(&payload);
198 buffer.open(openMode: QIODevice::ReadOnly);
199
200 QWebSocketFrame frame;
201 frame.readFrame(pIoDevice: &buffer);
202 buffer.close();
203
204 auto compareFrames = [](const QWebSocketFrame &other, const QWebSocketFrame &frame)
205 {
206 QCOMPARE(other.closeCode(), frame.closeCode());
207 QCOMPARE(other.closeReason(), frame.closeReason());
208 QCOMPARE(other.hasMask(), frame.hasMask());
209 QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame());
210 QCOMPARE(other.isControlFrame(), frame.isControlFrame());
211 QCOMPARE(other.isDataFrame(), frame.isDataFrame());
212 QCOMPARE(other.isFinalFrame(), frame.isFinalFrame());
213 QCOMPARE(other.isValid(), frame.isValid());
214 QCOMPARE(other.mask(), frame.mask());
215 QCOMPARE(other.opCode(), frame.opCode());
216 QCOMPARE(other.payload(), frame.payload());
217 QCOMPARE(other.rsv1(), frame.rsv1());
218 QCOMPARE(other.rsv2(), frame.rsv2());
219 QCOMPARE(other.rsv3(), frame.rsv3());
220 };
221
222 {
223 QWebSocketFrame other(frame);
224 compareFrames(other, frame);
225 }
226 {
227 QWebSocketFrame other;
228 other = frame;
229 compareFrames(other, frame);
230 QWebSocketFrame other2 = std::move(other);
231 compareFrames(other2, frame);
232 QWebSocketFrame other3(std::move(other2));
233 compareFrames(other3, frame);
234 }
235}
236
237void tst_WebSocketFrame::tst_goodFrames_data()
238{
239 QTest::addColumn<bool>(name: "rsv1");
240 QTest::addColumn<bool>(name: "rsv2");
241 QTest::addColumn<bool>(name: "rsv3");
242 QTest::addColumn<quint32>(name: "mask");
243 QTest::addColumn<QWebSocketProtocol::OpCode>(name: "opCode");
244 QTest::addColumn<bool>(name: "isFinal");
245 QTest::addColumn<QByteArray>(name: "payload");
246 QTest::addColumn<bool>(name: "isControlFrame");
247 QTest::addColumn<bool>(name: "isDataFrame");
248 QTest::addColumn<bool>(name: "isContinuationFrame");
249
250 QTest::newRow(dataTag: "Non masked final text frame with small payload")
251 << false << false << false
252 << 0U << QWebSocketProtocol::OpCodeText
253 << true << QStringLiteral("Hello world!").toUtf8()
254 << false << true << false;
255 QTest::newRow(dataTag: "Non masked final binary frame with small payload")
256 << false << false << false
257 << 0U << QWebSocketProtocol::OpCodeBinary
258 << true << QByteArrayLiteral("\x00\x01\x02\x03\x04")
259 << false << true << false;
260 QTest::newRow(dataTag: "Non masked final text frame with no payload")
261 << false << false << false
262 << 0U << QWebSocketProtocol::OpCodeText
263 << true << QByteArray()
264 << false << true << false;
265 QTest::newRow(dataTag: "Non masked final binary frame with no payload")
266 << false << false << false
267 << 0U << QWebSocketProtocol::OpCodeBinary
268 << true << QByteArray()
269 << false << true << false;
270
271 QTest::newRow(dataTag: "Non masked final close frame with small payload")
272 << false << false << false
273 << 0U << QWebSocketProtocol::OpCodeClose
274 << true << QStringLiteral("Hello world!").toUtf8()
275 << true << false << false;
276 QTest::newRow(dataTag: "Non masked final close frame with no payload")
277 << false << false << false
278 << 0U << QWebSocketProtocol::OpCodeClose
279 << true << QByteArray()
280 << true << false << false;
281 QTest::newRow(dataTag: "Non masked final ping frame with small payload")
282 << false << false << false
283 << 0U << QWebSocketProtocol::OpCodePing
284 << true << QStringLiteral("Hello world!").toUtf8()
285 << true << false << false;
286 QTest::newRow(dataTag: "Non masked final pong frame with no payload")
287 << false << false << false
288 << 0U << QWebSocketProtocol::OpCodePong
289 << true << QByteArray()
290 << true << false << false;
291
292 QTest::newRow(dataTag: "Non masked final continuation frame with small payload")
293 << false << false << false
294 << 0U << QWebSocketProtocol::OpCodeContinue
295 << true << QStringLiteral("Hello world!").toUtf8()
296 << false << true << true;
297 QTest::newRow(dataTag: "Non masked non-final continuation frame with small payload")
298 << false << false << false
299 << 0U << QWebSocketProtocol::OpCodeContinue
300 << false << QStringLiteral("Hello world!").toUtf8()
301 << false << true << true;
302}
303
304void tst_WebSocketFrame::tst_goodFrames()
305{
306 QFETCH(bool, rsv1);
307 QFETCH(bool, rsv2);
308 QFETCH(bool, rsv3);
309 QFETCH(quint32, mask);
310 QFETCH(QWebSocketProtocol::OpCode, opCode);
311 QFETCH(bool, isFinal);
312 QFETCH(QByteArray, payload);
313 QFETCH(bool, isControlFrame);
314 QFETCH(bool, isDataFrame);
315 QFETCH(bool, isContinuationFrame);
316
317 FrameHelper helper;
318 helper.setRsv1(rsv1);
319 helper.setRsv2(rsv2);
320 helper.setRsv3(rsv3);
321 helper.setMask(mask);
322 helper.setOpCode(opCode);
323 helper.setFinalFrame(isFinal);
324 helper.setPayload(payload);
325
326 QByteArray wireRepresentation = helper.wireRepresentation();
327 QBuffer buffer;
328 buffer.setData(wireRepresentation);
329 buffer.open(openMode: QIODevice::ReadOnly);
330 QWebSocketFrame frame;
331 frame.readFrame(pIoDevice: &buffer);
332 buffer.close();
333 QVERIFY(frame.isValid());
334 QCOMPARE(frame.rsv1(), rsv1);
335 QCOMPARE(frame.rsv2(), rsv2);
336 QCOMPARE(frame.rsv3(), rsv3);
337 QCOMPARE(frame.hasMask(), (mask != 0));
338 QCOMPARE(frame.opCode(), opCode);
339 QCOMPARE(frame.isFinalFrame(), isFinal);
340 QCOMPARE(frame.isControlFrame(), isControlFrame);
341 QCOMPARE(frame.isDataFrame(), isDataFrame);
342 QCOMPARE(frame.isContinuationFrame(), isContinuationFrame);
343 QCOMPARE(frame.payload().length(), payload.length());
344 QCOMPARE(frame.payload(), payload);
345}
346
347void tst_WebSocketFrame::tst_invalidFrames_data()
348{
349 QTest::addColumn<int>(name: "rsv1");
350 QTest::addColumn<int>(name: "rsv2");
351 QTest::addColumn<int>(name: "rsv3");
352 QTest::addColumn<quint32>(name: "mask");
353 QTest::addColumn<QWebSocketProtocol::OpCode>(name: "opCode");
354 QTest::addColumn<bool>(name: "isFinal");
355 QTest::addColumn<QByteArray>(name: "payload");
356 QTest::addColumn<QWebSocketProtocol::CloseCode>(name: "expectedError");
357
358 QTest::newRow(dataTag: "RSV1 != 0")
359 << 1 << 0 << 0
360 << 0U << QWebSocketProtocol::OpCodeText
361 << true << QStringLiteral("Hello world!").toUtf8()
362 << QWebSocketProtocol::CloseCodeProtocolError;
363 QTest::newRow(dataTag: "RSV2 != 0")
364 << 0 << 1 << 0
365 << 0U << QWebSocketProtocol::OpCodeText
366 << true << QStringLiteral("Hello world!").toUtf8()
367 << QWebSocketProtocol::CloseCodeProtocolError;
368 QTest::newRow(dataTag: "RSV3 != 0")
369 << 0 << 0 << 1
370 << 0U << QWebSocketProtocol::OpCodeText
371 << true << QStringLiteral("Hello world!").toUtf8()
372 << QWebSocketProtocol::CloseCodeProtocolError;
373 QTest::newRow(dataTag: "RSV1 != 0 and RSV2 != 0")
374 << 1 << 1 << 0
375 << 0U << QWebSocketProtocol::OpCodeText
376 << true << QStringLiteral("Hello world!").toUtf8()
377 << QWebSocketProtocol::CloseCodeProtocolError;
378 QTest::newRow(dataTag: "RSV1 != 0 and RSV3 != 0")
379 << 1 << 0 << 1
380 << 0U << QWebSocketProtocol::OpCodeText
381 << true << QStringLiteral("Hello world!").toUtf8()
382 << QWebSocketProtocol::CloseCodeProtocolError;
383 QTest::newRow(dataTag: "RSV2 != 0 and RSV3 != 0")
384 << 0 << 1 << 1
385 << 0U << QWebSocketProtocol::OpCodeText
386 << true << QStringLiteral("Hello world!").toUtf8()
387 << QWebSocketProtocol::CloseCodeProtocolError;
388
389 QTest::newRow(dataTag: "Reserved OpCode 3")
390 << 0 << 0 << 0
391 << 0U << QWebSocketProtocol::OpCodeReserved3
392 << true << QStringLiteral("Hello world!").toUtf8()
393 << QWebSocketProtocol::CloseCodeProtocolError;
394 QTest::newRow(dataTag: "Reserved OpCode 4")
395 << 0 << 0 << 0
396 << 0U << QWebSocketProtocol::OpCodeReserved4
397 << true << QStringLiteral("Hello world!").toUtf8()
398 << QWebSocketProtocol::CloseCodeProtocolError;
399 QTest::newRow(dataTag: "Reserved OpCode 5")
400 << 0 << 0 << 0
401 << 0U << QWebSocketProtocol::OpCodeReserved5
402 << true << QStringLiteral("Hello world!").toUtf8()
403 << QWebSocketProtocol::CloseCodeProtocolError;
404 QTest::newRow(dataTag: "Reserved OpCode 6")
405 << 0 << 0 << 0
406 << 0U << QWebSocketProtocol::OpCodeReserved6
407 << true << QStringLiteral("Hello world!").toUtf8()
408 << QWebSocketProtocol::CloseCodeProtocolError;
409 QTest::newRow(dataTag: "Reserved OpCode 7")
410 << 0 << 0 << 0
411 << 0U << QWebSocketProtocol::OpCodeReserved7
412 << true << QStringLiteral("Hello world!").toUtf8()
413 << QWebSocketProtocol::CloseCodeProtocolError;
414 QTest::newRow(dataTag: "Reserved OpCode B")
415 << 0 << 0 << 0
416 << 0U << QWebSocketProtocol::OpCodeReservedB
417 << true << QStringLiteral("Hello world!").toUtf8()
418 << QWebSocketProtocol::CloseCodeProtocolError;
419 QTest::newRow(dataTag: "Reserved OpCode C")
420 << 0 << 0 << 0
421 << 0U << QWebSocketProtocol::OpCodeReservedC
422 << true << QStringLiteral("Hello world!").toUtf8()
423 << QWebSocketProtocol::CloseCodeProtocolError;
424 QTest::newRow(dataTag: "Reserved OpCode D")
425 << 0 << 0 << 0
426 << 0U << QWebSocketProtocol::OpCodeReservedD
427 << true << QStringLiteral("Hello world!").toUtf8()
428 << QWebSocketProtocol::CloseCodeProtocolError;
429 QTest::newRow(dataTag: "Reserved OpCode E")
430 << 0 << 0 << 0
431 << 0U << QWebSocketProtocol::OpCodeReservedE
432 << true << QStringLiteral("Hello world!").toUtf8()
433 << QWebSocketProtocol::CloseCodeProtocolError;
434 QTest::newRow(dataTag: "Reserved OpCode F")
435 << 0 << 0 << 0
436 << 0U << QWebSocketProtocol::OpCodeReservedF
437 << true << QStringLiteral("Hello world!").toUtf8()
438 << QWebSocketProtocol::CloseCodeProtocolError;
439
440 QTest::newRow(dataTag: "Close Frame with payload > 125 bytes")
441 << 0 << 0 << 0
442 << 0U << QWebSocketProtocol::OpCodeClose
443 << true << QString(126, 'a').toUtf8()
444 << QWebSocketProtocol::CloseCodeProtocolError;
445 QTest::newRow(dataTag: "Non-final Close Frame")
446 << 0 << 0 << 0
447 << 0U << QWebSocketProtocol::OpCodeClose
448 << false << QString(126, 'a').toUtf8()
449 << QWebSocketProtocol::CloseCodeProtocolError;
450 QTest::newRow(dataTag: "Ping Frame with payload > 125 bytes")
451 << 0 << 0 << 0
452 << 0U << QWebSocketProtocol::OpCodePing
453 << true << QString(126, 'a').toUtf8()
454 << QWebSocketProtocol::CloseCodeProtocolError;
455 QTest::newRow(dataTag: "Non-final Ping Frame")
456 << 0 << 0 << 0
457 << 0U << QWebSocketProtocol::OpCodePing
458 << false << QString(126, 'a').toUtf8()
459 << QWebSocketProtocol::CloseCodeProtocolError;
460 QTest::newRow(dataTag: "Pong Frame with payload > 125 bytes")
461 << 0 << 0 << 0
462 << 0U << QWebSocketProtocol::OpCodePong
463 << true << QString(126, 'a').toUtf8()
464 << QWebSocketProtocol::CloseCodeProtocolError;
465 QTest::newRow(dataTag: "Non-final Pong Frame")
466 << 0 << 0 << 0
467 << 0U << QWebSocketProtocol::OpCodePong
468 << false << QString(126, 'a').toUtf8()
469 << QWebSocketProtocol::CloseCodeProtocolError;
470}
471
472void tst_WebSocketFrame::tst_invalidFrames()
473{
474 QFETCH(int, rsv1);
475 QFETCH(int, rsv2);
476 QFETCH(int, rsv3);
477 QFETCH(quint32, mask);
478 QFETCH(QWebSocketProtocol::OpCode, opCode);
479 QFETCH(bool, isFinal);
480 QFETCH(QByteArray, payload);
481 QFETCH(QWebSocketProtocol::CloseCode, expectedError);
482
483 FrameHelper helper;
484 helper.setRsv1(rsv1);
485 helper.setRsv2(rsv2);
486 helper.setRsv3(rsv3);
487 helper.setMask(mask);
488 helper.setOpCode(opCode);
489 helper.setFinalFrame(isFinal);
490 helper.setPayload(payload);
491
492 QByteArray wireRepresentation = helper.wireRepresentation();
493 QBuffer buffer;
494 buffer.setData(wireRepresentation);
495 buffer.open(openMode: QIODevice::ReadOnly);
496 QWebSocketFrame frame;
497 frame.readFrame(pIoDevice: &buffer);
498 buffer.close();
499
500 QVERIFY(!frame.isValid());
501 QCOMPARE(frame.closeCode(), expectedError);
502}
503
504
505/*
506 * Incomplete or overly large frames
507 * Payload must be crafted manually
508 *
509 QTest::newRow("Frame Too Big")
510 << 0 << 0 << 0
511 << 0U << QWebSocketProtocol::OpCodeText
512 << true << QString(MAX_FRAME_SIZE_IN_BYTES + 1, 'a').toUtf8()
513 << QWebSocketProtocol::CloseCodeTooMuchData;
514
515 */
516void tst_WebSocketFrame::tst_malformedFrames_data()
517{
518 QTest::addColumn<QByteArray>(name: "payload");
519 QTest::addColumn<QWebSocketProtocol::CloseCode>(name: "expectedError");
520
521 //too little data
522 QTest::newRow(dataTag: "No data") << QByteArray() << QWebSocketProtocol::CloseCodeGoingAway;
523 FrameHelper helper;
524 helper.setRsv1(0);
525 helper.setRsv2(0);
526 helper.setRsv3(0);
527 helper.setMask(0U);
528 helper.setOpCode(QWebSocketProtocol::OpCodeText);
529 helper.setFinalFrame(true);
530 helper.setPayload(QString(10, 'a').toUtf8());
531 QByteArray wireRep = helper.wireRepresentation();
532
533 //too little data
534 //header + payload should be 12 bytes for non-masked payloads < 126 bytes
535 for (int i = 1; i < 12; ++i)
536 {
537 QTest::newRow(QStringLiteral("Header too small - %1 byte(s)").arg(a: i).toLatin1().constData())
538 << wireRep.left(len: i)
539 << QWebSocketProtocol::CloseCodeGoingAway;
540 }
541 //too much data
542 {
543 const char bigpayloadIndicator = char(127);
544 const quint64 payloadSize = QWebSocketFrame::maxFrameSize() + 1;
545 uchar swapped[8] = {0};
546 qToBigEndian<quint64>(src: payloadSize, dest: swapped);
547 QTest::newRow(dataTag: "Frame too big")
548 << wireRep.left(len: 1).append(c: bigpayloadIndicator)
549 .append(s: reinterpret_cast<char *>(swapped), len: 8)
550 << QWebSocketProtocol::CloseCodeTooMuchData;
551 }
552 //invalid size field
553 {
554 const char bigpayloadIndicator = char(127);
555 quint64 payloadSize = quint64(1) << 63;
556 uchar swapped[8] = {0};
557 qToBigEndian<quint64>(src: payloadSize, dest: swapped);
558 QTest::newRow(dataTag: "Highest bit of payload length is set")
559 << wireRep.left(len: 1).append(c: bigpayloadIndicator)
560 .append(s: reinterpret_cast<char *>(swapped), len: 8)
561 << QWebSocketProtocol::CloseCodeProtocolError;
562
563 payloadSize = 256;
564 qToBigEndian<quint64>(src: payloadSize, dest: swapped);
565 QTest::newRow(dataTag: "Overlong 64-bit size field; should be 16-bit")
566 << wireRep.left(len: 1).append(c: bigpayloadIndicator)
567 .append(s: reinterpret_cast<char *>(swapped), len: 8)
568 << QWebSocketProtocol::CloseCodeProtocolError;
569 }
570 //overlong size field
571 {
572 const char largepayloadIndicator = char(126);
573 const quint16 payloadSize = 120;
574 uchar swapped[2] = {0};
575 qToBigEndian<quint16>(src: payloadSize, dest: swapped);
576 QTest::newRow(dataTag: "Overlong 16-bit size field")
577 << wireRep.left(len: 1).append(c: largepayloadIndicator)
578 .append(s: reinterpret_cast<char *>(swapped), len: 2)
579 << QWebSocketProtocol::CloseCodeProtocolError;
580 }
581 {
582 const char bigpayloadIndicator = char(127);
583 quint64 payloadSize = 120;
584 uchar swapped[8] = {0};
585 qToBigEndian<quint64>(src: payloadSize, dest: swapped);
586 QTest::newRow(dataTag: "Overlong 64-bit size field; should be 7-bit")
587 << wireRep.left(len: 1).append(c: bigpayloadIndicator)
588 .append(s: reinterpret_cast<char *>(swapped), len: 8)
589 << QWebSocketProtocol::CloseCodeProtocolError;
590
591 payloadSize = 256;
592 qToBigEndian<quint64>(src: payloadSize, dest: swapped);
593 QTest::newRow(dataTag: "Overlong 64-bit size field; should be 16-bit")
594 << wireRep.left(len: 1).append(c: bigpayloadIndicator)
595 .append(s: reinterpret_cast<char *>(swapped), len: 8)
596 << QWebSocketProtocol::CloseCodeProtocolError;
597 }
598}
599
600void tst_WebSocketFrame::tst_malformedFrames()
601{
602 QFETCH(QByteArray, payload);
603 QFETCH(QWebSocketProtocol::CloseCode, expectedError);
604
605 QBuffer buffer;
606 buffer.setData(payload);
607 buffer.open(openMode: QIODevice::ReadOnly);
608 QWebSocketFrame frame;
609 frame.readFrame(pIoDevice: &buffer);
610 buffer.close();
611
612 QVERIFY(!frame.isValid());
613 QCOMPARE(frame.closeCode(), expectedError);
614}
615
616QTEST_MAIN(tst_WebSocketFrame)
617
618#include "tst_websocketframe.moc"
619
620

source code of qtwebsockets/tests/auto/websockets/websocketframe/tst_websocketframe.cpp