Bug 1179301 - Restrict the SafeBrowsingHash size and make toUint32/fromUint32 more robust. r?gcp draft
authorHenry Chang <hchang@mozilla.com>
Thu, 18 Aug 2016 14:42:13 +0800
changeset 404864 b83f0017fbfc7256da78666e9f07d618ed651074
parent 403581 f97a056ae6235de7855fd8aaa04fb1c8d183bd06
child 529305 99de7b9b12b7d1f4a0cccd5509472120c54ed2f7
push id27339
push userhchang@mozilla.com
push dateWed, 24 Aug 2016 10:49:12 +0000
reviewersgcp
bugs1179301
milestone51.0a1
Bug 1179301 - Restrict the SafeBrowsingHash size and make toUint32/fromUint32 more robust. r?gcp MozReview-Commit-ID: EPQLeuab42W
toolkit/components/url-classifier/Entries.h
toolkit/components/url-classifier/tests/gtest/TestSafebrowsingHash.cpp
toolkit/components/url-classifier/tests/gtest/moz.build
--- 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'