Bug 1274732 - Avoid allocate 128k buffer on stack r?mcmanus draft
authorNatanael Copa <ncopa@alpinelinux.org>
Sun, 29 May 2016 15:59:24 +0200
changeset 372621 8960efdbd9c3e01fb15cf590b917989f29c164d7
parent 372484 2c7440e46d8786b2c82a1d2004e2b6d9d13f4046
child 522197 c95cff83942308ac214b8065ce4bf6261494f486
push id19544
push userbmo:natanael.copa@gmail.com
push dateSun, 29 May 2016 14:25:33 +0000
reviewersmcmanus
bugs1274732
milestone49.0a1
Bug 1274732 - Avoid allocate 128k buffer on stack r?mcmanus Move the 128k buffer for brotli decompression to the heap instead of stack. This fixes crash with musl libc which provides 80k stack by default. MozReview-Commit-ID: 9cDlFO5eoi1
netwerk/streamconv/converters/nsHTTPCompressConv.cpp
--- a/netwerk/streamconv/converters/nsHTTPCompressConv.cpp
+++ b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp
@@ -160,31 +160,36 @@ nsHTTPCompressConv::OnStopRequest(nsIReq
 NS_METHOD
 nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn,
                                   uint32_t, uint32_t aAvail, uint32_t *countRead)
 {
   MOZ_ASSERT(stream);
   nsHTTPCompressConv *self = static_cast<nsHTTPCompressConv *>(closure);
   *countRead = 0;
 
-  const uint32_t kOutSize = 128 * 1024; // just a chunk size, we call in a loop
-  unsigned char outBuffer[kOutSize];
-  unsigned char *outPtr;
+  const size_t kOutSize = 128 * 1024; // just a chunk size, we call in a loop
+  uint8_t *outPtr;
   size_t outSize;
   size_t avail = aAvail;
   BrotliResult res;
 
   if (!self->mBrotli) {
     *countRead = aAvail;
     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 = kOutSize;
-    outPtr = outBuffer;
+    outPtr = outBuffer.get();
 
     // brotli api is documented in brotli/dec/decode.h and brotli/dec/decode.c
     LOG(("nsHttpCompresssConv %p brotlihandler decompress %d\n", self, avail));
     res = ::BrotliDecompressStream(
       &avail, reinterpret_cast<const unsigned char **>(&dataIn),
       &outSize, &outPtr, &self->mBrotli->mTotalOut, &self->mBrotli->mState);
     outSize = kOutSize - outSize;
     LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%x out=%d\n",
@@ -205,17 +210,17 @@ nsHTTPCompressConv::BrotliHandler(nsIInp
         self->mBrotli->mStatus = NS_ERROR_UNEXPECTED;
         return self->mBrotli->mStatus;
       }
     }
     if (outSize > 0) {
       nsresult rv = self->do_OnDataAvailable(self->mBrotli->mRequest,
                                              self->mBrotli->mContext,
                                              self->mBrotli->mSourceOffset,
-                                             reinterpret_cast<const char *>(outBuffer),
+                                             reinterpret_cast<const char *>(outBuffer.get()),
                                              outSize);
       LOG(("nsHttpCompressConv %p BrotliHandler ODA rv=%x", self, rv));
       if (NS_FAILED(rv)) {
         self->mBrotli->mStatus = rv;
         return self->mBrotli->mStatus;
       }
     }