• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "components/zucchini/patch_reader.h"
6 #include "components/zucchini/patch_writer.h"
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <utility>
12 #include <vector>
13 
14 #include "components/zucchini/version_info.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace zucchini {
18 
19 namespace {
20 
21 // Used for initialization of raw test data.
22 using ByteVector = std::vector<uint8_t>;
23 
24 // Helper function that creates an object of type |T| and intializes it from
25 // data in |buffer|. Ensures initialization is successful. |buffer| is passed as
26 // pointer to avoid passing a temporay, which can causes dangling references.
27 template <class T>
TestInitialize(const ByteVector * buffer)28 T TestInitialize(const ByteVector* buffer) {
29   T value;
30   BufferSource buffer_source(buffer->data(), buffer->size());
31   EXPECT_TRUE(value.Initialize(&buffer_source));
32   EXPECT_TRUE(buffer_source.empty());  // Make sure all data has been consumed
33   return value;
34 }
35 
36 // Helper function that creates an object of type |T| and tries to intialize it
37 // from invalid data in |buffer|, expecting the operation to fail. |buffer| is
38 // passed as pointer to avoid passing a temporary, which can causes dangling
39 // references.
40 template <class T>
TestInvalidInitialize(const ByteVector * buffer)41 void TestInvalidInitialize(const ByteVector* buffer) {
42   T value;
43   BufferSource buffer_source(buffer->data(), buffer->size());
44   EXPECT_FALSE(value.Initialize(&buffer_source));
45 }
46 
47 // Helper function that serializes |value| into a buffer. Ensures that
48 // serialization is successful and that the result matches |expected|.
49 template <class T>
TestSerialize(const ByteVector & expected,const T & value)50 void TestSerialize(const ByteVector& expected, const T& value) {
51   size_t size = value.SerializedSize();
52   EXPECT_EQ(expected.size(), size);
53   ByteVector buffer(size);
54   BufferSink buffer_sink(buffer.data(), buffer.size());
55   EXPECT_TRUE(value.SerializeInto(&buffer_sink));
56   EXPECT_EQ(expected, buffer);
57 }
58 
CreatePatchElement()59 ByteVector CreatePatchElement() {
60   return {
61       // PatchElementHeader
62       0x01, 0, 0, 0,       // old_offset
63       0x51, 0, 0, 0,       // old_length
64       0x03, 0, 0, 0,       // new_offset
65       0x13, 0, 0, 0,       // new_length
66       'P', 'x', '8', '6',  // exe_type = EXE_TYPE_WIN32_X86
67       0x01, 0x00,          // element version
68       // EquivalenceSource
69       1, 0, 0, 0,  // src_skip size
70       0x10,        // src_skip content
71       1, 0, 0, 0,  // dst_skip size
72       0x00,        // dst_skip content
73       1, 0, 0, 0,  // copy_count size
74       0x12,        // copy_count content
75       // ExtraDataSource
76       1, 0, 0, 0,  // extra_data size
77       0x13,        // extra_data content
78       // RawDeltaSource
79       1, 0, 0, 0,  // raw_delta_skip size
80       0x14,        // raw_delta_skip content
81       1, 0, 0, 0,  // raw_delta_diff size
82       0x15,        // raw_delta_diff content
83       // ReferenceDeltaSource
84       1, 0, 0, 0,  // reference_delta size
85       0x16,        // reference_delta content
86       // PatchElementReader
87       2, 0, 0, 0,  // pool count
88       0,           // pool_tag
89       1, 0, 0, 0,  // extra_targets size
90       0x17,        // extra_targets content
91       2,           // pool_tag
92       1, 0, 0, 0,  // extra_targets size
93       0x18,        // extra_targets content
94   };
95 }
96 
CreateElementMatch()97 ByteVector CreateElementMatch() {
98   return {
99       // PatchElementHeader
100       0x01, 0,    0,   0,    // old_offset
101       0x02, 0,    0,   0,    // old_length
102       0x03, 0,    0,   0,    // new_offset
103       0x04, 0,    0,   0,    // new_length
104       'D',  'E',  'X', ' ',  // exe_type = kExeTypeDex
105       0x01, 0x00,            // element version
106   };
107 }
108 
109 // Helper to mutate test |data| (e.g., from CreatePatchElement()) at |idx| from
110 // |from_val| (as sanity check) to |to_val|.
ModifyByte(size_t idx,uint8_t from_val,uint8_t to_val,std::vector<uint8_t> * data)111 void ModifyByte(size_t idx,
112                 uint8_t from_val,
113                 uint8_t to_val,
114                 std::vector<uint8_t>* data) {
115   ASSERT_EQ(from_val, (*data)[idx]);
116   (*data)[idx] = to_val;
117 }
118 
119 }  // namespace
120 
operator ==(const ByteVector & a,ConstBufferView b)121 bool operator==(const ByteVector& a, ConstBufferView b) {
122   return a == ByteVector(b.begin(), b.end());
123 }
124 
TEST(PatchTest,ParseSerializeElementMatch)125 TEST(PatchTest, ParseSerializeElementMatch) {
126   ByteVector data = CreateElementMatch();
127   BufferSource buffer_source(data.data(), data.size());
128   ElementMatch element_match = {};
129   EXPECT_TRUE(patch::ParseElementMatch(&buffer_source, &element_match));
130   EXPECT_EQ(kExeTypeDex, element_match.exe_type());
131   EXPECT_EQ(kExeTypeDex, element_match.old_element.exe_type);
132   EXPECT_EQ(kExeTypeDex, element_match.new_element.exe_type);
133   EXPECT_EQ(0x1U, element_match.old_element.offset);
134   EXPECT_EQ(0x2U, element_match.old_element.size);
135   EXPECT_EQ(0x3U, element_match.new_element.offset);
136   EXPECT_EQ(0x4U, element_match.new_element.size);
137 
138   size_t size = patch::SerializedElementMatchSize(element_match);
139   EXPECT_EQ(data.size(), size);
140   ByteVector buffer(size);
141   BufferSink buffer_sink(buffer.data(), buffer.size());
142   EXPECT_TRUE(patch::SerializeElementMatch(element_match, &buffer_sink));
143   EXPECT_EQ(data, buffer);
144 }
145 
TEST(PatchTest,ParseElementMatchTooSmall)146 TEST(PatchTest, ParseElementMatchTooSmall) {
147   ByteVector data = {4};
148   BufferSource buffer_source(data.data(), data.size());
149   ElementMatch element_match = {};
150   EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
151 }
152 
TEST(PatchTest,ParseElementMatchNoLength)153 TEST(PatchTest, ParseElementMatchNoLength) {
154   // Set old_length to 0 to trigger an error.
155   {
156     ByteVector data = CreateElementMatch();
157     // old_length := 0.
158     ModifyByte(offsetof(PatchElementHeader, old_length), 0x02, 0x00, &data);
159     BufferSource buffer_source(data.data(), data.size());
160     ElementMatch element_match = {};
161     EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
162   }
163   // Set new_length to 0 to trigger an error.
164   {
165     ByteVector data = CreateElementMatch();
166     // new_length := 0.
167     ModifyByte(offsetof(PatchElementHeader, new_length), 0x04, 0x00, &data);
168     BufferSource buffer_source(data.data(), data.size());
169     ElementMatch element_match = {};
170     EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
171   }
172   // Set both new_length and old_length to 0 to trigger an error.
173   {
174     ByteVector data = CreateElementMatch();
175     // old_length := 0.
176     ModifyByte(offsetof(PatchElementHeader, old_length), 0x02, 0x00, &data);
177     // new_length := 0.
178     ModifyByte(offsetof(PatchElementHeader, new_length), 0x04, 0x00, &data);
179     BufferSource buffer_source(data.data(), data.size());
180     ElementMatch element_match = {};
181     EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match));
182   }
183 }
184 
TEST(PatchTest,ParseSerializeElementMatchExeMismatch)185 TEST(PatchTest, ParseSerializeElementMatchExeMismatch) {
186   ByteVector buffer(28);
187   BufferSink buffer_sink(buffer.data(), buffer.size());
188   EXPECT_FALSE(patch::SerializeElementMatch(
189       ElementMatch{{{1, 2}, kExeTypeNoOp}, {{3, 4}, kExeTypeWin32X86}},
190       &buffer_sink));
191 }
192 
TEST(PatchTest,SerializeElementMatchTooSmall)193 TEST(PatchTest, SerializeElementMatchTooSmall) {
194   ByteVector buffer(4);
195   BufferSink buffer_sink(buffer.data(), buffer.size());
196   EXPECT_FALSE(patch::SerializeElementMatch(
197       ElementMatch{{{1, 2}, kExeTypeDex}, {{3, 4}, kExeTypeDex}},
198       &buffer_sink));
199 }
200 
TEST(PatchTest,ParseSerializeBuffer)201 TEST(PatchTest, ParseSerializeBuffer) {
202   auto TestSerialize = [](const ByteVector& expected, const ByteVector& value) {
203     size_t size = patch::SerializedBufferSize(value);
204     EXPECT_EQ(expected.size(), size);
205     ByteVector buffer(size);
206     BufferSink buffer_sink(buffer.data(), buffer.size());
207     EXPECT_TRUE(patch::SerializeBuffer(value, &buffer_sink));
208     EXPECT_EQ(expected, buffer);
209   };
210 
211   // |data| is passed as pointer to avoid passing a temporay, which can causes
212   // dangling references.
213   auto TestParse = [](const ByteVector* data) {
214     BufferSource value;
215     BufferSource buffer_source(data->data(), data->size());
216     EXPECT_TRUE(patch::ParseBuffer(&buffer_source, &value));
217     // Make sure all data has been consumed.
218     EXPECT_TRUE(buffer_source.empty());
219     return value;
220   };
221 
222   ByteVector data = {
223       0, 0, 0, 0,  // size
224   };
225   BufferSource buffer = TestParse(&data);
226   EXPECT_TRUE(buffer.empty());
227   TestSerialize(data, ByteVector({}));
228 
229   data = {
230       3, 0, 0, 0,  // size
231       1, 2, 3      // content
232   };
233   buffer = TestParse(&data);
234   EXPECT_EQ(3U, buffer.size());
235   EXPECT_EQ(ByteVector({1, 2, 3}), ByteVector(buffer.begin(), buffer.end()));
236   TestSerialize(data, ByteVector({1, 2, 3}));
237 
238   // Ill-formed input.
239   data = {
240       3, 0, 0, 0,  // size
241       1, 2         // insufficient content
242   };
243   BufferSource value;
244   BufferSource buffer_source(data.data(), data.size());
245   EXPECT_FALSE(patch::ParseBuffer(&buffer_source, &value));
246   EXPECT_TRUE(value.empty());
247 }
248 
TEST(PatchTest,SerializeBufferTooSmall)249 TEST(PatchTest, SerializeBufferTooSmall) {
250   ByteVector buffer(3);
251   BufferSink buffer_sink(buffer.data(), buffer.size());
252   EXPECT_FALSE(patch::SerializeBuffer(ByteVector(), &buffer_sink));
253 }
254 
TEST(EquivalenceSinkSourceTest,Empty)255 TEST(EquivalenceSinkSourceTest, Empty) {
256   ByteVector data = {
257       // EquivalenceSource
258       0, 0, 0, 0,  // src_skip size
259       0, 0, 0, 0,  // dst_skip size
260       0, 0, 0, 0,  // copy_count size
261   };
262   EquivalenceSource equivalence_source =
263       TestInitialize<EquivalenceSource>(&data);
264 
265   EXPECT_FALSE(equivalence_source.GetNext());
266   EXPECT_TRUE(equivalence_source.Done());
267 
268   TestSerialize(data, EquivalenceSink());
269 }
270 
TEST(EquivalenceSourceSinkTest,Normal)271 TEST(EquivalenceSourceSinkTest, Normal) {
272   ByteVector data = {
273       // EquivalenceSource
274       2, 0, 0, 0,  // src_skip size
275       6, 7,        // src_skip content
276       2, 0, 0, 0,  // dst_skip size
277       7, 1,        // dst_skip content
278       2, 0, 0, 0,  // copy_count size
279       2, 1         // copy_count content
280   };
281   EquivalenceSource equivalence_source =
282       TestInitialize<EquivalenceSource>(&data);
283   auto equivalence = equivalence_source.GetNext();
284   EXPECT_FALSE(equivalence_source.Done());
285   EXPECT_TRUE(equivalence.has_value());
286   EXPECT_EQ(offset_t(3), equivalence->src_offset);
287   EXPECT_EQ(offset_t(7), equivalence->dst_offset);
288   EXPECT_EQ(offset_t(2), equivalence->length);
289 
290   equivalence = equivalence_source.GetNext();
291   EXPECT_TRUE(equivalence_source.Done());
292   EXPECT_TRUE(equivalence.has_value());
293   EXPECT_EQ(offset_t(1), equivalence->src_offset);
294   EXPECT_EQ(offset_t(10), equivalence->dst_offset);
295   EXPECT_EQ(offset_t(1), equivalence->length);
296 
297   equivalence = equivalence_source.GetNext();
298   EXPECT_FALSE(equivalence.has_value());
299 
300   EquivalenceSink equivalence_sink;
301   equivalence_sink.PutNext(Equivalence{3, 7, 2});
302   equivalence_sink.PutNext(Equivalence{1, 10, 1});
303   TestSerialize(data, equivalence_sink);
304 }
305 
TEST(ExtraDataSourceSinkTest,Empty)306 TEST(ExtraDataSourceSinkTest, Empty) {
307   ByteVector data = {
308       // ExtraDataSource
309       0, 0, 0, 0,  // extra_data size
310   };
311   ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data);
312 
313   EXPECT_FALSE(extra_data_source.GetNext(2));
314   EXPECT_TRUE(extra_data_source.Done());
315 
316   TestSerialize(data, ExtraDataSink());
317 }
318 
TEST(ExtraDataSourceSinkTest,Normal)319 TEST(ExtraDataSourceSinkTest, Normal) {
320   ByteVector data = {
321       // ExtraDataSource
322       5, 0, 0, 0,     // extra_data size
323       1, 2, 3, 4, 5,  // extra_data content
324   };
325   ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data);
326   EXPECT_FALSE(extra_data_source.Done());
327 
328   auto extra_data = extra_data_source.GetNext(3);
329   EXPECT_FALSE(extra_data_source.Done());
330   EXPECT_TRUE(extra_data.has_value());
331   EXPECT_EQ(size_t(3), extra_data->size());
332   EXPECT_EQ(ByteVector({1, 2, 3}),
333             ByteVector(extra_data->begin(), extra_data->end()));
334 
335   extra_data = extra_data_source.GetNext(2);
336   EXPECT_TRUE(extra_data_source.Done());
337   EXPECT_TRUE(extra_data.has_value());
338   EXPECT_EQ(ByteVector({4, 5}),
339             ByteVector(extra_data->begin(), extra_data->end()));
340 
341   extra_data = extra_data_source.GetNext(2);
342   EXPECT_FALSE(extra_data.has_value());
343 
344   ExtraDataSink extra_data_sink;
345 
346   ByteVector content = {1, 2, 3};
347   extra_data_sink.PutNext({content.data(), content.size()});
348   content = {4, 5};
349   extra_data_sink.PutNext({content.data(), content.size()});
350   TestSerialize(data, extra_data_sink);
351 }
352 
TEST(RawDeltaSourceSinkTest,Empty)353 TEST(RawDeltaSourceSinkTest, Empty) {
354   ByteVector data = {
355       // RawDeltaSource
356       0, 0, 0, 0,  // raw_delta_skip size
357       0, 0, 0, 0,  // raw_delta_diff size
358   };
359   RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
360 
361   EXPECT_FALSE(raw_delta_source.GetNext());
362   EXPECT_TRUE(raw_delta_source.Done());
363 
364   TestSerialize(data, RawDeltaSink());
365 }
366 
TEST(RawDeltaSinkSourceSinkTest,Normal)367 TEST(RawDeltaSinkSourceSinkTest, Normal) {
368   ByteVector data = {
369       // RawDeltaSource
370       3,  0,  0,   0,  // raw_delta_skip size
371       1,  3,  0,       // raw_delta_skip content
372       3,  0,  0,   0,  // raw_delta_diff size
373       42, 24, 235,     // raw_delta_diff content
374   };
375   RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
376   EXPECT_FALSE(raw_delta_source.Done());
377 
378   auto raw_delta = raw_delta_source.GetNext();
379   EXPECT_FALSE(raw_delta_source.Done());
380   EXPECT_TRUE(raw_delta.has_value());
381   EXPECT_EQ(1U, raw_delta->copy_offset);
382   EXPECT_EQ(42, raw_delta->diff);
383 
384   raw_delta = raw_delta_source.GetNext();
385   EXPECT_FALSE(raw_delta_source.Done());
386   EXPECT_TRUE(raw_delta.has_value());
387   EXPECT_EQ(5U, raw_delta->copy_offset);
388   EXPECT_EQ(24, raw_delta->diff);
389 
390   raw_delta = raw_delta_source.GetNext();
391   EXPECT_TRUE(raw_delta_source.Done());
392   EXPECT_TRUE(raw_delta.has_value());
393   EXPECT_EQ(6U, raw_delta->copy_offset);
394   EXPECT_EQ(-21, raw_delta->diff);
395 
396   EXPECT_FALSE(raw_delta_source.GetNext());
397   EXPECT_TRUE(raw_delta_source.Done());
398 
399   RawDeltaSink raw_delta_sink;
400   raw_delta_sink.PutNext({1, 42});
401   raw_delta_sink.PutNext({5, 24});
402   raw_delta_sink.PutNext({6, -21});
403   TestSerialize(data, raw_delta_sink);
404 }
405 
TEST(RawDeltaSourceSinkTest,InvalidContent)406 TEST(RawDeltaSourceSinkTest, InvalidContent) {
407   ByteVector data = {
408       // RawDeltaSource
409       2, 0, 0, 0,  // raw_delta_skip size
410       1, 3,        // raw_delta_skip content
411       2, 0, 0, 0,  // raw_delta_diff size
412       0, 4,        // raw_delta_diff content
413   };
414   RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data);
415   EXPECT_FALSE(raw_delta_source.GetNext());
416   EXPECT_FALSE(raw_delta_source.Done());
417 }
418 
TEST(ReferenceDeltaSourceSinkTest,Empty)419 TEST(ReferenceDeltaSourceSinkTest, Empty) {
420   ByteVector data = {
421       // ReferenceDeltaSource
422       0, 0, 0, 0,  // reference_delta size
423   };
424   ReferenceDeltaSource reference_delta_source =
425       TestInitialize<ReferenceDeltaSource>(&data);
426 
427   EXPECT_FALSE(reference_delta_source.GetNext());
428   EXPECT_TRUE(reference_delta_source.Done());
429 
430   TestSerialize(data, ReferenceDeltaSink());
431 }
432 
TEST(ReferenceDeltaSourceSinkTest,Normal)433 TEST(ReferenceDeltaSourceSinkTest, Normal) {
434   ByteVector data = {
435       // ReferenceDeltaSource
436       2,  0,  0, 0,  // reference_delta size
437       84, 47,        // reference_delta content
438   };
439   ReferenceDeltaSource reference_delta_source =
440       TestInitialize<ReferenceDeltaSource>(&data);
441   EXPECT_FALSE(reference_delta_source.Done());
442 
443   auto delta = reference_delta_source.GetNext();
444   EXPECT_FALSE(reference_delta_source.Done());
445   EXPECT_TRUE(delta.has_value());
446   EXPECT_EQ(42, *delta);
447 
448   delta = reference_delta_source.GetNext();
449   EXPECT_TRUE(reference_delta_source.Done());
450   EXPECT_TRUE(delta.has_value());
451   EXPECT_EQ(-24, *delta);
452 
453   EXPECT_FALSE(reference_delta_source.GetNext());
454   EXPECT_TRUE(reference_delta_source.Done());
455 
456   ReferenceDeltaSink reference_delta;
457   reference_delta.PutNext(42);
458   reference_delta.PutNext(-24);
459   TestSerialize(data, reference_delta);
460 }
461 
TEST(TargetSourceSinkTest,Empty)462 TEST(TargetSourceSinkTest, Empty) {
463   ByteVector data = {
464       // TargetSource
465       0, 0, 0, 0,  // extra_targets size
466   };
467   TargetSource target_source = TestInitialize<TargetSource>(&data);
468 
469   EXPECT_FALSE(target_source.GetNext());
470   EXPECT_TRUE(target_source.Done());
471 
472   TestSerialize(data, TargetSink());
473 }
474 
TEST(TargetSourceSinkTest,Normal)475 TEST(TargetSourceSinkTest, Normal) {
476   ByteVector data = {
477       // TargetSource
478       2, 0, 0, 0,  // extra_targets size
479       3, 1,        // extra_targets content
480   };
481   TargetSource target_source = TestInitialize<TargetSource>(&data);
482   EXPECT_FALSE(target_source.Done());
483 
484   auto target = target_source.GetNext();
485   EXPECT_FALSE(target_source.Done());
486   EXPECT_TRUE(target.has_value());
487   EXPECT_EQ(3U, *target);
488 
489   target = target_source.GetNext();
490   EXPECT_TRUE(target_source.Done());
491   EXPECT_TRUE(target.has_value());
492   EXPECT_EQ(5U, *target);
493 
494   EXPECT_FALSE(target_source.GetNext());
495   EXPECT_TRUE(target_source.Done());
496 
497   TargetSink target_sink;
498   target_sink.PutNext(3);
499   target_sink.PutNext(5);
500   TestSerialize(data, target_sink);
501 }
502 
TEST(PatchElementTest,Normal)503 TEST(PatchElementTest, Normal) {
504   ByteVector data = CreatePatchElement();
505 
506   PatchElementReader patch_element_reader =
507       TestInitialize<PatchElementReader>(&data);
508 
509   ElementMatch element_match = patch_element_reader.element_match();
510   EXPECT_EQ(kExeTypeWin32X86, element_match.exe_type());
511   EXPECT_EQ(kExeTypeWin32X86, element_match.old_element.exe_type);
512   EXPECT_EQ(kExeTypeWin32X86, element_match.new_element.exe_type);
513   EXPECT_EQ(0x1U, element_match.old_element.offset);
514   EXPECT_EQ(0x51U, element_match.old_element.size);
515   EXPECT_EQ(0x3U, element_match.new_element.offset);
516   EXPECT_EQ(0x13U, element_match.new_element.size);
517 
518   EquivalenceSource equivalence_source =
519       patch_element_reader.GetEquivalenceSource();
520   EXPECT_EQ(ByteVector({0x10}), equivalence_source.src_skip());
521   EXPECT_EQ(ByteVector({0x00}), equivalence_source.dst_skip());
522   EXPECT_EQ(ByteVector({0x12}), equivalence_source.copy_count());
523 
524   ExtraDataSource extra_data_source = patch_element_reader.GetExtraDataSource();
525   EXPECT_EQ(ByteVector({0x13}), extra_data_source.extra_data());
526 
527   RawDeltaSource raw_delta_source = patch_element_reader.GetRawDeltaSource();
528   EXPECT_EQ(ByteVector({0x14}), raw_delta_source.raw_delta_skip());
529   EXPECT_EQ(ByteVector({0x15}), raw_delta_source.raw_delta_diff());
530 
531   ReferenceDeltaSource reference_delta_source =
532       patch_element_reader.GetReferenceDeltaSource();
533   EXPECT_EQ(ByteVector({0x16}), reference_delta_source.reference_delta());
534 
535   TargetSource target_source1 =
536       patch_element_reader.GetExtraTargetSource(PoolTag(0));
537   EXPECT_EQ(ByteVector({0x17}), target_source1.extra_targets());
538   TargetSource target_source2 =
539       patch_element_reader.GetExtraTargetSource(PoolTag(1));
540   EXPECT_EQ(ByteVector({}), target_source2.extra_targets());
541   TargetSource target_source3 =
542       patch_element_reader.GetExtraTargetSource(PoolTag(2));
543   EXPECT_EQ(ByteVector({0x18}), target_source3.extra_targets());
544 
545   PatchElementWriter patch_element_writer(element_match);
546 
547   patch_element_writer.SetEquivalenceSink(
548       EquivalenceSink({0x10}, {0x00}, {0x12}));
549   patch_element_writer.SetExtraDataSink(ExtraDataSink({0x13}));
550   patch_element_writer.SetRawDeltaSink(RawDeltaSink({0x14}, {0x15}));
551   patch_element_writer.SetReferenceDeltaSink(ReferenceDeltaSink({0x16}));
552   patch_element_writer.SetTargetSink(PoolTag(0), TargetSink({0x17}));
553   patch_element_writer.SetTargetSink(PoolTag(2), TargetSink({0x18}));
554   TestSerialize(data, patch_element_writer);
555 }
556 
TEST(PatchElementTest,BadEquivalence)557 TEST(PatchElementTest, BadEquivalence) {
558   // If the "old" element is too small then the test should fail.
559   {
560     ByteVector data = CreatePatchElement();
561     // old_length := 0x4 (too small).
562     ModifyByte(offsetof(PatchElementHeader, old_length), 0x51, 0x04, &data);
563     TestInvalidInitialize<PatchElementReader>(&data);
564   }
565 
566   // If the "new" element is too small then the test should fail.
567   {
568     ByteVector data = CreatePatchElement();
569     // new_length := 0x5 (too small).
570     ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x05, &data);
571     TestInvalidInitialize<PatchElementReader>(&data);
572   }
573 }
574 
TEST(PatchElementTest,WrongExtraData)575 TEST(PatchElementTest, WrongExtraData) {
576   // Make "new" too large so insufficient extra data exists to cover the image.
577   {
578     ByteVector data = CreatePatchElement();
579     // new_length := 0x14 (too large).
580     ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x14, &data);
581     TestInvalidInitialize<PatchElementReader>(&data);
582   }
583   // Make "new" too small so there is too much extra data.
584   {
585     ByteVector data = CreatePatchElement();
586     // new_length := 0x12 (too small).
587     ModifyByte(offsetof(PatchElementHeader, new_length), 0x13, 0x12, &data);
588     TestInvalidInitialize<PatchElementReader>(&data);
589   }
590 }
591 
TEST(PatchElementTest,WrongVersion)592 TEST(PatchElementTest, WrongVersion) {
593   // Bump element version to 2.
594   {
595     ByteVector data = CreatePatchElement();
596     ModifyByte(offsetof(PatchElementHeader, version), 0x01, 0x02, &data);
597     TestInvalidInitialize<PatchElementReader>(&data);
598   }
599   // Bump element version to 0.
600   {
601     ByteVector data = CreatePatchElement();
602     ModifyByte(offsetof(PatchElementHeader, version), 0x01, 0x00, &data);
603     TestInvalidInitialize<PatchElementReader>(&data);
604   }
605 }
606 
TEST(EnsemblePatchTest,RawPatch)607 TEST(EnsemblePatchTest, RawPatch) {
608   ByteVector data = {
609       // PatchHeader
610       0x5A, 0x75, 0x63, 0x63,  // magic
611       0x01, 0x00, 0x00, 0x00,  // major/minor version
612       0x10, 0x32, 0x54, 0x76,  // old_size
613       0x00, 0x11, 0x22, 0x33,  // old_crc
614       0x01, 0, 0, 0,           // new_size
615       0x44, 0x55, 0x66, 0x77,  // new_crc
616 
617       1, 0, 0, 0,  // number of element
618 
619       // PatchElementHeader
620       0x01, 0, 0, 0,       // old_offset
621       0x02, 0, 0, 0,       // old_length
622       0x00, 0, 0, 0,       // new_offset
623       0x01, 0, 0, 0,       // new_length
624       'P', 'x', '8', '6',  // exe_type = EXE_TYPE_WIN32_X8
625       0x01, 0x00,          // element version
626       // EquivalenceSource
627       0, 0, 0, 0,  // src_skip size
628       0, 0, 0, 0,  // dst_skip size
629       0, 0, 0, 0,  // copy_count size
630       // ExtraDataSource
631       0x01, 0, 0, 0,  // extra_data size
632       0x04,           // extra_data content
633       // RawDeltaSource
634       0, 0, 0, 0,  // raw_delta_skip size
635       0, 0, 0, 0,  // raw_delta_diff size
636       // ReferenceDeltaSource
637       0, 0, 0, 0,  // reference_delta size
638       // PatchElementReader
639       0, 0, 0, 0,  // pool count
640   };
641 
642   EnsemblePatchReader ensemble_patch_reader =
643       TestInitialize<EnsemblePatchReader>(&data);
644 
645   PatchHeader header = ensemble_patch_reader.header();
646   EXPECT_EQ(PatchHeader::kMagic, header.magic);
647   EXPECT_EQ(kMajorVersion, header.major_version);
648   EXPECT_EQ(kMinorVersion, header.minor_version);
649   EXPECT_EQ(0x76543210U, header.old_size);
650   EXPECT_EQ(0x33221100U, header.old_crc);
651   EXPECT_EQ(0x01U, header.new_size);
652   EXPECT_EQ(0x77665544U, header.new_crc);
653 
654   const std::vector<PatchElementReader>& elements =
655       ensemble_patch_reader.elements();
656   EXPECT_EQ(size_t(1), elements.size());
657 
658   EnsemblePatchWriter ensemble_patch_writer(header);
659   PatchElementWriter patch_element_writer(elements[0].element_match());
660   patch_element_writer.SetEquivalenceSink({});
661   patch_element_writer.SetExtraDataSink(ExtraDataSink({0x04}));
662   patch_element_writer.SetRawDeltaSink({});
663   patch_element_writer.SetReferenceDeltaSink({});
664   ensemble_patch_writer.AddElement(std::move(patch_element_writer));
665 
666   TestSerialize(data, ensemble_patch_writer);
667 }
668 
TEST(EnsemblePatchTest,CheckFile)669 TEST(EnsemblePatchTest, CheckFile) {
670   ByteVector data = {
671       // PatchHeader
672       0x5A, 0x75, 0x63, 0x63,  // magic
673       0x01, 0x00, 0x00, 0x00,  // major/minor version
674       0x05, 0x00, 0x00, 0x00,  // old_size
675       0xDF, 0x13, 0xE4, 0x10,  // old_crc
676       0x03, 0x00, 0x00, 0x00,  // new_size
677       0xDC, 0xF7, 0x00, 0x40,  // new_crc
678 
679       1, 0, 0, 0,  // number of element
680 
681       // PatchElementHeader
682       0x01, 0, 0, 0,       // old_offset
683       0x02, 0, 0, 0,       // old_length
684       0x00, 0, 0, 0,       // new_offset
685       0x03, 0, 0, 0,       // new_length
686       'P', 'x', '8', '6',  // exe_type = EXE_TYPE_WIN32_X86
687       0x01, 0x00,          // element version
688       // EquivalenceSource
689       0, 0, 0, 0,  // src_skip size
690       0, 0, 0, 0,  // dst_skip size
691       0, 0, 0, 0,  // copy_count size
692       // ExtraDataSource
693       0x03, 0, 0, 0,  // extra_data size
694       'A', 'B', 'C',  // extra_data content
695       // RawDeltaSource
696       0, 0, 0, 0,  // raw_delta_skip size
697       0, 0, 0, 0,  // raw_delta_diff size
698       // ReferenceDeltaSource
699       0, 0, 0, 0,  // reference_delta size
700       // PatchElementReader
701       0, 0, 0, 0,  // pool count
702   };
703 
704   EnsemblePatchReader ensemble_patch_reader =
705       TestInitialize<EnsemblePatchReader>(&data);
706 
707   ByteVector old_file = {0x10, 0x32, 0x54, 0x76, 0x98};
708   ByteVector new_file = {0xBA, 0xDC, 0xFE};
709 
710   ConstBufferView old_image(old_file.data(), old_file.size());
711   ConstBufferView new_image(new_file.data(), new_file.size());
712 
713   EXPECT_TRUE(ensemble_patch_reader.CheckOldFile(old_image));
714   EXPECT_TRUE(ensemble_patch_reader.CheckNewFile(new_image));
715   EXPECT_FALSE(ensemble_patch_reader.CheckOldFile(new_image));
716   EXPECT_FALSE(ensemble_patch_reader.CheckNewFile(old_image));
717 }
718 
TEST(EnsemblePatchTest,InvalidMagic)719 TEST(EnsemblePatchTest, InvalidMagic) {
720   ByteVector data = {
721       // PatchHeader
722       0x42, 0x42, 0x42, 0x42,  // magic
723       0x01, 0x00, 0x00, 0x00,  // major/minor version
724       0x10, 0x32, 0x54, 0x76,  // old_size
725       0x00, 0x11, 0x22, 0x33,  // old_crc
726       0x03, 0x00, 0x00, 0x00,  // new_size
727       0x44, 0x55, 0x66, 0x77,  // new_crc
728 
729       1, 0, 0, 0,  // number of element
730 
731       // PatchElementHeader
732       0x01, 0, 0, 0,       // old_offset
733       0x02, 0, 0, 0,       // old_length
734       0x00, 0, 0, 0,       // new_offset
735       0x03, 0, 0, 0,       // new_length
736       'P', 'x', '8', '6',  // exe_type = EXE_TYPE_WIN32_X86
737       0x01, 0x00,          // element version
738       // EquivalenceSource
739       0, 0, 0, 0,  // src_skip size
740       0, 0, 0, 0,  // dst_skip size
741       0, 0, 0, 0,  // copy_count size
742       // ExtraDataSource
743       0, 0, 0, 0,  // extra_data size
744       // RawDeltaSource
745       0, 0, 0, 0,  // raw_delta_skip size
746       0, 0, 0, 0,  // raw_delta_diff size
747       // ReferenceDeltaSource
748       0, 0, 0, 0,  // reference_delta size
749       // PatchElementReader
750       0, 0, 0, 0,  // pool count
751   };
752 
753   TestInvalidInitialize<EnsemblePatchReader>(&data);
754 }
755 
TEST(EnsemblePatchTest,InvalidVersion)756 TEST(EnsemblePatchTest, InvalidVersion) {
757   ByteVector data = {
758       // PatchHeader
759       0x5A, 0x75, 0x63, 0x63,  // magic
760       0x02, 0x01, 0x00, 0x00,  // major/minor version
761       0x10, 0x32, 0x54, 0x76,  // old_size
762       0x00, 0x11, 0x22, 0x33,  // old_crc
763       0x03, 0x00, 0x00, 0x00,  // new_size
764       0x44, 0x55, 0x66, 0x77,  // new_crc
765 
766       1, 0, 0, 0,  // number of element
767 
768       // PatchElementHeader
769       0x01, 0, 0, 0,       // old_offset
770       0x02, 0, 0, 0,       // old_length
771       0x00, 0, 0, 0,       // new_offset
772       0x03, 0, 0, 0,       // new_length
773       'P', 'x', '8', '6',  // exe_type = EXE_TYPE_WIN32_X86
774       0x01, 0x00,          // element version
775       // EquivalenceSource
776       0, 0, 0, 0,  // src_skip size
777       0, 0, 0, 0,  // dst_skip size
778       0, 0, 0, 0,  // copy_count size
779       // ExtraDataSource
780       0, 0, 0, 0,  // extra_data size
781       // RawDeltaSource
782       0, 0, 0, 0,  // raw_delta_skip size
783       0, 0, 0, 0,  // raw_delta_diff size
784       // ReferenceDeltaSource
785       0, 0, 0, 0,  // reference_delta size
786       // PatchElementReader
787       0, 0, 0, 0,  // pool count
788   };
789 
790   TestInvalidInitialize<EnsemblePatchReader>(&data);
791 }
792 
793 }  // namespace zucchini
794