Bug 1492524. r=dragana
authorNicholas Hurley <hurley@mozilla.com>
Mon, 08 Oct 2018 06:44:42 -0400
changeset 495691 430f18b70e6f2def589d9b304abad3bc8d10d58d
parent 495690 2b61cf8794a0f641d980d9d7ec6aa3643184a1f0
child 495692 594b22ac459fc11ee7948cd7be54b88a86bd54c1
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1492524
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1492524. r=dragana Differential Revision: https://phabricator.services.mozilla.com/D6946
netwerk/protocol/http/Http2Compression.cpp
--- a/netwerk/protocol/http/Http2Compression.cpp
+++ b/netwerk/protocol/http/Http2Compression.cpp
@@ -416,17 +416,17 @@ Http2Decompressor::DecodeHeaderBlock(con
   mHeaderScheme.Truncate();
   mHeaderPath.Truncate();
   mHeaderMethod.Truncate();
   mSeenNonColonHeader = false;
   mIsPush = isPush;
 
   nsresult rv = NS_OK;
   nsresult softfail_rv = NS_OK;
-  while (NS_SUCCEEDED(rv) && (mOffset < datalen)) {
+  while (NS_SUCCEEDED(rv) && (mOffset < mDataLen)) {
     bool modifiesTable = true;
     if (mData[mOffset] & 0x80) {
       rv = DoIndexed();
       LOG(("Decompressor state after indexed"));
     } else if (mData[mOffset] & 0x40) {
       rv = DoLiteralWithIncremental();
       LOG(("Decompressor state after literal with incremental"));
     } else if (mData[mOffset] & 0x20) {
@@ -698,16 +698,21 @@ Http2Decompressor::CopyStringFromInput(u
   mOffset += bytes;
   return NS_OK;
 }
 
 nsresult
 Http2Decompressor::DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table,
                                                uint8_t &c, uint8_t &bitsLeft)
 {
+  MOZ_ASSERT(mOffset <= mDataLen);
+  if (mOffset > mDataLen) {
+    NS_WARNING("DecodeFinalHuffmanCharacter would read beyond end of buffer");
+    return NS_ERROR_FAILURE;
+  }
   uint8_t mask = (1 << bitsLeft) - 1;
   uint8_t idx = mData[mOffset - 1] & mask;
   idx <<= (8 - bitsLeft);
   // Don't update bitsLeft yet, because we need to check that value against the
   // number of bits used by our encoding later on. We'll update when we are sure
   // how many bits we've actually used.
 
   if (table->IndexHasANextTable(idx)) {
@@ -735,16 +740,17 @@ Http2Decompressor::DecodeFinalHuffmanCha
   bitsLeft -= entry->mPrefixLen;
 
   return NS_OK;
 }
 
 uint8_t
 Http2Decompressor::ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed)
 {
+  MOZ_DIAGNOSTIC_ASSERT(mOffset < mDataLen);
   uint8_t rv;
 
   if (bitsLeft) {
     // Need to extract bitsLeft bits from the previous byte, and 8 - bitsLeft
     // bits from the current byte
     uint8_t mask = (1 << bitsLeft) - 1;
     rv = (mData[mOffset - 1] & mask) << (8 - bitsLeft);
     rv |= (mData[mOffset] & ~mask) >> bitsLeft;
@@ -764,18 +770,18 @@ Http2Decompressor::ExtractByte(uint8_t b
 nsresult
 Http2Decompressor::DecodeHuffmanCharacter(const HuffmanIncomingTable *table,
                                           uint8_t &c, uint32_t &bytesConsumed,
                                           uint8_t &bitsLeft)
 {
   uint8_t idx = ExtractByte(bitsLeft, bytesConsumed);
 
   if (table->IndexHasANextTable(idx)) {
-    if (bytesConsumed >= mDataLen) {
-      if (!bitsLeft || (bytesConsumed > mDataLen)) {
+    if (mOffset >= mDataLen) {
+      if (!bitsLeft || (mOffset > mDataLen)) {
         // TODO - does this get me into trouble in the new world?
         // No info left in input to try to consume, we're done
         LOG(("DecodeHuffmanCharacter all out of bits to consume, can't chain"));
         return NS_ERROR_FAILURE;
       }
 
       // We might get lucky here!
       return DecodeFinalHuffmanCharacter(table->NextTable(idx), c, bitsLeft);
@@ -906,16 +912,23 @@ Http2Decompressor::DoLiteralInternal(nsA
 
   // first let's get the name
   uint32_t index;
   nsresult rv = DecodeInteger(namePrefixLen, index);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  // sanity check
+  if (mOffset >= mDataLen) {
+    NS_WARNING("Http2 Decompressor ran out of data");
+    // This is session-fatal
+    return NS_ERROR_FAILURE;
+  }
+
   bool isHuffmanEncoded;
 
   if (!index) {
     // name is embedded as a literal
     uint32_t nameLen;
     isHuffmanEncoded = mData[mOffset] & (1 << 7);
     rv = DecodeInteger(7, nameLen);
     if (NS_SUCCEEDED(rv)) {
@@ -933,16 +946,23 @@ Http2Decompressor::DoLiteralInternal(nsA
     rv = CopyHeaderString(index - 1, name);
     LOG(("Http2Decompressor::DoLiteralInternal indexed name %d %s",
          index, name.BeginReading()));
   }
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  // sanity check
+  if (mOffset >= mDataLen) {
+    NS_WARNING("Http2 Decompressor ran out of data");
+    // This is session-fatal
+    return NS_ERROR_FAILURE;
+  }
+
   // now the value
   uint32_t valueLen;
   isHuffmanEncoded = mData[mOffset] & (1 << 7);
   rv = DecodeInteger(7, valueLen);
   if (NS_SUCCEEDED(rv)) {
     if (isHuffmanEncoded) {
       rv = CopyHuffmanStringFromInput(valueLen, value);
     } else {