Bug 1781094 - Revert the some changes done in bug 1759745 and also try to take more output data, r=necko-reviewers,dragana

The problem in the previous change is that `mBrotli->mTotalOut` is not updated immediately. In the case that `nsUnknownDecoder` is involved in the listener chain and the result of `Brotli` decoder is `BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT`, `mBrotli->mTotalOut` is 0. In the end, when `nsHTTPCompressConv::OnStopRequest` is called by `nsUnknownDecoder` [1], an error code is set [2].
The safest way would be to revert the changes done in bug 1759745. However, to make the case in bug 1759745 work ( and also make `test_brotli_decoding.js` pass), we need to add another while loop and try to get more output data from the decoder.


[1] https://searchfox.org/mozilla-central/rev/d5edb4a4538657b7d691a41c00e6796a19ade6e7/netwerk/streamconv/converters/nsUnknownDecoder.cpp#778
[2] https://searchfox.org/mozilla-central/rev/d5edb4a4538657b7d691a41c00e6796a19ade6e7/netwerk/streamconv/converters/nsHTTPCompressConv.cpp#167

Differential Revision: https://phabricator.services.mozilla.com/D152729
This commit is contained in:
Kershaw Chang 2022-07-28 08:04:13 +00:00
parent d690c61a8f
commit 5c8ac9f08f

View File

@ -201,9 +201,14 @@ nsresult nsHTTPCompressConv::BrotliHandler(nsIInputStream* stream,
return NS_OK;
}
auto outBuffer = MakeUniqueFallible<uint8_t[]>(kOutSize);
if (outBuffer == nullptr) {
self->mBrotli->mStatus = NS_ERROR_OUT_OF_MEMORY;
return self->mBrotli->mStatus;
}
do {
outSize = 0;
outPtr = nullptr;
outSize = kOutSize;
outPtr = outBuffer.get();
// brotli api is documented in brotli/dec/decode.h and brotli/dec/decode.c
LOG(("nsHttpCompresssConv %p brotlihandler decompress %zu\n", self, avail));
@ -212,11 +217,13 @@ nsresult nsHTTPCompressConv::BrotliHandler(nsIInputStream* stream,
&self->mBrotli->mState, &avail,
reinterpret_cast<const unsigned char**>(&dataIn), &outSize, &outPtr,
&totalOut);
outSize = kOutSize - outSize;
self->mBrotli->mTotalOut = totalOut;
self->mBrotli->mBrotliStateIsStreamEnd =
BrotliDecoderIsFinished(&self->mBrotli->mState);
LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%" PRIx32, self,
static_cast<uint32_t>(res)));
LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%" PRIx32
" out=%zu\n",
self, static_cast<uint32_t>(res), outSize));
if (res == BROTLI_DECODER_RESULT_ERROR) {
LOG(("nsHttpCompressConv %p marking invalid encoding", self));
@ -235,17 +242,35 @@ nsresult nsHTTPCompressConv::BrotliHandler(nsIInputStream* stream,
}
}
while (::BrotliDecoderHasMoreOutput(&self->mBrotli->mState)) {
outSize = kOutSize;
const uint8_t* buffer =
::BrotliDecoderTakeOutput(&self->mBrotli->mState, &outSize);
nsresult rv = self->do_OnDataAvailable(
self->mBrotli->mRequest, self->mBrotli->mSourceOffset,
reinterpret_cast<const char*>(buffer), outSize);
auto callOnDataAvailable = [&](uint64_t aSourceOffset, const char* aBuffer,
uint32_t aCount) {
nsresult rv = self->do_OnDataAvailable(self->mBrotli->mRequest,
aSourceOffset, aBuffer, aCount);
LOG(("nsHttpCompressConv %p BrotliHandler ODA rv=%" PRIx32, self,
static_cast<uint32_t>(rv)));
if (NS_FAILED(rv)) {
self->mBrotli->mStatus = rv;
}
return rv;
};
if (outSize > 0) {
if (NS_FAILED(callOnDataAvailable(
self->mBrotli->mSourceOffset,
reinterpret_cast<const char*>(outBuffer.get()), outSize))) {
return self->mBrotli->mStatus;
}
}
// See bug 1759745. If the decoder has more output data, take it.
while (::BrotliDecoderHasMoreOutput(&self->mBrotli->mState)) {
outSize = kOutSize;
const uint8_t* buffer =
::BrotliDecoderTakeOutput(&self->mBrotli->mState, &outSize);
if (NS_FAILED(callOnDataAvailable(self->mBrotli->mSourceOffset,
reinterpret_cast<const char*>(buffer),
outSize))) {
return self->mBrotli->mStatus;
}
}