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