Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/url-classifier/HashStore.h
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifndef HashStore_h__
6
#define HashStore_h__
7
8
#include "Entries.h"
9
#include "ChunkSet.h"
10
11
#include "nsString.h"
12
#include "nsTArray.h"
13
#include "nsIFile.h"
14
#include "nsIFileStreams.h"
15
#include "nsISupports.h"
16
#include "nsCOMPtr.h"
17
#include "nsClassHashtable.h"
18
#include <string>
19
20
namespace mozilla {
21
namespace safebrowsing {
22
23
// The abstract class of TableUpdateV2 and TableUpdateV4. This
24
// is convenient for passing the TableUpdate* around associated
25
// with v2 and v4 instance.
26
class TableUpdate {
27
public:
28
  TableUpdate(const nsACString& aTable)
29
    : mTable(aTable)
30
0
  {
31
0
  }
32
33
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TableUpdate);
34
35
  // To be overriden.
36
  virtual bool Empty() const = 0;
37
38
  // Common interfaces.
39
0
  const nsCString& TableName() const { return mTable; }
40
41
  template<typename T>
42
0
  static T* Cast(TableUpdate* aThat) {
43
0
    return (T::TAG == aThat->Tag() ? reinterpret_cast<T*>(aThat) : nullptr);
44
0
  }
Unexecuted instantiation: mozilla::safebrowsing::TableUpdateV2* mozilla::safebrowsing::TableUpdate::Cast<mozilla::safebrowsing::TableUpdateV2>(mozilla::safebrowsing::TableUpdate*)
Unexecuted instantiation: mozilla::safebrowsing::TableUpdateV4* mozilla::safebrowsing::TableUpdate::Cast<mozilla::safebrowsing::TableUpdateV4>(mozilla::safebrowsing::TableUpdate*)
45
  template<typename T>
46
0
  static const T* Cast(const TableUpdate* aThat) {
47
0
    return (T::TAG == aThat->Tag() ? reinterpret_cast<const T*>(aThat) : nullptr);
48
0
  }
Unexecuted instantiation: mozilla::safebrowsing::TableUpdateV2 const* mozilla::safebrowsing::TableUpdate::Cast<mozilla::safebrowsing::TableUpdateV2>(mozilla::safebrowsing::TableUpdate const*)
Unexecuted instantiation: mozilla::safebrowsing::TableUpdateV4 const* mozilla::safebrowsing::TableUpdate::Cast<mozilla::safebrowsing::TableUpdateV4>(mozilla::safebrowsing::TableUpdate const*)
49
50
protected:
51
0
  virtual ~TableUpdate() {}
52
53
private:
54
  virtual int Tag() const = 0;
55
56
  const nsCString mTable;
57
};
58
59
typedef nsTArray<RefPtr<TableUpdate>> TableUpdateArray;
60
typedef nsTArray<RefPtr<const TableUpdate>> ConstTableUpdateArray;
61
62
// A table update is built from a single update chunk from the server. As the
63
// protocol parser processes each chunk, it constructs a table update with the
64
// new hashes.
65
class TableUpdateV2 : public TableUpdate {
66
public:
67
  explicit TableUpdateV2(const nsACString& aTable)
68
0
    : TableUpdate(aTable) {}
69
70
0
  bool Empty() const override {
71
0
    return mAddChunks.Length() == 0 &&
72
0
      mSubChunks.Length() == 0 &&
73
0
      mAddExpirations.Length() == 0 &&
74
0
      mSubExpirations.Length() == 0 &&
75
0
      mAddPrefixes.Length() == 0 &&
76
0
      mSubPrefixes.Length() == 0 &&
77
0
      mAddCompletes.Length() == 0 &&
78
0
      mSubCompletes.Length() == 0 &&
79
0
      mMissPrefixes.Length() == 0;
80
0
  }
81
82
  // Throughout, uint32_t aChunk refers only to the chunk number. Chunk data is
83
  // stored in the Prefix structures.
84
0
  MOZ_MUST_USE nsresult NewAddChunk(uint32_t aChunk) {
85
0
    return mAddChunks.Set(aChunk);
86
0
  };
87
0
  MOZ_MUST_USE nsresult NewSubChunk(uint32_t aChunk) {
88
0
    return mSubChunks.Set(aChunk);
89
0
  };
90
0
  MOZ_MUST_USE nsresult NewAddExpiration(uint32_t aChunk) {
91
0
    return mAddExpirations.Set(aChunk);
92
0
  };
93
0
  MOZ_MUST_USE nsresult NewSubExpiration(uint32_t aChunk) {
94
0
    return mSubExpirations.Set(aChunk);
95
0
  };
96
  MOZ_MUST_USE nsresult NewAddPrefix(uint32_t aAddChunk, const Prefix& aPrefix);
97
  MOZ_MUST_USE nsresult NewSubPrefix(uint32_t aAddChunk,
98
                                     const Prefix& aPrefix,
99
                                     uint32_t aSubChunk);
100
  MOZ_MUST_USE nsresult NewAddComplete(uint32_t aChunk,
101
                                       const Completion& aCompletion);
102
  MOZ_MUST_USE nsresult NewSubComplete(uint32_t aAddChunk,
103
                                       const Completion& aCompletion,
104
                                       uint32_t aSubChunk);
105
  MOZ_MUST_USE nsresult NewMissPrefix(const Prefix& aPrefix);
106
107
0
  const ChunkSet& AddChunks() const { return mAddChunks; }
108
0
  const ChunkSet& SubChunks() const { return mSubChunks; }
109
110
  // Expirations for chunks.
111
0
  const ChunkSet& AddExpirations() const { return mAddExpirations; }
112
0
  const ChunkSet& SubExpirations() const { return mSubExpirations; }
113
114
  // Hashes associated with this chunk.
115
0
  AddPrefixArray& AddPrefixes() { return mAddPrefixes; }
116
0
  SubPrefixArray& SubPrefixes() { return mSubPrefixes; }
117
0
  const AddCompleteArray& AddCompletes() const { return mAddCompletes; }
118
0
  AddCompleteArray& AddCompletes() { return mAddCompletes; }
119
0
  SubCompleteArray& SubCompletes() { return mSubCompletes; }
120
121
  // Entries that cannot be completed.
122
0
  const MissPrefixArray& MissPrefixes() const { return mMissPrefixes; }
123
124
  // For downcasting.
125
  static const int TAG = 2;
126
127
private:
128
129
  // The list of chunk numbers that we have for each of the type of chunks.
130
  ChunkSet mAddChunks;
131
  ChunkSet mSubChunks;
132
  ChunkSet mAddExpirations;
133
  ChunkSet mSubExpirations;
134
135
  // 4-byte sha256 prefixes.
136
  AddPrefixArray  mAddPrefixes;
137
  SubPrefixArray  mSubPrefixes;
138
139
  // This is only used by gethash so don't add this to Header.
140
  MissPrefixArray mMissPrefixes;
141
142
  // 32-byte hashes.
143
  AddCompleteArray mAddCompletes;
144
  SubCompleteArray mSubCompletes;
145
146
0
  virtual int Tag() const override { return TAG; }
147
};
148
149
// Structure for DBService/HashStore/Classifiers to update.
150
// It would contain the prefixes (both fixed and variable length)
151
// for addition and indices to removal. See Bug 1283009.
152
class TableUpdateV4 : public TableUpdate {
153
public:
154
  typedef nsTArray<int32_t> RemovalIndiceArray;
155
156
public:
157
  explicit TableUpdateV4(const nsACString& aTable)
158
    : TableUpdate(aTable)
159
    , mFullUpdate(false)
160
0
  {
161
0
  }
162
163
  bool Empty() const override
164
0
  {
165
0
    return mPrefixesMap.IsEmpty() &&
166
0
           mRemovalIndiceArray.IsEmpty() &&
167
0
           mFullHashResponseMap.IsEmpty();
168
0
  }
169
170
0
  bool IsFullUpdate() const { return mFullUpdate; }
171
0
  const PrefixStringMap& Prefixes() const { return mPrefixesMap; }
172
0
  const RemovalIndiceArray& RemovalIndices() const { return mRemovalIndiceArray; }
173
0
  const nsACString& ClientState() const { return mClientState; }
174
0
  const nsACString& Checksum() const { return mChecksum; }
175
0
  const FullHashResponseMap& FullHashResponse() const { return mFullHashResponseMap; }
176
177
  // For downcasting.
178
  static const int TAG = 4;
179
180
0
  void SetFullUpdate(bool aIsFullUpdate) { mFullUpdate = aIsFullUpdate; }
181
  void NewPrefixes(int32_t aSize, const nsACString& aPrefixes);
182
0
  void SetNewClientState(const nsACString& aState) { mClientState = aState; }
183
  void NewChecksum(const std::string& aChecksum);
184
185
  nsresult NewRemovalIndices(const uint32_t* aIndices, size_t aNumOfIndices);
186
  nsresult NewFullHashResponse(const Prefix& aPrefix,
187
                               const CachedFullHashResponse& aResponse);
188
189
private:
190
0
  virtual int Tag() const override { return TAG; }
191
192
  bool mFullUpdate;
193
  PrefixStringMap mPrefixesMap;
194
  RemovalIndiceArray mRemovalIndiceArray;
195
  nsCString mClientState;
196
  nsCString mChecksum;
197
198
  // This is used to store response from fullHashes.find.
199
  FullHashResponseMap mFullHashResponseMap;
200
};
201
202
// There is one hash store per table.
203
class HashStore {
204
public:
205
  HashStore(const nsACString& aTableName,
206
            const nsACString& aProvider,
207
            nsIFile* aRootStoreFile);
208
  ~HashStore();
209
210
0
  const nsCString& TableName() const { return mTableName; }
211
212
  nsresult Open();
213
  // Add Prefixes are stored partly in the PrefixSet (contains the
214
  // Prefix data organized for fast lookup/low RAM usage) and partly in the
215
  // HashStore (Add Chunk numbers - only used for updates, slow retrieval).
216
  // AugmentAdds function joins the separate datasets into one complete
217
  // prefixes+chunknumbers dataset.
218
  nsresult AugmentAdds(const nsTArray<uint32_t>& aPrefixes);
219
220
  ChunkSet& AddChunks();
221
  ChunkSet& SubChunks();
222
0
  AddPrefixArray& AddPrefixes() { return mAddPrefixes; }
223
0
  SubPrefixArray& SubPrefixes() { return mSubPrefixes; }
224
  AddCompleteArray& AddCompletes();
225
  SubCompleteArray& SubCompletes();
226
227
  // =======
228
  // Updates
229
  // =======
230
  // Begin the update process.  Reads the store into memory.
231
  nsresult BeginUpdate();
232
233
  // Imports the data from a TableUpdate.
234
  nsresult ApplyUpdate(RefPtr<TableUpdateV2> aUpdate);
235
236
  // Process expired chunks
237
  nsresult Expire();
238
239
  // Rebuild the store, Incorporating all the applied updates.
240
  nsresult Rebuild();
241
242
  // Write the current state of the store to disk.
243
  // If you call between ApplyUpdate() and Rebuild(), you'll
244
  // have a mess on your hands.
245
  nsresult WriteFile();
246
247
  // Wipe out all Completes.
248
  void ClearCompletes();
249
250
private:
251
  nsresult Reset();
252
253
  nsresult ReadHeader();
254
  nsresult SanityCheck() const;
255
  nsresult CalculateChecksum(nsAutoCString& aChecksum, uint32_t aFileSize,
256
                             bool aChecksumPresent);
257
  nsresult CheckChecksum(uint32_t aFileSize);
258
  void UpdateHeader();
259
260
  nsresult ReadCompletions();
261
  nsresult ReadChunkNumbers();
262
  nsresult ReadHashes();
263
264
  nsresult ReadAddPrefixes();
265
  nsresult ReadSubPrefixes();
266
267
  nsresult WriteAddPrefixes(nsIOutputStream* aOut);
268
  nsresult WriteSubPrefixes(nsIOutputStream* aOut);
269
270
  nsresult ProcessSubs();
271
272
  nsresult PrepareForUpdate();
273
274
  bool AlreadyReadChunkNumbers() const;
275
  bool AlreadyReadCompletions() const;
276
277
 // This is used for checking that the database is correct and for figuring out
278
 // the number of chunks, etc. to read from disk on restart.
279
  struct Header {
280
    uint32_t magic;
281
    uint32_t version;
282
    uint32_t numAddChunks;
283
    uint32_t numSubChunks;
284
    uint32_t numAddPrefixes;
285
    uint32_t numSubPrefixes;
286
    uint32_t numAddCompletes;
287
    uint32_t numSubCompletes;
288
  };
289
290
  Header mHeader;
291
292
  // The name of the table (must end in -shavar or -digest256, or evidently
293
  // -simple for unittesting.
294
  const nsCString mTableName;
295
  nsCOMPtr<nsIFile> mStoreDirectory;
296
297
  bool mInUpdate;
298
299
  nsCOMPtr<nsIInputStream> mInputStream;
300
301
  // Chunk numbers, stored as uint32_t arrays.
302
  ChunkSet mAddChunks;
303
  ChunkSet mSubChunks;
304
305
  ChunkSet mAddExpirations;
306
  ChunkSet mSubExpirations;
307
308
  // Chunk data for shavar tables. See Entries.h for format.
309
  AddPrefixArray mAddPrefixes;
310
  SubPrefixArray mSubPrefixes;
311
312
  // See bug 806422 for background. We must be able to distinguish between
313
  // updates from the completion server and updates from the regular server.
314
  AddCompleteArray mAddCompletes;
315
  SubCompleteArray mSubCompletes;
316
317
  uint32_t mFileSize;
318
319
  // For gtest to inspect private members.
320
  friend class PerProviderDirectoryTestUtils;
321
};
322
323
} // namespace safebrowsing
324
} // namespace mozilla
325
326
#endif