Bug 1179301 - Restrict the SafeBrowsingHash size and make toUint32/fromUint32 more robust. r?gcp
MozReview-Commit-ID: EPQLeuab42W
--- a/toolkit/components/url-classifier/Entries.h
+++ b/toolkit/components/url-classifier/Entries.h
@@ -25,16 +25,18 @@ namespace safebrowsing {
#define PREFIX_SIZE 4
#define COMPLETE_SIZE 32
// This is the struct that contains 4-byte hash prefixes.
template <uint32_t S, class Comparator>
struct SafebrowsingHash
{
+ static_assert(S >= 4, "The SafebrowsingHash should be at least 4 bytes.");
+
static const uint32_t sHashSize = S;
typedef SafebrowsingHash<S, Comparator> self_type;
uint8_t buf[S];
nsresult FromPlaintext(const nsACString& aPlainText, nsICryptoHash* aHash) {
// From the protocol doc:
// Each entry in the chunk is composed
// of the SHA 256 hash of a suffix/prefix expression.
@@ -99,28 +101,34 @@ struct SafebrowsingHash
for (size_t i = 0; i < len; ++i) {
const char c = static_cast<const char>(buf[i]);
aStr.Append(lut[(c >> 4) & 0x0F]);
aStr.Append(lut[c & 15]);
}
}
uint32_t ToUint32() const {
- return *((uint32_t*)buf);
+ uint32_t n;
+ memcpy(&n, buf, sizeof(n));
+ return n;
}
void FromUint32(uint32_t aHash) {
- *((uint32_t*)buf) = aHash;
+ memcpy(buf, &aHash, sizeof(aHash));
}
};
class PrefixComparator {
public:
static int Compare(const uint8_t* a, const uint8_t* b) {
- uint32_t first = *((uint32_t*)a);
- uint32_t second = *((uint32_t*)b);
+ uint32_t first;
+ memcpy(&first, a, sizeof(uint32_t));
+
+ uint32_t second;
+ memcpy(&second, b, sizeof(uint32_t));
+
if (first > second) {
return 1;
} else if (first == second) {
return 0;
} else {
return -1;
}
}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/url-classifier/tests/gtest/TestSafebrowsingHash.cpp
@@ -0,0 +1,52 @@
+#include "Entries.h"
+#include "mozilla/EndianUtils.h"
+
+TEST(SafebrowsingHash, ToFromUint32)
+{
+ using namespace mozilla::safebrowsing;
+
+ // typedef SafebrowsingHash<PREFIX_SIZE, PrefixComparator> Prefix;
+ // typedef nsTArray<Prefix> PrefixArray;
+
+ const char PREFIX_RAW[4] = { 0x1, 0x2, 0x3, 0x4 };
+ uint32_t PREFIX_UINT32;
+ memcpy(&PREFIX_UINT32, PREFIX_RAW, 4);
+
+ Prefix p;
+ p.Assign(nsCString(PREFIX_RAW, 4));
+ ASSERT_EQ(p.ToUint32(), PREFIX_UINT32);
+
+ p.FromUint32(PREFIX_UINT32);
+ ASSERT_EQ(memcmp(PREFIX_RAW, p.buf, 4), 0);
+}
+
+TEST(SafebrowsingHash, Compare)
+{
+ using namespace mozilla;
+ using namespace mozilla::safebrowsing;
+
+ Prefix p1, p2, p3;
+
+ // The order of p1,p2,p3 is "p1 == p3 < p2"
+#if MOZ_LITTLE_ENDIAN
+ p1.Assign(nsCString("\x01\x00\x00\x00", 4));
+ p2.Assign(nsCString("\x00\x00\x00\x01", 4));
+ p3.Assign(nsCString("\x01\x00\x00\x00", 4));
+#else
+ p1.Assign(nsCString("\x00\x00\x00\x01", 4));
+ p2.Assign(nsCString("\x01\x00\x00\x00", 4));
+ p3.Assign(nsCString("\x00\x00\x00\x01", 4));
+#endif
+
+ // Make sure "p1 == p3 < p2" is true
+ // on both little and big endian machine.
+
+ ASSERT_EQ(p1.Compare(p2), -1);
+ ASSERT_EQ(p1.Compare(p1), 0);
+ ASSERT_EQ(p2.Compare(p1), 1);
+ ASSERT_EQ(p1.Compare(p3), 0);
+
+ ASSERT_TRUE(p1 < p2);
+ ASSERT_TRUE(p1 == p1);
+ ASSERT_TRUE(p1 == p3);
+}
\ No newline at end of file
--- a/toolkit/components/url-classifier/tests/gtest/moz.build
+++ b/toolkit/components/url-classifier/tests/gtest/moz.build
@@ -5,13 +5,14 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
LOCAL_INCLUDES += [
'../..',
]
UNIFIED_SOURCES += [
'TestChunkSet.cpp',
+ 'TestSafebrowsingHash.cpp',
'TestSafeBrowsingProtobuf.cpp',
'TestUrlClassifierUtils.cpp',
]
FINAL_LIBRARY = 'xul-gtest'