wasm: fix heap crash when making multiple network calls

Pick-to: 5.15
Task-number: QTBUG-83991
Change-Id: I354934b53799f3eeb958395932bed18289b1e279
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Lorn Potter 2020-05-09 08:32:43 +10:00
parent f061c413de
commit 745a7fa31e
2 changed files with 23 additions and 20 deletions

View File

@ -221,7 +221,7 @@ void QNetworkReplyWasmImplPrivate::doSendRequest()
if (headersData.count() > 0) { if (headersData.count() > 0) {
const char* customHeaders[arrayLength]; const char* customHeaders[arrayLength];
int i = 0; int i = 0;
for (i; i < headersData.count() * 2; (i = i + 2)) { for (i; i < headersData.count(); i++) {
customHeaders[i] = headersData[i].constData(); customHeaders[i] = headersData[i].constData();
customHeaders[i + 1] = request.rawHeader(headersData[i]).constData(); customHeaders[i + 1] = request.rawHeader(headersData[i]).constData();
} }
@ -365,24 +365,28 @@ static int parseHeaderName(const QByteArray &headerName)
} }
void QNetworkReplyWasmImplPrivate::headersReceived(const QString &bufferString) void QNetworkReplyWasmImplPrivate::headersReceived(const QByteArray &buffer)
{ {
Q_Q(QNetworkReplyWasmImpl); Q_Q(QNetworkReplyWasmImpl);
if (!bufferString.isEmpty()) { if (!buffer.isEmpty()) {
QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), Qt::SkipEmptyParts); QList<QByteArray> headers = buffer.split('\n');
for (int i = 0; i < headers.size(); i++) { for (int i = 0; i < headers.size(); i++) {
QString headerName = headers.at(i).split(QString::fromUtf8(": ")).at(0); if (headers.at(i).contains(':')) { // headers include final \x00, so skip
QString headersValue = headers.at(i).split(QString::fromUtf8(": ")).at(1); QByteArray headerName = headers.at(i).split(': ').at(0).trimmed();
if (headerName.isEmpty() || headersValue.isEmpty()) QByteArray headersValue = headers.at(i).split(': ').at(1).trimmed();
continue;
int headerIndex = parseHeaderName(headerName.toLocal8Bit()); if (headerName.isEmpty() || headersValue.isEmpty())
continue;
if (headerIndex == -1) int headerIndex = parseHeaderName(headerName);
q->setRawHeader(headerName.toLocal8Bit(), headersValue.toLocal8Bit());
else if (headerIndex == -1)
q->setHeader(static_cast<QNetworkRequest::KnownHeaders>(headerIndex), (QVariant)headersValue); q->setRawHeader(headerName, headersValue);
else
q->setHeader(static_cast<QNetworkRequest::KnownHeaders>(headerIndex), (QVariant)headersValue);
}
} }
} }
emit q->metaDataChanged(); emit q->metaDataChanged();
@ -463,12 +467,11 @@ void QNetworkReplyWasmImplPrivate::stateChange(emscripten_fetch_t *fetch)
{ {
if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) { if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) {
size_t headerLength = emscripten_fetch_get_response_headers_length(fetch); size_t headerLength = emscripten_fetch_get_response_headers_length(fetch);
char *dst = nullptr; QByteArray str(headerLength, Qt::Uninitialized);
emscripten_fetch_get_response_headers(fetch, dst, headerLength + 1); emscripten_fetch_get_response_headers(fetch, str.data(), str.size());
std::string str = dst; QNetworkReplyWasmImplPrivate *reply =
QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData); reply->headersReceived(str);
reply->headersReceived(QString::fromStdString(str));
} }
} }

View File

@ -110,7 +110,7 @@ public:
void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &); void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &);
void emitDataReadProgress(qint64 done, qint64 total); void emitDataReadProgress(qint64 done, qint64 total);
void dataReceived(const QByteArray &buffer, int bufferSize); void dataReceived(const QByteArray &buffer, int bufferSize);
void headersReceived(const QString &bufferString); void headersReceived(const QByteArray &buffer);
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData); QIODevice *outgoingData);