diff options
author | Tomasz Duda <tomaszduda23@gmail.com> | 2012-09-19 17:42:11 (GMT) |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-09-25 13:35:09 (GMT) |
commit | 872d6aff3ea96d548e0bad99def669b803368a36 (patch) | |
tree | 6a7fdcbc26fab50bf0ba81b2bd47516a5fb09481 /tests/auto/qnetworkreply | |
parent | 87cd2d3530dfd3d7dc78b7dab50aefde87ca3b16 (diff) | |
download | Qt-872d6aff3ea96d548e0bad99def669b803368a36.zip Qt-872d6aff3ea96d548e0bad99def669b803368a36.tar.gz Qt-872d6aff3ea96d548e0bad99def669b803368a36.tar.bz2 |
HTTP header may be damaged - fix, unit test
"HTTP/1.1 100 CONTINUE\r\n"
If the header from a server is splitted between two packets
the first packet contains "HTTP/1.1 100" and the second one
contains " CONTINUE\r\n", one space (0x20) is skipped. After
processing the line looks in this way "HTTP/1.1 100CONTINUE".
QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
is called twice, if a http header is splitted as above.
The function always removes whitespace from the beginning of a packet,
even if it is the second part of a http header
QHttpNetworkReply returns QNetworkReply::RemoteHostClosedError
due to damaged http header during processing.
Task-number: QTBUG-27161
Backported qtbase/60f4fc8b706db9cbeacd5dc4886a7aa347daafc0
Change-Id: I07ec43641bbb9966285a8a1f57a51fb27d2643d4
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Diffstat (limited to 'tests/auto/qnetworkreply')
-rw-r--r-- | tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 49bcf12..591ff55 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -371,6 +371,9 @@ private Q_SLOTS: void qtbug18232gzipContentLengthZero(); void nb279420gzipNoContentLengthEmptyContentDisconnect(); + void qtbug27161httpHeaderMayBeDamaged_data(); + void qtbug27161httpHeaderMayBeDamaged(); + void synchronousRequest_data(); void synchronousRequest(); #ifndef QT_NO_OPENSSL @@ -6428,6 +6431,79 @@ void tst_QNetworkReply::nb279420gzipNoContentLengthEmptyContentDisconnect() QCOMPARE(reply->readAll(), QByteArray()); } +class QtBug27161Helper : public QObject { + Q_OBJECT +public: + QtBug27161Helper(MiniHttpServer & server, const QByteArray & data): + m_server(server), + m_data(data) + { + connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot())); + } +public slots: + void newConnectionSlot(){ + connect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); + } + + void bytesWrittenSlot(){ + disconnect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); + m_Timer.singleShot(100, this, SLOT(timeoutSlot())); + } + + void timeoutSlot(){ + m_server.doClose = true; + // we need to emulate the bytesWrittenSlot call if the data is empty. + if (m_data.size() == 0) + QMetaObject::invokeMethod(&m_server, "bytesWrittenSlot", Qt::QueuedConnection); + else + m_server.client->write(m_data); + } + +private: + MiniHttpServer & m_server; + QByteArray m_data; + QTimer m_Timer; +}; + +void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged_data(){ + QByteArray response("HTTP/1.0 200 OK\r\nServer: bogus\r\nContent-Length: 3\r\n\r\nABC"); + QTest::addColumn<QByteArray>("firstPacket"); + QTest::addColumn<QByteArray>("secondPacket"); + + for (int i = 1; i < response.size(); i++){ + QByteArray dataTag("Iteration: "); + dataTag.append(QByteArray::number(i - 1)); + QTest::newRow(dataTag.constData()) << response.left(i) << response.mid(i); + } +} + +/* + * Purpose of this test is to check whether a content from server is parsed correctly + * if it is splitted into two parts. + */ +void tst_QNetworkReply::qtbug27161httpHeaderMayBeDamaged(){ + QFETCH(QByteArray, firstPacket); + QFETCH(QByteArray, secondPacket); + MiniHttpServer server(firstPacket); + server.doClose = false; + QtBug27161Helper helper(server, secondPacket); + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply(manager.get(request)); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->size(), qint64(3)); + QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(3)); + QCOMPARE(reply->rawHeader("Content-length"), QByteArray("3")); + QCOMPARE(reply->rawHeader("Server"), QByteArray("bogus")); + QCOMPARE(reply->readAll(), QByteArray("ABC")); +} + void tst_QNetworkReply::synchronousRequest_data() { QTest::addColumn<QUrl>("url"); |