blob: 319a88a9f46f004e4111808791c28de7308cfc26 [file] [log] [blame]
Samuel Huang06f1ae92018-03-13 18:19:34 +00001// 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/element_detection.h"
6
Samuel Huangf35146e2018-06-21 15:50:22 +00007#include <map>
Samuel Huang06f1ae92018-03-13 18:19:34 +00008#include <vector>
9
10#include "base/bind.h"
11#include "components/zucchini/buffer_view.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace zucchini {
Samuel Huang06f1ae92018-03-13 18:19:34 +000015namespace {
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000016// This test uses a mock archive format where regions are determined by their
17// consecutive byte values rather than parsing real executables.
18//
19// 0 - Padding or raw data (not mapped to an executable).
20// 1 - A Win32x86 executable.
21// 2 - A Win32x64 executable.
22//
23// So an example archive file of;
24// 0 1 1 1 0 1 1 0 0 2 2 2 2
25// contains (in order left to right):
26// - One padding byte
27// - Three byte Win32x86 executable
28// - One padding byte
29// - Two byte Win32x86 executable
30// - Two padding bytes
31// - Four byte Win32x64 executable
Samuel Huang06f1ae92018-03-13 18:19:34 +000032
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000033class ElementDetectionTest : public ::testing::Test {
34 protected:
35 using ElementVector = std::vector<Element>;
36 using ExeTypeMap = std::map<uint8_t, ExecutableType>;
Samuel Huang06f1ae92018-03-13 18:19:34 +000037
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000038 ElementDetectionTest()
39 : exe_map_({{1, kExeTypeWin32X86}, {2, kExeTypeWin32X64}}) {}
Samuel Huang06f1ae92018-03-13 18:19:34 +000040
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000041 ElementVector TestElementFinder(std::vector<uint8_t> buffer) {
42 ConstBufferView image(buffer.data(), buffer.size());
43
44 ElementFinder finder(
45 image,
46 base::BindRepeating(
47 [](ExeTypeMap exe_map, ConstBufferView image,
Anton Bikineev1a965512021-05-15 22:35:36 +000048 ConstBufferView region) -> absl::optional<Element> {
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000049 EXPECT_GE(region.begin(), image.begin());
50 EXPECT_LE(region.end(), image.end());
51 EXPECT_GE(region.size(), 0U);
52
53 if (region[0] != 0) {
54 offset_t length = 1;
55 while (length < region.size() && region[length] == region[0])
56 ++length;
57 return Element{{0, length}, exe_map[region[0]]};
58 }
Anton Bikineev1a965512021-05-15 22:35:36 +000059 return absl::nullopt;
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000060 },
61 exe_map_, image));
62 std::vector<Element> elements;
63 for (auto element = finder.GetNext(); element; element = finder.GetNext()) {
64 elements.push_back(*element);
65 }
66 return elements;
67 }
68
69 // Translation map from mock archive bytes to actual types used in Zucchini.
70 ExeTypeMap exe_map_;
71};
72
73TEST_F(ElementDetectionTest, ElementFinderEmpty) {
Samuel Huang06f1ae92018-03-13 18:19:34 +000074 std::vector<uint8_t> buffer(10, 0);
75 ElementFinder finder(
76 ConstBufferView(buffer.data(), buffer.size()),
Anton Bikineev1a965512021-05-15 22:35:36 +000077 base::BindRepeating([](ConstBufferView image) -> absl::optional<Element> {
78 return absl::nullopt;
Samuel Huang06f1ae92018-03-13 18:19:34 +000079 }));
Anton Bikineev1a965512021-05-15 22:35:36 +000080 EXPECT_EQ(absl::nullopt, finder.GetNext());
Samuel Huang06f1ae92018-03-13 18:19:34 +000081}
82
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +000083TEST_F(ElementDetectionTest, ElementFinder) {
Samuel Huang06f1ae92018-03-13 18:19:34 +000084 EXPECT_EQ(ElementVector(), TestElementFinder({}));
85 EXPECT_EQ(ElementVector(), TestElementFinder({0, 0}));
86 EXPECT_EQ(ElementVector({{{0, 2}, kExeTypeWin32X86}}),
87 TestElementFinder({1, 1}));
88 EXPECT_EQ(
89 ElementVector({{{0, 2}, kExeTypeWin32X86}, {{2, 2}, kExeTypeWin32X64}}),
90 TestElementFinder({1, 1, 2, 2}));
91 EXPECT_EQ(ElementVector({{{1, 2}, kExeTypeWin32X86}}),
92 TestElementFinder({0, 1, 1, 0}));
93 EXPECT_EQ(
94 ElementVector({{{1, 2}, kExeTypeWin32X86}, {{3, 3}, kExeTypeWin32X64}}),
95 TestElementFinder({0, 1, 1, 2, 2, 2}));
96 EXPECT_EQ(
97 ElementVector({{{1, 2}, kExeTypeWin32X86}, {{4, 3}, kExeTypeWin32X64}}),
98 TestElementFinder({0, 1, 1, 0, 2, 2, 2}));
99}
100
Calder Kitagawa05b1b6a2018-04-24 13:54:46 +0000101} // namespace
Samuel Huang06f1ae92018-03-13 18:19:34 +0000102} // namespace zucchini