LCOV - code coverage report
Current view: top level - toolkit/components/url-classifier - Entries.h (source / functions) Hit Total Coverage
Test: output.info Lines: 52 139 37.4 %
Date: 2017-07-14 16:53:18 Functions: 26 63 41.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : // This header file defines the storage types of the actual safebrowsing
       7             : // chunk data, which may be either 32-bit hashes or complete 256-bit hashes.
       8             : // Chunk numbers are represented in ChunkSet.h.
       9             : 
      10             : #ifndef SBEntries_h__
      11             : #define SBEntries_h__
      12             : 
      13             : #include "nsTArray.h"
      14             : #include "nsString.h"
      15             : #include "nsICryptoHash.h"
      16             : #include "nsNetUtil.h"
      17             : #include "nsIOutputStream.h"
      18             : #include "nsClassHashtable.h"
      19             : #include "nsDataHashtable.h"
      20             : #include "plbase64.h"
      21             : 
      22             : namespace mozilla {
      23             : namespace safebrowsing {
      24             : 
      25             : #define PREFIX_SIZE   4
      26             : #define COMPLETE_SIZE 32
      27             : 
      28             : // This is the struct that contains 4-byte hash prefixes.
      29             : template <uint32_t S, class Comparator>
      30             : struct SafebrowsingHash
      31             : {
      32             :   static_assert(S >= 4, "The SafebrowsingHash should be at least 4 bytes.");
      33             : 
      34             :   static const uint32_t sHashSize = S;
      35             :   typedef SafebrowsingHash<S, Comparator> self_type;
      36             :   uint8_t buf[S];
      37             : 
      38           9 :   nsresult FromPlaintext(const nsACString& aPlainText, nsICryptoHash* aHash) {
      39             :     // From the protocol doc:
      40             :     // Each entry in the chunk is composed
      41             :     // of the SHA 256 hash of a suffix/prefix expression.
      42             : 
      43           9 :     nsresult rv = aHash->Init(nsICryptoHash::SHA256);
      44           9 :     NS_ENSURE_SUCCESS(rv, rv);
      45             : 
      46           9 :     rv = aHash->Update
      47           9 :       (reinterpret_cast<const uint8_t*>(aPlainText.BeginReading()),
      48             :        aPlainText.Length());
      49           9 :     NS_ENSURE_SUCCESS(rv, rv);
      50             : 
      51          18 :     nsAutoCString hashed;
      52           9 :     rv = aHash->Finish(false, hashed);
      53           9 :     NS_ENSURE_SUCCESS(rv, rv);
      54             : 
      55           9 :     NS_ASSERTION(hashed.Length() >= sHashSize,
      56             :                  "not enough characters in the hash");
      57             : 
      58           9 :     memcpy(buf, hashed.BeginReading(), sHashSize);
      59             : 
      60           9 :     return NS_OK;
      61             :   }
      62             : 
      63           0 :   void Assign(const nsACString& aStr) {
      64           0 :     NS_ASSERTION(aStr.Length() >= sHashSize,
      65             :                  "string must be at least sHashSize characters long");
      66           0 :     memcpy(buf, aStr.BeginReading(), sHashSize);
      67           0 :   }
      68             : 
      69           8 :   int Compare(const self_type& aOther) const {
      70           8 :     return Comparator::Compare(buf, aOther.buf);
      71             :   }
      72             : 
      73           3 :   bool operator==(const self_type& aOther) const {
      74           3 :     return Comparator::Compare(buf, aOther.buf) == 0;
      75             :   }
      76             : 
      77           0 :   bool operator!=(const self_type& aOther) const {
      78           0 :     return Comparator::Compare(buf, aOther.buf) != 0;
      79             :   }
      80             : 
      81           4 :   bool operator<(const self_type& aOther) const {
      82           4 :     return Comparator::Compare(buf, aOther.buf) < 0;
      83             :   }
      84             : 
      85           0 :   void ToString(nsACString& aStr) const {
      86           0 :     uint32_t len = ((sHashSize + 2) / 3) * 4;
      87             : 
      88             :     // Capacity should be one greater than length, because PL_Base64Encode
      89             :     // will not be null-terminated, while nsCString requires it.
      90           0 :     aStr.SetCapacity(len + 1);
      91           0 :     PL_Base64Encode((char*)buf, sHashSize, aStr.BeginWriting());
      92           0 :     aStr.BeginWriting()[len] = '\0';
      93           0 :     aStr.SetLength(len);
      94           0 :   }
      95             : 
      96           0 :   void ToHexString(nsACString& aStr) const {
      97             :     static const char* const lut = "0123456789ABCDEF";
      98             :     // 32 bytes is the longest hash
      99           0 :     size_t len = 32;
     100             : 
     101           0 :     aStr.SetCapacity(2 * len);
     102           0 :     for (size_t i = 0; i < len; ++i) {
     103           0 :       const char c = static_cast<const char>(buf[i]);
     104           0 :       aStr.Append(lut[(c >> 4) & 0x0F]);
     105           0 :       aStr.Append(lut[c & 15]);
     106             :     }
     107           0 :   }
     108             : 
     109           4 :   uint32_t ToUint32() const {
     110             :     uint32_t n;
     111           4 :     memcpy(&n, buf, sizeof(n));
     112           4 :     return n;
     113             :   }
     114           0 :   void FromUint32(uint32_t aHash) {
     115           0 :     memcpy(buf, &aHash, sizeof(aHash));
     116           0 :   }
     117             : };
     118             : 
     119             : class PrefixComparator {
     120             : public:
     121           0 :   static int Compare(const uint8_t* a, const uint8_t* b) {
     122             :       uint32_t first;
     123           0 :       memcpy(&first, a, sizeof(uint32_t));
     124             : 
     125             :       uint32_t second;
     126           0 :       memcpy(&second, b, sizeof(uint32_t));
     127             : 
     128           0 :       if (first > second) {
     129           0 :           return 1;
     130           0 :       } else if (first == second) {
     131           0 :           return 0;
     132             :       } else {
     133           0 :           return -1;
     134             :       }
     135             :   }
     136             : };
     137             : // Use this for 4-byte hashes
     138             : typedef SafebrowsingHash<PREFIX_SIZE, PrefixComparator> Prefix;
     139             : typedef nsTArray<Prefix> PrefixArray;
     140             : 
     141             : class CompletionComparator {
     142             : public:
     143          15 :   static int Compare(const uint8_t* a, const uint8_t* b) {
     144          15 :     return memcmp(a, b, COMPLETE_SIZE);
     145             :   }
     146             : };
     147             : // Use this for 32-byte hashes
     148             : typedef SafebrowsingHash<COMPLETE_SIZE, CompletionComparator> Completion;
     149             : typedef nsTArray<Completion> CompletionArray;
     150             : 
     151             : struct AddPrefix {
     152             :   // The truncated hash.
     153             :   Prefix prefix;
     154             :   // The chunk number to which it belongs.
     155             :   uint32_t addChunk;
     156             : 
     157           0 :   AddPrefix() : addChunk(0) {}
     158             : 
     159             :   // Returns the chunk number.
     160           0 :   uint32_t Chunk() const { return addChunk; }
     161           0 :   const Prefix &PrefixHash() const { return prefix; }
     162             : 
     163             :   template<class T>
     164           0 :   int Compare(const T& other) const {
     165           0 :     int cmp = prefix.Compare(other.PrefixHash());
     166           0 :     if (cmp != 0) {
     167           0 :       return cmp;
     168             :     }
     169           0 :     return addChunk - other.addChunk;
     170             :   }
     171             : };
     172             : 
     173             : struct AddComplete {
     174             :   Completion complete;
     175             :   uint32_t addChunk;
     176             : 
     177          28 :   AddComplete() : addChunk(0) {}
     178             : 
     179          14 :   uint32_t Chunk() const { return addChunk; }
     180             :   // The 4-byte prefix of the sha256 hash.
     181           0 :   uint32_t ToUint32() const { return complete.ToUint32(); }
     182             :   // The 32-byte sha256 hash.
     183          15 :   const Completion &CompleteHash() const { return complete; }
     184             : 
     185             :   template<class T>
     186           8 :   int Compare(const T& other) const {
     187           8 :     int cmp = complete.Compare(other.CompleteHash());
     188           8 :     if (cmp != 0) {
     189           6 :       return cmp;
     190             :     }
     191           2 :     return addChunk - other.addChunk;
     192             :   }
     193             : 
     194             :   bool operator!=(const AddComplete& aOther) const {
     195             :     if (addChunk != aOther.addChunk) {
     196             :       return true;
     197             :     }
     198             :     return complete != aOther.complete;
     199             :   }
     200             : };
     201             : 
     202             : struct SubPrefix {
     203             :   // The hash to subtract.
     204             :   Prefix prefix;
     205             :   // The chunk number of the add chunk to which the hash belonged.
     206             :   uint32_t addChunk;
     207             :   // The chunk number of this sub chunk.
     208             :   uint32_t subChunk;
     209             : 
     210           0 :   SubPrefix(): addChunk(0), subChunk(0) {}
     211             : 
     212           0 :   uint32_t Chunk() const { return subChunk; }
     213           0 :   uint32_t AddChunk() const { return addChunk; }
     214           0 :   const Prefix &PrefixHash() const { return prefix; }
     215             : 
     216             :   template<class T>
     217             :   // Returns 0 if and only if the chunks are the same in every way.
     218           0 :   int Compare(const T& aOther) const {
     219           0 :     int cmp = prefix.Compare(aOther.PrefixHash());
     220           0 :     if (cmp != 0)
     221           0 :       return cmp;
     222           0 :     if (addChunk != aOther.addChunk)
     223           0 :       return addChunk - aOther.addChunk;
     224           0 :     return subChunk - aOther.subChunk;
     225             :   }
     226             : 
     227             :   template<class T>
     228           0 :   int CompareAlt(const T& aOther) const {
     229             :     Prefix other;
     230           0 :     other.FromUint32(aOther.ToUint32());
     231           0 :     int cmp = prefix.Compare(other);
     232           0 :     if (cmp != 0)
     233           0 :       return cmp;
     234           0 :     return addChunk - aOther.addChunk;
     235             :   }
     236             : };
     237             : 
     238             : struct SubComplete {
     239             :   Completion complete;
     240             :   uint32_t addChunk;
     241             :   uint32_t subChunk;
     242             : 
     243           0 :   SubComplete() : addChunk(0), subChunk(0) {}
     244             : 
     245           0 :   uint32_t Chunk() const { return subChunk; }
     246             :   uint32_t AddChunk() const { return addChunk; }
     247           0 :   const Completion &CompleteHash() const { return complete; }
     248             :   // The 4-byte prefix of the sha256 hash.
     249           0 :   uint32_t ToUint32() const { return complete.ToUint32(); }
     250             : 
     251           0 :   int Compare(const SubComplete& aOther) const {
     252           0 :     int cmp = complete.Compare(aOther.complete);
     253           0 :     if (cmp != 0)
     254           0 :       return cmp;
     255           0 :     if (addChunk != aOther.addChunk)
     256           0 :       return addChunk - aOther.addChunk;
     257           0 :     return subChunk - aOther.subChunk;
     258             :   }
     259             : };
     260             : 
     261             : typedef FallibleTArray<AddPrefix>   AddPrefixArray;
     262             : typedef FallibleTArray<AddComplete> AddCompleteArray;
     263             : typedef FallibleTArray<SubPrefix>   SubPrefixArray;
     264             : typedef FallibleTArray<SubComplete> SubCompleteArray;
     265             : typedef FallibleTArray<Prefix>      MissPrefixArray;
     266             : 
     267             : /**
     268             :  * Compares chunks by their add chunk, then their prefix.
     269             :  */
     270             : template<class T>
     271             : class EntryCompare {
     272             : public:
     273             :   typedef T elem_type;
     274           2 :   static int Compare(const void* e1, const void* e2) {
     275           2 :     const elem_type* a = static_cast<const elem_type*>(e1);
     276           2 :     const elem_type* b = static_cast<const elem_type*>(e2);
     277           2 :     return a->Compare(*b);
     278             :   }
     279             : };
     280             : 
     281             : /**
     282             :  * Sort an array of store entries.  nsTArray::Sort uses Equal/LessThan
     283             :  * to sort, this does a single Compare so it's a bit quicker over the
     284             :  * large sorts we do.
     285             :  */
     286             : template<class T, class Alloc>
     287             : void
     288          48 : EntrySort(nsTArray_Impl<T, Alloc>& aArray)
     289             : {
     290          48 :   qsort(aArray.Elements(), aArray.Length(), sizeof(T),
     291             :         EntryCompare<T>::Compare);
     292          48 : }
     293             : 
     294             : template<class T, class Alloc>
     295             : nsresult
     296         162 : ReadTArray(nsIInputStream* aStream, nsTArray_Impl<T, Alloc>* aArray, uint32_t aNumElements)
     297             : {
     298         162 :   if (!aArray->SetLength(aNumElements, fallible))
     299           0 :     return NS_ERROR_OUT_OF_MEMORY;
     300             : 
     301         162 :   void *buffer = aArray->Elements();
     302          66 :   nsresult rv = NS_ReadInputStreamToBuffer(aStream, &buffer,
     303         162 :                                            (aNumElements * sizeof(T)));
     304         162 :   NS_ENSURE_SUCCESS(rv, rv);
     305         162 :   return NS_OK;
     306             : }
     307             : 
     308             : template<class T, class Alloc>
     309             : nsresult
     310         120 : WriteTArray(nsIOutputStream* aStream, nsTArray_Impl<T, Alloc>& aArray)
     311             : {
     312             :   uint32_t written;
     313         120 :   return aStream->Write(reinterpret_cast<char*>(aArray.Elements()),
     314         120 :                         aArray.Length() * sizeof(T),
     315         360 :                         &written);
     316             : }
     317             : 
     318             : typedef nsClassHashtable<nsUint32HashKey, nsCString> PrefixStringMap;
     319             : 
     320             : typedef nsDataHashtable<nsCStringHashKey, int64_t> TableFreshnessMap;
     321             : 
     322             : typedef nsCStringHashKey FullHashString;
     323             : 
     324             : typedef nsDataHashtable<FullHashString, int64_t> FullHashExpiryCache;
     325             : 
     326           0 : struct CachedFullHashResponse {
     327             :   int64_t negativeCacheExpirySec;
     328             : 
     329             :   // Map contains all matches found in Fullhash response, this field might be empty.
     330             :   FullHashExpiryCache fullHashes;
     331             : 
     332           0 :   CachedFullHashResponse& operator=(const CachedFullHashResponse& aOther) {
     333           0 :     negativeCacheExpirySec = aOther.negativeCacheExpirySec;
     334             : 
     335           0 :     fullHashes.Clear();
     336           0 :     for (auto iter = aOther.fullHashes.ConstIter(); !iter.Done(); iter.Next()) {
     337           0 :       fullHashes.Put(iter.Key(), iter.Data());
     338             :     }
     339             : 
     340           0 :     return *this;
     341             :   }
     342             : 
     343           0 :   bool operator==(const CachedFullHashResponse& aOther) const {
     344           0 :     if (negativeCacheExpirySec != aOther.negativeCacheExpirySec ||
     345           0 :         fullHashes.Count() != aOther.fullHashes.Count()) {
     346           0 :       return false;
     347             :     }
     348           0 :     for (auto iter = fullHashes.ConstIter(); !iter.Done(); iter.Next()) {
     349           0 :       if (iter.Data() != aOther.fullHashes.Get(iter.Key())) {
     350           0 :         return false;
     351             :       }
     352             :     }
     353           0 :     return true;
     354             :   }
     355             : };
     356             : 
     357             : typedef nsClassHashtable<nsUint32HashKey, CachedFullHashResponse> FullHashResponseMap;
     358             : 
     359             : template<class T>
     360             : void
     361           6 : CopyClassHashTable(const T& aSource, T& aDestination)
     362             : {
     363           6 :   for (auto iter = aSource.ConstIter(); !iter.Done(); iter.Next()) {
     364           0 :     auto value = aDestination.LookupOrAdd(iter.Key());
     365           0 :     *value = *(iter.Data());
     366             :   }
     367           6 : }
     368             : 
     369             : } // namespace safebrowsing
     370             : } // namespace mozilla
     371             : 
     372             : #endif // SBEntries_h__

Generated by: LCOV version 1.13