Bug 1378680 - Use fallible alloc in url-classifier draft
authorThomas Nguyen <tnguyen@mozilla.com>
Thu, 20 Jul 2017 16:04:25 +0800
changeset 612008 0a87b2b7cbf49e251558b5e67b1395179e6dbfd5
parent 611714 eb1d92b2b6a4161492561250f51bae5bafeda68a
child 638290 17c6be41109b93f8c1b98dcbcfd74befe7b5a004
push id69363
push userbmo:tnguyen@mozilla.com
push dateThu, 20 Jul 2017 08:04:39 +0000
bugs1378680
milestone56.0a1
Bug 1378680 - Use fallible alloc in url-classifier MozReview-Commit-ID: BxkLrz2eqeA
toolkit/components/url-classifier/Classifier.cpp
toolkit/components/url-classifier/HashStore.cpp
toolkit/components/url-classifier/HashStore.h
toolkit/components/url-classifier/LookupCache.cpp
toolkit/components/url-classifier/ProtocolParser.cpp
toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
--- a/toolkit/components/url-classifier/Classifier.cpp
+++ b/toolkit/components/url-classifier/Classifier.cpp
@@ -484,20 +484,20 @@ Classifier::Check(const nsACString& aSpe
       LookupCache *cache = cacheArray[i];
       bool has, confirmed;
       uint32_t matchLength;
 
       rv = cache->Has(lookupHash, &has, &matchLength, &confirmed);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (has) {
-        LookupResult *result = aResults.AppendElement();
-        if (!result)
+        LookupResult *result = aResults.AppendElement(fallible);
+        if (!result) {
           return NS_ERROR_OUT_OF_MEMORY;
-
+        }
         LOG(("Found a result in %s: %s",
              cache->TableName().get(),
              confirmed ? "confirmed." : "Not confirmed."));
 
         result->hash.complete = lookupHash;
         result->mConfirmed = confirmed;
         result->mTableName.Assign(cache->TableName());
         result->mPartialHashLength = confirmed ? COMPLETE_SIZE : matchLength;
--- a/toolkit/components/url-classifier/HashStore.cpp
+++ b/toolkit/components/url-classifier/HashStore.cpp
@@ -193,22 +193,29 @@ TableUpdateV4::NewPrefixes(int32_t aSize
 
     LOG(("---- %" PRIuSIZE " fixed-length prefixes in total.", aPrefixes.size() / aSize));
   }
 
   PrefixStdString* prefix = new PrefixStdString(aPrefixes);
   mPrefixesMap.Put(aSize, prefix);
 }
 
-void
+nsresult
 TableUpdateV4::NewRemovalIndices(const uint32_t* aIndices, size_t aNumOfIndices)
 {
+  MOZ_ASSERT(mRemovalIndiceArray.IsEmpty(), "mRemovalIndiceArray must be empty");
+
+  if (!mRemovalIndiceArray.SetCapacity(aNumOfIndices, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   for (size_t i = 0; i < aNumOfIndices; i++) {
     mRemovalIndiceArray.AppendElement(aIndices[i]);
   }
+  return NS_OK;
 }
 
 void
 TableUpdateV4::NewChecksum(const std::string& aChecksum)
 {
   mChecksum.Assign(aChecksum.data(), aChecksum.size());
 }
 
@@ -587,18 +594,19 @@ Merge(ChunkSet* aStoreChunks,
     // case?
     while (storeIter < storeEnd && (storeIter->Compare(updatePrefix) < 0)) {
       // skip forward to matching element (or not...)
       storeIter++;
     }
     // no match, add
     if (storeIter == storeEnd
         || storeIter->Compare(updatePrefix) != 0) {
-      if (!adds.AppendElement(updatePrefix))
+      if (!adds.AppendElement(updatePrefix, fallible)) {
         return NS_ERROR_OUT_OF_MEMORY;
+      }
     }
   }
 
   // Chunks can be empty, but we should still report we have them
   // to make the chunkranges continuous.
   aStoreChunks->Merge(aUpdateChunks);
 
   if (!aStorePrefixes->AppendElements(adds, fallible))
@@ -934,19 +942,21 @@ HashStore::WriteAddPrefixes(nsIOutputStr
 
 nsresult
 HashStore::WriteSubPrefixes(nsIOutputStream* aOut)
 {
   nsTArray<uint32_t> addchunks;
   nsTArray<uint32_t> subchunks;
   nsTArray<uint32_t> prefixes;
   uint32_t count = mSubPrefixes.Length();
-  addchunks.SetCapacity(count);
-  subchunks.SetCapacity(count);
-  prefixes.SetCapacity(count);
+  if (!addchunks.SetCapacity(count, fallible) ||
+      !subchunks.SetCapacity(count, fallible) ||
+      !prefixes.SetCapacity(count, fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   for (uint32_t i = 0; i < count; i++) {
     addchunks.AppendElement(mSubPrefixes[i].AddChunk());
     prefixes.AppendElement(mSubPrefixes[i].PrefixHash().ToUint32());
     subchunks.AppendElement(mSubPrefixes[i].Chunk());
   }
 
   nsresult rv = ByteSliceWrite(aOut, addchunks);
--- a/toolkit/components/url-classifier/HashStore.h
+++ b/toolkit/components/url-classifier/HashStore.h
@@ -179,19 +179,20 @@ public:
   const nsACString& Checksum() const { return mChecksum; }
   const FullHashResponseMap& FullHashResponse() const { return mFullHashResponseMap; }
 
   // For downcasting.
   static const int TAG = 4;
 
   void SetFullUpdate(bool aIsFullUpdate) { mFullUpdate = aIsFullUpdate; }
   void NewPrefixes(int32_t aSize, std::string& aPrefixes);
-  void NewRemovalIndices(const uint32_t* aIndices, size_t aNumOfIndices);
   void SetNewClientState(const nsACString& aState) { mClientState = aState; }
   void NewChecksum(const std::string& aChecksum);
+
+  nsresult NewRemovalIndices(const uint32_t* aIndices, size_t aNumOfIndices);
   nsresult NewFullHashResponse(const Prefix& aPrefix,
                                CachedFullHashResponse& aResponse);
 
 private:
   virtual int Tag() const override { return TAG; }
 
   bool mFullUpdate;
   PrefixStdStringMap mPrefixesMap;
--- a/toolkit/components/url-classifier/LookupCache.cpp
+++ b/toolkit/components/url-classifier/LookupCache.cpp
@@ -613,17 +613,20 @@ LookupCacheV2::IsEmpty()
 nsresult
 LookupCacheV2::Build(AddPrefixArray& aAddPrefixes,
                      AddCompleteArray& aAddCompletes)
 {
   Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_COMPLETIONS,
                         static_cast<uint32_t>(aAddCompletes.Length()));
 
   mUpdateCompletions.Clear();
-  mUpdateCompletions.SetCapacity(aAddCompletes.Length());
+  if (!mUpdateCompletions.SetCapacity(aAddCompletes.Length(), fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   for (uint32_t i = 0; i < aAddCompletes.Length(); i++) {
     mUpdateCompletions.AppendElement(aAddCompletes[i].CompleteHash());
   }
   aAddCompletes.Clear();
   mUpdateCompletions.Sort();
 
   Telemetry::Accumulate(Telemetry::URLCLASSIFIER_LC_PREFIXES,
                         static_cast<uint32_t>(aAddPrefixes.Length()));
@@ -680,18 +683,22 @@ nsresult
 LookupCacheV2::ReadCompletions()
 {
   HashStore store(mTableName, mProvider, mRootStoreDirectory);
 
   nsresult rv = store.Open();
   NS_ENSURE_SUCCESS(rv, rv);
 
   mUpdateCompletions.Clear();
+  const AddCompleteArray& addComplete = store.AddCompletes();
 
-  const AddCompleteArray& addComplete = store.AddCompletes();
+  if (!mUpdateCompletions.SetCapacity(addComplete.Length(), fallible)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   for (uint32_t i = 0; i < addComplete.Length(); i++) {
     mUpdateCompletions.AppendElement(addComplete[i].complete);
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/toolkit/components/url-classifier/ProtocolParser.cpp
+++ b/toolkit/components/url-classifier/ProtocolParser.cpp
@@ -336,17 +336,20 @@ ProtocolParserV2::ProcessForward(const n
 nsresult
 ProtocolParserV2::AddForward(const nsACString& aUrl)
 {
   if (!mTableUpdate) {
     NS_WARNING("Forward without a table name.");
     return NS_ERROR_FAILURE;
   }
 
-  ForwardedUpdate *forward = mForwards.AppendElement();
+  ForwardedUpdate *forward = mForwards.AppendElement(fallible);
+  if (!forward) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   forward->table = mTableUpdate->TableName();
   forward->url.Assign(aUrl);
 
   return NS_OK;
 }
 
 nsresult
 ProtocolParserV2::ProcessChunk(bool* aDone)
@@ -965,18 +968,22 @@ ProtocolParserProtobuf::ProcessRawRemova
     return NS_OK;
   }
 
   // indices is an array of int32.
   auto indices = aRemoval.raw_indices().indices();
   PARSER_LOG(("* Raw removal"));
   PARSER_LOG(("  - # of removal: %d", indices.size()));
 
-  aTableUpdate.NewRemovalIndices((const uint32_t*)indices.data(),
-                                 indices.size());
+  nsresult rv = aTableUpdate.NewRemovalIndices((const uint32_t*)indices.data(),
+                                               indices.size());
+  if (NS_FAILED(rv)) {
+    PARSER_LOG(("Failed to create new removal indices."));
+    return rv;
+  }
 
   return NS_OK;
 }
 
 static nsresult
 DoRiceDeltaDecode(const RiceDeltaEncoding& aEncoding,
                   nsTArray<uint32_t>& aDecoded)
 {
@@ -1099,15 +1106,19 @@ ProtocolParserProtobuf::ProcessEncodedRe
   nsTArray<uint32_t> decoded;
   nsresult rv = DoRiceDeltaDecode(aRemoval.rice_indices(), decoded);
   if (NS_FAILED(rv)) {
     PARSER_LOG(("Failed to decode encoded removal indices."));
     return rv;
   }
 
   // The encoded prefixes are always 4 bytes.
-  aTableUpdate.NewRemovalIndices(&decoded[0], decoded.Length());
+  rv = aTableUpdate.NewRemovalIndices(&decoded[0], decoded.Length());
+  if (NS_FAILED(rv)) {
+    PARSER_LOG(("Failed to create new removal indices."));
+    return rv;
+  }
 
   return NS_OK;
 }
 
 } // namespace safebrowsing
 } // namespace mozilla
--- a/toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
+++ b/toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
@@ -128,17 +128,19 @@ VariableLengthPrefixSet::GetPrefixes(Pre
   // 4-bytes prefixes are handled by nsUrlClassifierPrefixSet.
   FallibleTArray<uint32_t> array;
   nsresult rv = mFixedPrefixSet->GetPrefixesNative(array);
   NS_ENSURE_SUCCESS(rv, rv);
 
   size_t count = array.Length();
   if (count) {
     nsCString* prefixes = new nsCString();
-    prefixes->SetLength(PREFIX_SIZE_FIXED * count);
+    if (!prefixes->SetLength(PREFIX_SIZE_FIXED * count, fallible)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     // Writing integer array to character array
     uint32_t* begin = reinterpret_cast<uint32_t*>(prefixes->BeginWriting());
     for (uint32_t i = 0; i < count; i++) {
       begin[i] = NativeEndian::swapToBigEndian(array[i]);
     }
 
     aPrefixMap.Put(PREFIX_SIZE_FIXED, prefixes);
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -151,17 +151,17 @@ nsUrlClassifierDBServiceWorker::QueueLoo
                                             const nsACString& tables,
                                             nsIUrlClassifierLookupCallback* callback)
 {
   MutexAutoLock lock(mPendingLookupLock);
   if (gShuttingDownThread) {
       return NS_ERROR_ABORT;
   }
 
-  PendingLookup* lookup = mPendingLookups.AppendElement();
+  PendingLookup* lookup = mPendingLookups.AppendElement(fallible);
   if (!lookup) return NS_ERROR_OUT_OF_MEMORY;
 
   lookup->mStartTime = TimeStamp::Now();
   lookup->mKey = spec;
   lookup->mCallback = callback;
   lookup->mTables = tables;
 
   return NS_OK;
@@ -229,17 +229,17 @@ nsUrlClassifierDBServiceWorker::DoLookup
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   PRIntervalTime clockStart = 0;
   if (LOG_ENABLED()) {
     clockStart = PR_IntervalNow();
   }
 
-  nsAutoPtr<LookupResultArray> results(new LookupResultArray());
+  nsAutoPtr<LookupResultArray> results(new (fallible) LookupResultArray());
   if (!results) {
     c->LookupComplete(nullptr);
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = DoLocalLookup(spec, tables, results);
   if (NS_FAILED(rv)) {
     c->LookupComplete(nullptr);
@@ -315,19 +315,20 @@ nsUrlClassifierDBServiceWorker::AddNoise
   }
 
   PrefixArray noiseEntries;
   nsresult rv = mClassifier->ReadNoiseEntries(aPrefix, tableName,
                                               aCount, &noiseEntries);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (uint32_t i = 0; i < noiseEntries.Length(); i++) {
-    LookupResult *result = results.AppendElement();
-    if (!result)
+    LookupResult *result = results.AppendElement(fallible);
+    if (!result) {
       return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     result->hash.fixedLengthPrefix = noiseEntries[i];
     result->mNoise = true;
     result->mPartialHashLength = PREFIX_SIZE; // Noise is always 4-byte,
     result->mTableName.Assign(tableName);
   }
 
   return NS_OK;
@@ -451,20 +452,23 @@ nsUrlClassifierDBServiceWorker::BeginStr
 
     if (useProtobuf != isCurProtobuf) {
       NS_WARNING("Cannot mix 'proto' tables with other types "
                  "within the same provider.");
       break;
     }
   }
 
-  mProtocolParser = (useProtobuf ? static_cast<ProtocolParser*>(new ProtocolParserProtobuf())
-                                 : static_cast<ProtocolParser*>(new ProtocolParserV2()));
-  if (!mProtocolParser)
+  mProtocolParser = (useProtobuf ? static_cast<ProtocolParser*>(new (fallible)
+                                     ProtocolParserProtobuf())
+                                 : static_cast<ProtocolParser*>(new (fallible)
+                                     ProtocolParserV2()));
+  if (!mProtocolParser) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   mProtocolParser->Init(mCryptoHash);
 
   if (!table.IsEmpty()) {
     mProtocolParser->SetCurrentTable(table);
   }
 
   mProtocolParser->SetRequestedTables(mUpdateTables);
@@ -936,17 +940,17 @@ nsUrlClassifierDBServiceWorker::OpenDb()
   if (mClassifier) {
     return NS_OK;
   }
 
   nsresult rv;
   mCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAutoPtr<Classifier> classifier(new Classifier());
+  nsAutoPtr<Classifier> classifier(new (fallible) Classifier());
   if (!classifier) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   rv = classifier->Open(*mCacheDir);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mClassifier = classifier;
@@ -1217,24 +1221,24 @@ nsUrlClassifierLookupCallback::Completio
   return ProcessComplete(result.forget());
 }
 
 nsresult
 nsUrlClassifierLookupCallback::ProcessComplete(CacheResult* aCacheResult)
 {
   // Send this completion to the store for caching.
   if (!mCacheResults) {
-    mCacheResults = new CacheResultArray();
+    mCacheResults = new (fallible) CacheResultArray();
     if (!mCacheResults) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // OK if this fails, we just won't cache the item.
-  mCacheResults->AppendElement(aCacheResult);
+  mCacheResults->AppendElement(aCacheResult, fallible);
 
   // Check if this matched any of our results.
   for (uint32_t i = 0; i < mResults->Length(); i++) {
     LookupResult& result = mResults->ElementAt(i);
 
     // Now, see if it verifies a lookup
     if (!result.mNoise
         && result.mTableName.Equals(aCacheResult->table)
@@ -1324,28 +1328,30 @@ nsUrlClassifierLookupCallback::CacheMiss
     const LookupResult &result = mResults->ElementAt(i);
     // Skip V4 because cache information is already included in the
     // fullhash response so we don't need to manually add it here.
     if (!result.mProtocolV2 || result.Confirmed() || result.mNoise) {
       continue;
     }
 
     if (!mCacheResults) {
-      mCacheResults = new CacheResultArray();
+      mCacheResults = new (fallible) CacheResultArray();
       if (!mCacheResults) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
 
     auto cacheResult = new CacheResultV2;
 
     cacheResult->table = result.mTableName;
     cacheResult->prefix = result.hash.fixedLengthPrefix;
     cacheResult->miss = true;
-    mCacheResults->AppendElement(cacheResult);
+    if (!mCacheResults->AppendElement(cacheResult, fallible)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
   }
   return NS_OK;
 }
 
 struct Provider {
   nsCString name;
   uint8_t priority;
 };
@@ -1467,17 +1473,17 @@ NS_INTERFACE_MAP_BEGIN(nsUrlClassifierDB
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIClassifier)
 NS_INTERFACE_MAP_END
 
 /* static */ nsUrlClassifierDBService*
 nsUrlClassifierDBService::GetInstance(nsresult *result)
 {
   *result = NS_OK;
   if (!sUrlClassifierDBService) {
-    sUrlClassifierDBService = new nsUrlClassifierDBService();
+    sUrlClassifierDBService = new (fallible) nsUrlClassifierDBService();
     if (!sUrlClassifierDBService) {
       *result = NS_ERROR_OUT_OF_MEMORY;
       return nullptr;
     }
 
     NS_ADDREF(sUrlClassifierDBService);   // addref the global
 
     *result = sUrlClassifierDBService->Init();
@@ -1630,19 +1636,20 @@ nsUrlClassifierDBService::Init()
     }
   }
 
   // Start the background thread.
   rv = NS_NewNamedThread("URL Classifier", &gDbBackgroundThread);
   if (NS_FAILED(rv))
     return rv;
 
-  mWorker = new nsUrlClassifierDBServiceWorker();
-  if (!mWorker)
+  mWorker = new (fallible) nsUrlClassifierDBServiceWorker();
+  if (!mWorker) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   rv = mWorker->Init(sGethashNoise, cacheDir, this);
   if (NS_FAILED(rv)) {
     mWorker = nullptr;
     return rv;
   }
 
   // Proxy for calling the worker on the background thread
@@ -1722,17 +1729,17 @@ nsUrlClassifierDBService::Classify(nsIPr
 
   if (!(mCheckMalware || mCheckPhishing || aTrackingProtectionEnabled ||
         mCheckBlockedURIs)) {
     *result = false;
     return NS_OK;
   }
 
   RefPtr<nsUrlClassifierClassifyCallback> callback =
-    new nsUrlClassifierClassifyCallback(c);
+    new (fallible) nsUrlClassifierClassifyCallback(c);
 
   if (!callback) return NS_ERROR_OUT_OF_MEMORY;
 
   nsCString tables = mBaseTables;
   if (aTrackingProtectionEnabled) {
     AppendTables(mTrackingProtectionTables, tables);
   }
 
@@ -1901,17 +1908,17 @@ nsUrlClassifierDBService::ClassifyLocalW
 
   nsAutoCString key;
   // Canonicalize the url
   nsCOMPtr<nsIUrlClassifierUtils> utilsService =
     do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
   rv = utilsService->GetKeyForURI(uri, key);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsAutoPtr<LookupResultArray> results(new LookupResultArray());
+  nsAutoPtr<LookupResultArray> results(new (fallible) LookupResultArray());
   if (!results) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // In unittests, we may not have been initalized, so don't crash.
   rv = mWorkerProxy->DoLocalLookup(key, aTables, results);
   if (NS_SUCCEEDED(rv)) {
     rv = ProcessLookupResults(results, aTableResults);
@@ -1986,19 +1993,20 @@ nsUrlClassifierDBService::LookupURI(nsIP
       return NS_OK;
     }
   }
 
   // Create an nsUrlClassifierLookupCallback object.  This object will
   // take care of confirming partial hash matches if necessary before
   // calling the client's callback.
   nsCOMPtr<nsIUrlClassifierLookupCallback> callback =
-    new nsUrlClassifierLookupCallback(this, c);
-  if (!callback)
+    new (fallible) nsUrlClassifierLookupCallback(this, c);
+  if (!callback) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   nsCOMPtr<nsIUrlClassifierLookupCallback> proxyCallback =
     new UrlClassifierLookupCallbackProxy(callback);
 
   // Queue this lookup and call the lookup function to flush the queue if
   // necessary.
   rv = mWorker->QueueLookup(key, tables, proxyCallback);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
@@ -114,22 +114,31 @@ nsUrlClassifierPrefixSet::MakePrefixSet(
   uint32_t previousItem = aPrefixes[0];
   for (uint32_t i = 1; i < aLength; i++) {
     if ((numOfDeltas >= DELTAS_LIMIT) ||
           (aPrefixes[i] - previousItem >= MAX_INDEX_DIFF)) {
       // Compact the previous element.
       // Note there is always at least one element when we get here,
       // because we created the first element before the loop.
       mIndexDeltas.LastElement().Compact();
-      mIndexDeltas.AppendElement();
-      mIndexPrefixes.AppendElement(aPrefixes[i]);
+      if (!mIndexDeltas.AppendElement(fallible)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+
+      if (!mIndexPrefixes.AppendElement(aPrefixes[i], fallible)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+
       numOfDeltas = 0;
     } else {
       uint16_t delta = aPrefixes[i] - previousItem;
-      mIndexDeltas.LastElement().AppendElement(delta);
+      if (!mIndexDeltas.LastElement().AppendElement(delta, fallible)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+
       numOfDeltas++;
       totalDeltas++;
     }
     previousItem = aPrefixes[i];
   }
 
   mIndexDeltas.LastElement().Compact();
   mIndexDeltas.Compact();
@@ -415,19 +424,21 @@ nsUrlClassifierPrefixSet::LoadPrefixes(n
       return NS_OK;
     }
 
     if (deltaSize > (indexSize * DELTAS_LIMIT)) {
       return NS_ERROR_FILE_CORRUPTED;
     }
 
     nsTArray<uint32_t> indexStarts;
-    indexStarts.SetLength(indexSize);
-    mIndexPrefixes.SetLength(indexSize);
-    mIndexDeltas.SetLength(indexSize);
+    if (!indexStarts.SetLength(indexSize, fallible) ||
+        !mIndexPrefixes.SetLength(indexSize, fallible) ||
+        !mIndexDeltas.SetLength(indexSize, fallible)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
 
     mTotalPrefixes = indexSize;
 
     uint32_t toRead = indexSize*sizeof(uint32_t);
     rv = in->Read(reinterpret_cast<char*>(mIndexPrefixes.Elements()), toRead, &read);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(read == toRead, NS_ERROR_FAILURE);
 
@@ -440,17 +451,19 @@ nsUrlClassifierPrefixSet::LoadPrefixes(n
     }
     for (uint32_t i = 0; i < indexSize; i++) {
       uint32_t numInDelta = i == indexSize - 1 ? deltaSize - indexStarts[i]
                                : indexStarts[i + 1] - indexStarts[i];
       if (numInDelta > DELTAS_LIMIT) {
         return NS_ERROR_FILE_CORRUPTED;
       }
       if (numInDelta > 0) {
-        mIndexDeltas[i].SetLength(numInDelta);
+        if (!mIndexDeltas[i].SetLength(numInDelta, fallible)) {
+          return NS_ERROR_OUT_OF_MEMORY;
+        }
         mTotalPrefixes += numInDelta;
         toRead = numInDelta * sizeof(uint16_t);
         rv = in->Read(reinterpret_cast<char*>(mIndexDeltas[i].Elements()), toRead, &read);
         NS_ENSURE_SUCCESS(rv, rv);
         NS_ENSURE_TRUE(read == toRead, NS_ERROR_FAILURE);
       }
     }
   } else {
@@ -494,17 +507,19 @@ nsUrlClassifierPrefixSet::WritePrefixes(
   // If we ever update the format, we can gain space by storing the delta
   // subarray sizes, which fit in bytes.
   nsTArray<uint32_t> indexStarts;
   indexStarts.AppendElement(0);
 
   for (uint32_t i = 0; i < indexDeltaSize; i++) {
     uint32_t deltaLength = mIndexDeltas[i].Length();
     totalDeltas += deltaLength;
-    indexStarts.AppendElement(totalDeltas);
+    if (!indexStarts.AppendElement(totalDeltas, fallible)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
   }
 
   rv = out->Write(reinterpret_cast<char*>(&indexSize), writelen, &written);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(written == writelen, NS_ERROR_FAILURE);
 
   rv = out->Write(reinterpret_cast<char*>(&totalDeltas), writelen, &written);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
@@ -22,16 +22,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/Telemetry.h"
 #include "nsContentUtils.h"
 #include "nsIURLFormatter.h"
 #include "Classifier.h"
 
 using namespace mozilla::safebrowsing;
+using namespace mozilla;
 
 #define DEFAULT_RESPONSE_TIMEOUT_MS 15 * 1000
 #define DEFAULT_TIMEOUT_MS 60 * 1000
 static_assert(DEFAULT_TIMEOUT_MS > DEFAULT_RESPONSE_TIMEOUT_MS,
   "General timeout must be greater than reponse timeout");
 
 static const char* gQuitApplicationMessage = "quit-application";
 
@@ -278,17 +279,20 @@ nsUrlClassifierStreamUpdater::DownloadUp
   NS_ENSURE_ARG(aSuccessCallback);
   NS_ENSURE_ARG(aUpdateErrorCallback);
   NS_ENSURE_ARG(aDownloadErrorCallback);
 
   if (mIsUpdating) {
     LOG(("Already updating, queueing update %s from %s", aRequestPayload.Data(),
          aUpdateUrl.Data()));
     *_retval = false;
-    PendingRequest *request = mPendingRequests.AppendElement();
+    PendingRequest *request = mPendingRequests.AppendElement(fallible);
+    if (!request) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     request->mTables = aRequestTables;
     request->mRequestPayload = aRequestPayload;
     request->mIsPostRequest = aIsPostRequest;
     request->mUrl = aUpdateUrl;
     request->mSuccessCallback = aSuccessCallback;
     request->mUpdateErrorCallback = aUpdateErrorCallback;
     request->mDownloadErrorCallback = aDownloadErrorCallback;
     return NS_OK;
@@ -318,17 +322,20 @@ nsUrlClassifierStreamUpdater::DownloadUp
     mInitialized = true;
   }
 
   rv = mDBService->BeginUpdate(this, aRequestTables);
   if (rv == NS_ERROR_NOT_AVAILABLE) {
     LOG(("Service busy, already updating, queuing update %s from %s",
          aRequestPayload.Data(), aUpdateUrl.Data()));
     *_retval = false;
-    PendingRequest *request = mPendingRequests.AppendElement();
+    PendingRequest *request = mPendingRequests.AppendElement(fallible);
+    if (!request) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     request->mTables = aRequestTables;
     request->mRequestPayload = aRequestPayload;
     request->mIsPostRequest = aIsPostRequest;
     request->mUrl = aUpdateUrl;
     request->mSuccessCallback = aSuccessCallback;
     request->mUpdateErrorCallback = aUpdateErrorCallback;
     request->mDownloadErrorCallback = aDownloadErrorCallback;
 
@@ -373,19 +380,20 @@ nsUrlClassifierStreamUpdater::DownloadUp
 // nsIUrlClassifierUpdateObserver implementation
 
 NS_IMETHODIMP
 nsUrlClassifierStreamUpdater::UpdateUrlRequested(const nsACString &aUrl,
                                                  const nsACString &aTable)
 {
   LOG(("Queuing requested update from %s\n", PromiseFlatCString(aUrl).get()));
 
-  PendingUpdate *update = mPendingUpdates.AppendElement();
-  if (!update)
+  PendingUpdate *update = mPendingUpdates.AppendElement(fallible);
+  if (!update) {
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   // Allow data: and file: urls for unit testing purposes, otherwise assume http
   if (StringBeginsWith(aUrl, NS_LITERAL_CSTRING("data:")) ||
       StringBeginsWith(aUrl, NS_LITERAL_CSTRING("file:"))) {
     update->mUrl = aUrl;
   } else {
     // For unittesting update urls to localhost should use http, not https
     // (otherwise the connection will fail silently, since there will be no