Bug 1378680 - Refactor usage fallible alloc in url-classifier r=francois
authorThomas Nguyen <tnguyen@mozilla.com>
Thu, 20 Jul 2017 16:20:27 +0800
changeset 371148 84e29e660f0cfd4a11d8081cea2d07f93f1ede00
parent 371147 3b4442aa9040dd915b73dd7ef3639f822208675e
child 371149 382ac74f97a20dd13918d7e0891766bfd4efa001
push id93039
push userkwierso@gmail.com
push dateThu, 27 Jul 2017 01:33:28 +0000
treeherdermozilla-inbound@35b0bdaacb0d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrancois
bugs1378680
milestone56.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 1378680 - Refactor usage fallible alloc in url-classifier r=francois MozReview-Commit-ID: HHG1ByeIwZv
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
@@ -611,17 +611,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()));
@@ -678,18 +681,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
@@ -965,18 +965,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 +1103,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