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