Bug 669410 - Prevent hash collisions from occuring in the same place in every client. r=tony

See also bug 669407.
This commit is contained in:
Gian-Carlo Pascutto
2011-09-08 22:17:25 +02:00
parent b6aee54606
commit 397818839e
4 changed files with 224 additions and 29 deletions

View File

@@ -44,6 +44,7 @@
#include "nsTArray.h"
#include "nsUrlClassifierPrefixSet.h"
#include "nsIUrlClassifierPrefixSet.h"
#include "nsIRandomGenerator.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#include "nsToolkitCompsCID.h"
@@ -70,13 +71,36 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSe
nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
: mPrefixSetLock("mPrefixSetLock"),
mSetIsReady(mPrefixSetLock, "mSetIsReady"),
mHasPrefixes(PR_FALSE)
mHasPrefixes(PR_FALSE),
mRandomKey(0)
{
#if defined(PR_LOGGING)
if (!gUrlClassifierPrefixSetLog)
gUrlClassifierPrefixSetLog = PR_NewLogModule("UrlClassifierPrefixSet");
#endif
LOG(("Instantiating PrefixSet"));
nsresult rv = InitKey();
if (NS_FAILED(rv)) {
LOG(("Failed to initialize PrefixSet"));
}
}
nsresult
nsUrlClassifierPrefixSet::InitKey()
{
nsCOMPtr<nsIRandomGenerator> rg =
do_GetService("@mozilla.org/security/random-generator;1");
NS_ENSURE_STATE(rg);
PRUint8 *temp;
nsresult rv = rg->GenerateRandomBytes(sizeof(mRandomKey), &temp);
NS_ENSURE_SUCCESS(rv, rv);
memcpy(&mRandomKey, temp, sizeof(mRandomKey));
NS_Free(temp);
LOG(("Initialized PrefixSet, key = %X", mRandomKey));
return NS_OK;
}
NS_IMETHODIMP
@@ -196,7 +220,7 @@ nsUrlClassifierPrefixSet::Contains(PRUint32 aPrefix, PRBool * aFound)
// Because of this, we need to check if the target lies before the beginning
// of the indices.
int i = BinSearch(0, mIndexPrefixes.Length() - 1, target);
PRUint32 i = BinSearch(0, mIndexPrefixes.Length() - 1, target);
if (mIndexPrefixes[i] > target && i > 0) {
i--;
}
@@ -240,10 +264,30 @@ nsUrlClassifierPrefixSet::IsEmpty(PRBool * aEmpty)
}
NS_IMETHODIMP
nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix, PRBool * aReady, PRBool * aFound)
nsUrlClassifierPrefixSet::GetKey(PRUint32 * aKey)
{
MutexAutoLock lock(mPrefixSetLock);
*aKey = mRandomKey;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierPrefixSet::Probe(PRUint32 aPrefix, PRUint32 aKey,
PRBool* aReady, PRBool* aFound)
{
MutexAutoLock lock(mPrefixSetLock);
// We might have raced here with a LoadPrefixSet call,
// loading a saved PrefixSet with another key than the one used to probe us.
// This must occur exactly between the GetKey call and the Probe call.
// This could cause a false negative immediately after browser start.
// Claim we are still busy loading instead.
if (aKey != mRandomKey) {
LOG(("Potential race condition detected, avoiding"));
*aReady = PR_FALSE;
return NS_OK;
}
// check whether we are opportunistically probing or should wait
if (*aReady) {
// we should block until we are ready
@@ -279,6 +323,8 @@ nsUrlClassifierPrefixSet::LoadFromFd(AutoFDClose & fileFd)
PRUint32 indexSize;
PRUint32 deltaSize;
read = PR_Read(fileFd, &mRandomKey, sizeof(PRUint32));
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
read = PR_Read(fileFd, &indexSize, sizeof(PRUint32));
NS_ENSURE_TRUE(read > 0, NS_ERROR_FAILURE);
read = PR_Read(fileFd, &deltaSize, sizeof(PRUint32));
@@ -346,6 +392,9 @@ nsUrlClassifierPrefixSet::StoreToFd(AutoFDClose & fileFd)
written = PR_Write(fileFd, &magic, sizeof(PRUint32));
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
written = PR_Write(fileFd, &mRandomKey, sizeof(PRUint32));
NS_ENSURE_TRUE(written > 0, NS_ERROR_FAILURE);
PRUint32 indexSize = mIndexStarts.Length();
PRUint32 deltaSize = mDeltas.Length();
written = PR_Write(fileFd, &indexSize, sizeof(PRUint32));