• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/safe_browsing/safe_browsing_store.h"
6 #include "chrome/browser/safe_browsing/safe_browsing_store_unittest_helper.h"
7 
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace {
11 
TEST(SafeBrowsingStoreTest,SBAddPrefixLess)12 TEST(SafeBrowsingStoreTest, SBAddPrefixLess) {
13   // chunk_id then prefix.
14   EXPECT_TRUE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(11, 1)));
15   EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(11, 1), SBAddPrefix(10, 1)));
16   EXPECT_TRUE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(10, 2)));
17   EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(10, 2), SBAddPrefix(10, 1)));
18 
19   // Equal is not less.
20   EXPECT_FALSE(SBAddPrefixLess(SBAddPrefix(10, 1), SBAddPrefix(10, 1)));
21 }
22 
TEST(SafeBrowsingStoreTest,SBAddPrefixHashLess)23 TEST(SafeBrowsingStoreTest, SBAddPrefixHashLess) {
24   // The first four bytes of SBFullHash can be read as an int32, which
25   // means that byte-ordering issues can come up.  To test this, |one|
26   // and |two| differ in the prefix, while |one| and |onetwo| have the
27   // same prefix, but differ in the byte after the prefix.
28   SBFullHash one, onetwo, two;
29   memset(&one, 0, sizeof(one));
30   memset(&onetwo, 0, sizeof(onetwo));
31   memset(&two, 0, sizeof(two));
32   one.prefix = 1;
33   one.full_hash[sizeof(int32)] = 1;
34   onetwo.prefix = 1;
35   onetwo.full_hash[sizeof(int32)] = 2;
36   two.prefix = 2;
37 
38   const base::Time now = base::Time::Now();
39 
40   // add_id dominates.
41   EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now, two),
42                                   SBAddFullHash(11, now, one)));
43   EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(11, now, two),
44                                    SBAddFullHash(10, now, one)));
45 
46   // After add_id, prefix.
47   EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now, one),
48                                   SBAddFullHash(10, now, two)));
49   EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now, two),
50                                    SBAddFullHash(10, now, one)));
51 
52   // After prefix, full hash.
53   EXPECT_TRUE(SBAddPrefixHashLess(SBAddFullHash(10, now, one),
54                                   SBAddFullHash(10, now, onetwo)));
55   EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now, onetwo),
56                                    SBAddFullHash(10, now, one)));
57 
58   // Equal is not less-than.
59   EXPECT_FALSE(SBAddPrefixHashLess(SBAddFullHash(10, now, one),
60                                    SBAddFullHash(10, now, one)));
61 }
62 
TEST(SafeBrowsingStoreTest,SBSubPrefixLess)63 TEST(SafeBrowsingStoreTest, SBSubPrefixLess) {
64   // add_id dominates.
65   EXPECT_TRUE(SBAddPrefixLess(SBSubPrefix(12, 10, 2), SBSubPrefix(9, 11, 1)));
66   EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 11, 2), SBSubPrefix(9, 10, 1)));
67 
68   // After add_id, prefix.
69   EXPECT_TRUE(SBAddPrefixLess(SBSubPrefix(12, 10, 1), SBSubPrefix(9, 10, 2)));
70   EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 10, 2), SBSubPrefix(9, 10, 1)));
71 
72   // Equal is not less-than.
73   EXPECT_FALSE(SBAddPrefixLess(SBSubPrefix(12, 10, 1), SBSubPrefix(12, 10, 1)));
74 
75   // chunk_id doesn't matter.
76 }
77 
TEST(SafeBrowsingStoreTest,SBSubFullHashLess)78 TEST(SafeBrowsingStoreTest, SBSubFullHashLess) {
79   SBFullHash one, onetwo, two;
80   memset(&one, 0, sizeof(one));
81   memset(&onetwo, 0, sizeof(onetwo));
82   memset(&two, 0, sizeof(two));
83   one.prefix = 1;
84   one.full_hash[sizeof(int32)] = 1;
85   onetwo.prefix = 1;
86   onetwo.full_hash[sizeof(int32)] = 2;
87   two.prefix = 2;
88 
89   // add_id dominates.
90   EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, two),
91                                   SBSubFullHash(9, 11, one)));
92   EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 11, two),
93                                    SBSubFullHash(9, 10, one)));
94 
95   // After add_id, prefix.
96   EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one),
97                                   SBSubFullHash(9, 10, two)));
98   EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, two),
99                                    SBSubFullHash(9, 10, one)));
100 
101   // After prefix, full_hash.
102   EXPECT_TRUE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one),
103                                   SBSubFullHash(9, 10, onetwo)));
104   EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, onetwo),
105                                    SBSubFullHash(9, 10, one)));
106 
107   // Equal is not less-than.
108   EXPECT_FALSE(SBAddPrefixHashLess(SBSubFullHash(12, 10, one),
109                                    SBSubFullHash(9, 10, one)));
110 }
111 
112 // SBProcessSubs does a lot of iteration, run through empty just to
113 // make sure degenerate cases work.
TEST(SafeBrowsingStoreTest,SBProcessSubsEmpty)114 TEST(SafeBrowsingStoreTest, SBProcessSubsEmpty) {
115   std::vector<SBAddPrefix> add_prefixes;
116   std::vector<SBAddFullHash> add_hashes;
117   std::vector<SBSubPrefix> sub_prefixes;
118   std::vector<SBSubFullHash> sub_hashes;
119 
120   const base::hash_set<int32> no_deletions;
121   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
122                 no_deletions, no_deletions);
123   EXPECT_TRUE(add_prefixes.empty());
124   EXPECT_TRUE(sub_prefixes.empty());
125   EXPECT_TRUE(add_hashes.empty());
126   EXPECT_TRUE(sub_hashes.empty());
127 }
128 
129 // Test that subs knock out adds.
TEST(SafeBrowsingStoreTest,SBProcessSubsKnockout)130 TEST(SafeBrowsingStoreTest, SBProcessSubsKnockout) {
131   const base::Time kNow = base::Time::Now();
132   const SBFullHash kHash1(SBFullHashFromString("one"));
133   const SBFullHash kHash2(SBFullHashFromString("two"));
134   const SBFullHash kHash3(SBFullHashFromString("three"));
135   const int kAddChunk1 = 1;  // Use different chunk numbers just in case.
136   const int kSubChunk1 = 2;
137 
138   // Construct some full hashes which share prefix with another.
139   SBFullHash kHash1mod1 = kHash1;
140   kHash1mod1.full_hash[sizeof(kHash1mod1.full_hash) - 1] ++;
141   SBFullHash kHash1mod2 = kHash1mod1;
142   kHash1mod2.full_hash[sizeof(kHash1mod2.full_hash) - 1] ++;
143   SBFullHash kHash1mod3 = kHash1mod2;
144   kHash1mod3.full_hash[sizeof(kHash1mod3.full_hash) - 1] ++;
145 
146   std::vector<SBAddPrefix> add_prefixes;
147   std::vector<SBAddFullHash> add_hashes;
148   std::vector<SBSubPrefix> sub_prefixes;
149   std::vector<SBSubFullHash> sub_hashes;
150 
151   // An add with prefix and a couple hashes, plus a sub for the prefix
152   // and a couple sub hashes.  The sub should knock all of them out.
153   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash1.prefix));
154   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1));
155   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1mod1));
156   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash1.prefix));
157   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod2));
158   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod3));
159 
160   // An add with no corresponding sub.  Both items should be retained.
161   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash2));
162   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash2.prefix));
163 
164   // A sub with no corresponding add.  Both items should be retained.
165   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash3));
166   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash3.prefix));
167 
168   const base::hash_set<int32> no_deletions;
169   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
170                 no_deletions, no_deletions);
171 
172   EXPECT_EQ(1U, add_prefixes.size());
173   EXPECT_EQ(kAddChunk1, add_prefixes[0].chunk_id);
174   EXPECT_EQ(kHash2.prefix, add_prefixes[0].prefix);
175 
176   EXPECT_EQ(1U, add_hashes.size());
177   EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id);
178   EXPECT_TRUE(SBFullHashEq(kHash2, add_hashes[0].full_hash));
179 
180   EXPECT_EQ(1U, sub_prefixes.size());
181   EXPECT_EQ(kSubChunk1, sub_prefixes[0].chunk_id);
182   EXPECT_EQ(kAddChunk1, sub_prefixes[0].add_chunk_id);
183   EXPECT_EQ(kHash3.prefix, sub_prefixes[0].add_prefix);
184 
185   EXPECT_EQ(1U, sub_hashes.size());
186   EXPECT_EQ(kSubChunk1, sub_hashes[0].chunk_id);
187   EXPECT_EQ(kAddChunk1, sub_hashes[0].add_chunk_id);
188   EXPECT_TRUE(SBFullHashEq(kHash3, sub_hashes[0].full_hash));
189 }
190 
191 // Test chunk deletions, and ordering of deletions WRT subs knocking
192 // out adds.
TEST(SafeBrowsingStoreTest,SBProcessSubsDeleteChunk)193 TEST(SafeBrowsingStoreTest, SBProcessSubsDeleteChunk) {
194   const base::Time kNow = base::Time::Now();
195   const SBFullHash kHash1(SBFullHashFromString("one"));
196   const SBFullHash kHash2(SBFullHashFromString("two"));
197   const SBFullHash kHash3(SBFullHashFromString("three"));
198   const int kAddChunk1 = 1;  // Use different chunk numbers just in case.
199   const int kSubChunk1 = 2;
200 
201   // Construct some full hashes which share prefix with another.
202   SBFullHash kHash1mod1 = kHash1;
203   kHash1mod1.full_hash[sizeof(kHash1mod1.full_hash) - 1] ++;
204   SBFullHash kHash1mod2 = kHash1mod1;
205   kHash1mod2.full_hash[sizeof(kHash1mod2.full_hash) - 1] ++;
206   SBFullHash kHash1mod3 = kHash1mod2;
207   kHash1mod3.full_hash[sizeof(kHash1mod3.full_hash) - 1] ++;
208 
209   std::vector<SBAddPrefix> add_prefixes;
210   std::vector<SBAddFullHash> add_hashes;
211   std::vector<SBSubPrefix> sub_prefixes;
212   std::vector<SBSubFullHash> sub_hashes;
213 
214   // An add with prefix and a couple hashes, plus a sub for the prefix
215   // and a couple sub hashes.  The sub should knock all of them out.
216   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash1.prefix));
217   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1));
218   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash1mod1));
219   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash1.prefix));
220   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod2));
221   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash1mod3));
222 
223   // An add with no corresponding sub.  Both items should be retained.
224   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash2));
225   add_prefixes.push_back(SBAddPrefix(kAddChunk1, kHash2.prefix));
226 
227   // A sub with no corresponding add.  Both items should be retained.
228   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash3));
229   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash3.prefix));
230 
231   const base::hash_set<int32> no_deletions;
232   base::hash_set<int32> add_deletions;
233   add_deletions.insert(kAddChunk1);
234   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
235                 add_deletions, no_deletions);
236 
237   EXPECT_TRUE(add_prefixes.empty());
238   EXPECT_TRUE(add_hashes.empty());
239 
240   EXPECT_EQ(1U, sub_prefixes.size());
241   EXPECT_EQ(kSubChunk1, sub_prefixes[0].chunk_id);
242   EXPECT_EQ(kAddChunk1, sub_prefixes[0].add_chunk_id);
243   EXPECT_EQ(kHash3.prefix, sub_prefixes[0].add_prefix);
244 
245   EXPECT_EQ(1U, sub_hashes.size());
246   EXPECT_EQ(kSubChunk1, sub_hashes[0].chunk_id);
247   EXPECT_EQ(kAddChunk1, sub_hashes[0].add_chunk_id);
248   EXPECT_TRUE(SBFullHashEq(kHash3, sub_hashes[0].full_hash));
249 
250   base::hash_set<int32> sub_deletions;
251   sub_deletions.insert(kSubChunk1);
252   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
253                 no_deletions, sub_deletions);
254 
255   EXPECT_TRUE(add_prefixes.empty());
256   EXPECT_TRUE(add_hashes.empty());
257   EXPECT_TRUE(sub_prefixes.empty());
258   EXPECT_TRUE(sub_hashes.empty());
259 }
260 
TEST(SafeBrowsingStoreTest,Y2K38)261 TEST(SafeBrowsingStoreTest, Y2K38) {
262   const base::Time now = base::Time::Now();
263   const base::Time future = now + base::TimeDelta::FromDays(3*365);
264 
265   // TODO: Fix file format before 2035.
266   EXPECT_GT(static_cast<int32>(future.ToTimeT()), 0)
267     << " (int32)time_t is running out.";
268 }
269 
270 }  // namespace
271