Bug 1362761 - Add checksum to nsUrlClassifierPrefixSet::mIndexDeltas array. r=gcp

Adding a checksum to an array in the URL classifier to test our
theory that the crashes are due to memory corruption.

This patch also restores the Compact() calls that were #ifdef'd
out in bug 1362761 to test a different theory.

MozReview-Commit-ID: IkLduLO3IXb

--HG--
extra : rebase_source : 3e628618aacddfc19c154e6e5c7bf78d8b4b5aa3
This commit is contained in:
Francois Marier 2018-02-15 16:59:14 -08:00
parent c8a2d994c8
commit 42aba66c3c
3 changed files with 42 additions and 8 deletions

View File

@ -77,6 +77,7 @@ FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../build',
'/xpcom/io',
]
CXXFLAGS += CONFIG['SQLITE_CFLAGS']

View File

@ -6,6 +6,7 @@
#include "nsUrlClassifierPrefixSet.h"
#include "nsIUrlClassifierPrefixSet.h"
#include "crc32c.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsPrintfCString.h"
@ -41,6 +42,7 @@ const uint32_t nsUrlClassifierPrefixSet::MAX_BUFFER_SIZE;
nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
: mLock("nsUrlClassifierPrefixSet.mLock")
, mIndexDeltasChecksum(~0)
, mTotalPrefixes(0)
, mMemoryReportPath()
{
@ -117,10 +119,6 @@ nsUrlClassifierPrefixSet::MakePrefixSet(const uint32_t* aPrefixes, uint32_t aLen
// 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.
// Bug 1362761 : Remove Compact from NIGHTLY build for debug purpose
#ifndef NIGHTLY_BUILD
mIndexDeltas.LastElement().Compact();
#endif
if (!mIndexDeltas.AppendElement(fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -142,14 +140,16 @@ nsUrlClassifierPrefixSet::MakePrefixSet(const uint32_t* aPrefixes, uint32_t aLen
previousItem = aPrefixes[i];
}
// Bug 1362761 : Remove Compact from NIGHTLY build for debug purpose
#ifndef NIGHTLY_BUILD
mIndexDeltas.LastElement().Compact();
// The hdr pointer of the last element of nsTArray may change after calling
// mIndexDeltas.LastElement().Compact(), so calculate checksum after the call.
CalculateTArrayChecksum(mIndexDeltas, &mIndexDeltasChecksum);
mIndexDeltas.Compact();
mIndexPrefixes.Compact();
#endif
LOG(("Total number of indices: %d", aLength));
LOG(("Total number of indices: %d (crc=%u)", aLength, mIndexDeltasChecksum));
LOG(("Total number of deltas: %d", totalDeltas));
LOG(("Total number of delta chunks: %zu", mIndexDeltas.Length()));
@ -504,6 +504,18 @@ nsUrlClassifierPrefixSet::WritePrefixes(nsIOutputStream* out)
{
mCanary.Check();
// In Bug 1362761, crashes happened while reading mIndexDeltas[i].
// We suspect that this is due to memory corruption so to test this
// hypothesis, we will crash the browser. Once we have established
// memory corruption as the root cause, we can attempt to gracefully
// handle this.
uint32_t checksum;
CalculateTArrayChecksum(mIndexDeltas, &checksum);
if (checksum != mIndexDeltasChecksum) {
LOG(("The contents of mIndexDeltas doesn't match the checksum!"));
MOZ_CRASH("Memory corruption detected in mIndexDeltas.");
}
uint32_t written;
uint32_t writelen = sizeof(uint32_t);
uint32_t magic = PREFIXSET_VERSION_MAGIC;
@ -561,3 +573,19 @@ nsUrlClassifierPrefixSet::WritePrefixes(nsIOutputStream* out)
return NS_OK;
}
template<typename T>
void
nsUrlClassifierPrefixSet::CalculateTArrayChecksum(nsTArray<T>& aArray,
uint32_t* outChecksum)
{
*outChecksum = ~0;
for (size_t i = 0; i < aArray.Length(); i++) {
const T& element = aArray[i];
const void* pointer = &element;
*outChecksum = ComputeCrc32c(*outChecksum,
reinterpret_cast<const uint8_t*>(pointer),
sizeof(void*));
}
}

View File

@ -68,6 +68,9 @@ private:
nsresult WritePrefixes(nsIOutputStream* out);
nsresult LoadPrefixes(nsIInputStream* in);
template<typename T>
void CalculateTArrayChecksum(nsTArray<T>& aArray, uint32_t* outChecksum);
// Lock to prevent races between the url-classifier thread (which does most
// of the operations) and the main thread (which does memory reporting).
// It should be held for all operations between Init() and destruction that
@ -81,6 +84,8 @@ private:
// prefix from mIndexPrefix. Then every "delta" corresponds
// to a prefix in the PrefixSet.
nsTArray<nsTArray<uint16_t> > mIndexDeltas;
uint32_t mIndexDeltasChecksum;
// how many prefixes we have.
uint32_t mTotalPrefixes;