summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hartmann <phartmann@blackberry.com>2013-07-25 16:05:29 (GMT)
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-03 01:41:37 (GMT)
commit1f40ed553e618c3b0511c7db4b4fd26c2d2b65bf (patch)
tree7e689089ac242ce9d2dee649573f627a1ca95acb
parent8234f5171a20628d6384d10a45d0437a0ab791ee (diff)
downloadQt-1f40ed553e618c3b0511c7db4b4fd26c2d2b65bf.zip
Qt-1f40ed553e618c3b0511c7db4b4fd26c2d2b65bf.tar.gz
Qt-1f40ed553e618c3b0511c7db4b4fd26c2d2b65bf.tar.bz2
QHttpMultiPart: fix data corruption in readData method
When readData() is called repeatedly, we need to keep track which part of the multipart message we are currently reading from. Hereby we also need to take the boundary size into account, and not only the size of the multipart; otherwise we would skip a not completely read part. This would then later lead to advancing the read pointer by negative indexes and data loss. Task-number: QTBUG-32534 Change-Id: Ibb6dff16adaf4ea67181d23d1d0c8459e33a0ed0 Reviewed-by: Jonathan Liu <net147@gmail.com> Reviewed-by: Shane Kearns <shane.kearns@accenture.com> (cherry picked from qtbase/af96c6fed931564c95037539f07e9c8e33c69529) Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/network/access/qhttpmultipart.cpp3
-rw-r--r--tests/auto/qnetworkreply/tst_qnetworkreply.cpp44
2 files changed, 46 insertions, 1 deletions
diff --git a/src/network/access/qhttpmultipart.cpp b/src/network/access/qhttpmultipart.cpp
index 635129a..b25e917 100644
--- a/src/network/access/qhttpmultipart.cpp
+++ b/src/network/access/qhttpmultipart.cpp
@@ -488,7 +488,8 @@ qint64 QHttpMultiPartIODevice::readData(char *data, qint64 maxSize)
// skip the parts we have already read
while (index < multiPart->parts.count() &&
- readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size())
+ readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size()
+ + multiPart->boundary.count() + 6) // 6 == 2 boundary dashes, \r\n after boundary, \r\n after multipart
index++;
// read the data
diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
index e4373ea..64f8f78 100644
--- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp
@@ -216,6 +216,7 @@ private Q_SLOTS:
void postToHttpSynchronous();
void postToHttpMultipart_data();
void postToHttpMultipart();
+ void multipartSkipIndices(); // QTBUG-32534
void deleteFromHttp_data();
void deleteFromHttp();
void putGetDeleteGetFromHttp_data();
@@ -2279,6 +2280,49 @@ void tst_QNetworkReply::postToHttpMultipart()
QCOMPARE(replyData, expectedReplyData);
}
+void tst_QNetworkReply::multipartSkipIndices() // QTBUG-32534
+{
+ QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::MixedType);
+ QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi");
+ QNetworkRequest request(url);
+ QList<QByteArray> parts;
+ parts << QByteArray(56083, 'X') << QByteArray(468, 'X') << QByteArray(24952, 'X');
+
+ QHttpPart part1;
+ part1.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"field1\"; filename=\"aaaa.bin\"");
+ part1.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
+ part1.setBody(parts.at(0));
+ multiPart->append(part1);
+
+ QHttpPart part2;
+ part2.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"field2\"; filename=\"bbbb.txt\"");
+ part2.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
+ part2.setBody(parts.at(1));
+ multiPart->append(part2);
+
+ QHttpPart part3;
+ part3.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"text-3\"; filename=\"cccc.txt\"");
+ part3.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
+ part3.setBody(parts.at(2));
+ multiPart->append(part3);
+
+ QNetworkReplyPtr reply;
+ RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST"));
+
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok
+ QByteArray line;
+ int partIndex = 0;
+ while ((line = reply->readLine()) != QByteArray("")) {
+ if (line.startsWith("content:")) {
+ // before, the 3rd part would return garbled output at the end
+ QCOMPARE("content: " + parts[partIndex++] + "\n", line);
+ }
+ }
+ multiPart->deleteLater();
+}
+
void tst_QNetworkReply::putToHttpMultipart_data()
{
postToHttpMultipart_data();