wasm: don’t dereference null reply pointer

Move all access to the reply inside the nullptr check,
while making sure to still call emscripten_fetch_close()
unconditionally where needed.

Make all four Emscripten callback handlers have a similar
structure where we check if the reply is not null and
not in the Aborted state.

(This removes one emscripten_fetch_t nullptr check in
stateChage(), if it is really the case that Emscripten
calls us with a null emscripten_fetch_t then we should
add it back.)

Pick-to: 5.15 6.1 6.2
Change-Id: Iadcbe6338c338cfeb8967490e0951d8b3e1ec5b3
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
bb10
Morten Johan Sørvig 2021-08-18 10:59:11 +02:00
parent e68bf3ddaf
commit 8585cd2483
1 changed files with 33 additions and 40 deletions

View File

@ -446,13 +446,14 @@ void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingData()
void QNetworkReplyWasmImplPrivate::downloadSucceeded(emscripten_fetch_t *fetch)
{
auto reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
if (!reply || reply->state == QNetworkReplyPrivate::Aborted)
return;
QByteArray buffer(fetch->data, fetch->numBytes);
reply->dataReceived(buffer, buffer.size());
if (reply) {
if (reply->state != QNetworkReplyPrivate::Aborted) {
QByteArray buffer(fetch->data, fetch->numBytes);
reply->dataReceived(buffer, buffer.size());
}
reply->m_fetch = nullptr;
}
emscripten_fetch_close(fetch);
reply->m_fetch = nullptr;
}
void QNetworkReplyWasmImplPrivate::setStatusCode(int status, const QByteArray &statusText)
@ -464,18 +465,13 @@ void QNetworkReplyWasmImplPrivate::setStatusCode(int status, const QByteArray &s
void QNetworkReplyWasmImplPrivate::stateChange(emscripten_fetch_t *fetch)
{
if (fetch) {
if (!quintptr(fetch->userData))
return;
auto reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
if (reply->state != QNetworkReplyPrivate::Aborted) {
if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) {
size_t headerLength = emscripten_fetch_get_response_headers_length(fetch);
QByteArray str(headerLength, Qt::Uninitialized);
emscripten_fetch_get_response_headers(fetch, str.data(), str.size());
reply->headersReceived(str);
}
auto reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
if (reply && reply->state != QNetworkReplyPrivate::Aborted) {
if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) {
size_t headerLength = emscripten_fetch_get_response_headers_length(fetch);
QByteArray str(headerLength, Qt::Uninitialized);
emscripten_fetch_get_response_headers(fetch, str.data(), str.size());
reply->headersReceived(str);
}
}
}
@ -483,37 +479,34 @@ void QNetworkReplyWasmImplPrivate::stateChange(emscripten_fetch_t *fetch)
void QNetworkReplyWasmImplPrivate::downloadProgress(emscripten_fetch_t *fetch)
{
auto reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
if (!reply || reply->state == QNetworkReplyPrivate::Aborted)
return;
if (fetch->status < 400) {
uint64_t bytes = fetch->dataOffset + fetch->numBytes;
uint64_t tBytes = fetch->totalBytes; // totalBytes can be 0 if server not reporting content length
if (tBytes == 0)
tBytes = bytes;
reply->emitDataReadProgress(bytes, tBytes);
if (reply && reply->state != QNetworkReplyPrivate::Aborted) {
if (fetch->status < 400) {
uint64_t bytes = fetch->dataOffset + fetch->numBytes;
uint64_t tBytes = fetch->totalBytes; // totalBytes can be 0 if server not reporting content length
if (tBytes == 0)
tBytes = bytes;
reply->emitDataReadProgress(bytes, tBytes);
}
}
}
void QNetworkReplyWasmImplPrivate::downloadFailed(emscripten_fetch_t *fetch)
{
auto reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fetch->userData);
if (reply) {
QString reasonStr;
if (fetch->status > 600)
reasonStr = QStringLiteral("Operation canceled");
else
reasonStr = QString::fromUtf8(fetch->statusText);
QByteArray statusText(fetch->statusText);
reply->setStatusCode(fetch->status, statusText);
reply->emitReplyError(reply->statusCodeFromHttp(fetch->status, reply->request.url()), reasonStr);
if (reply->state != QNetworkReplyPrivate::Aborted) {
QString reasonStr;
if (fetch->status > 600)
reasonStr = QStringLiteral("Operation canceled");
else
reasonStr = QString::fromUtf8(fetch->statusText);
QByteArray statusText(fetch->statusText);
reply->setStatusCode(fetch->status, statusText);
reply->emitReplyError(reply->statusCodeFromHttp(fetch->status, reply->request.url()), reasonStr);
}
reply->m_fetch = nullptr;
}
emscripten_fetch_close(fetch);
reply->m_fetch = nullptr;
}
//taken from qhttpthreaddelegate.cpp