blob: 7959d285f909030649c519d974a1aa031b1227a2 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2017 The Chromium Authors
huangsf953e4072017-07-28 01:16:212// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Arthur Sonzognib948e672024-07-31 08:29:045#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
7#pragma allow_unsafe_buffers
8#endif
9
Samuel Huang577ef6c2018-03-13 18:19:3410#include "components/zucchini/zucchini_commands.h"
huangsf953e4072017-07-28 01:16:2111
Samuel Huange8d07b752017-08-21 16:05:2512#include <stddef.h>
13#include <stdint.h>
14
huangs252600a2017-07-31 22:19:4815#include <ostream>
Samuel Huang73a64ff2018-04-30 22:47:5216#include <string>
Samuel Huang577ef6c2018-03-13 18:19:3417#include <utility>
huangs252600a2017-07-31 22:19:4818
19#include "base/command_line.h"
20#include "base/files/file.h"
21#include "base/files/file_path.h"
22#include "base/files/memory_mapped_file.h"
huangsf953e4072017-07-28 01:16:2123#include "base/logging.h"
Samuel Huang577ef6c2018-03-13 18:19:3424#include "components/zucchini/buffer_view.h"
25#include "components/zucchini/crc32.h"
Samuel Huang0fe9ae92022-10-31 17:30:1326#include "components/zucchini/encoded_view.h"
27#include "components/zucchini/image_index.h"
Samuel Huang577ef6c2018-03-13 18:19:3428#include "components/zucchini/io_utils.h"
29#include "components/zucchini/mapped_file.h"
30#include "components/zucchini/patch_writer.h"
Samuel Huang0fe9ae92022-10-31 17:30:1331#include "components/zucchini/suffix_array.h"
Samuel Huang577ef6c2018-03-13 18:19:3432#include "components/zucchini/zucchini_integration.h"
33#include "components/zucchini/zucchini_tools.h"
huangsf953e4072017-07-28 01:16:2134
35namespace {
36
Samuel Huang0fe9ae92022-10-31 17:30:1337using zucchini::status::kStatusFileReadError;
38using zucchini::status::kStatusSuccess;
39
Etienne Pierre-Doray73ed4232017-08-10 01:28:4140/******** Command-line Switches ********/
41
Samuel Huangd943db62017-08-23 21:46:5742constexpr char kSwitchDump[] = "dump";
Samuel Huang73a64ff2018-04-30 22:47:5243constexpr char kSwitchImpose[] = "impose";
Samuel Huang21879c32018-03-21 18:54:0344constexpr char kSwitchKeep[] = "keep";
Samuel Huangd943db62017-08-23 21:46:5745constexpr char kSwitchRaw[] = "raw";
Samuel Huang304d2162025-05-15 13:54:1246constexpr char kSwitchStartScanAt[] = "start-scan-at";
Etienne Pierre-Doray73ed4232017-08-10 01:28:4147
Samuel Huang0fe9ae92022-10-31 17:30:1348class WrappedMappedFileReader : public zucchini::MappedFileReader {
49 public:
50 static constexpr uint32_t read_flags = base::File::FLAG_OPEN |
51 base::File::FLAG_READ |
52 base::File::FLAG_WIN_SHARE_DELETE;
53
54 explicit WrappedMappedFileReader(const base::FilePath& path)
55 : MappedFileReader(base::File(path, read_flags)) {
56 if (HasError()) {
57 LOG(ERROR) << "Error reading file " << path.value() << ": " << error();
58 status = kStatusFileReadError;
59 }
60 }
61
62 zucchini::status::Code status = kStatusSuccess;
63};
64
Samuel Huang304d2162025-05-15 13:54:1265zucchini::GenerateOptions ReadGenerateOptions(const MainParams& params) {
66 zucchini::GenerateOptions options{
67 .imposed_matches =
68 params.command_line->GetSwitchValueASCII(kSwitchImpose),
69 .is_raw = params.command_line->HasSwitch(kSwitchRaw),
70 };
71 if (params.command_line->HasSwitch(kSwitchStartScanAt)) {
72 const std::string s =
73 params.command_line->GetSwitchValueASCII(kSwitchStartScanAt);
74 std::istringstream(s) >> options.start_scan_at;
75 }
76 return options;
77}
78
huangsf953e4072017-07-28 01:16:2179} // namespace
80
Samuel Huang304d2162025-05-15 13:54:1281/******** Various Main*() functions ********/
82
huangs252600a2017-07-31 22:19:4883zucchini::status::Code MainGen(MainParams params) {
Samuel Huang304d2162025-05-15 13:54:1284 zucchini::GenerateOptions options = ReadGenerateOptions(params);
Ali Hijazia709b48b2022-11-09 01:27:4485 CHECK_EQ(3U, params.file_paths->size());
Samuel Huang304d2162025-05-15 13:54:1286 return zucchini::Generate((*params.file_paths)[0], (*params.file_paths)[1],
87 (*params.file_paths)[2], options,
88 params.command_line->HasSwitch(kSwitchKeep));
huangsf953e4072017-07-28 01:16:2189}
90
huangs252600a2017-07-31 22:19:4891zucchini::status::Code MainApply(MainParams params) {
Ali Hijazia709b48b2022-11-09 01:27:4492 CHECK_EQ(3U, params.file_paths->size());
93 return zucchini::Apply((*params.file_paths)[0], (*params.file_paths)[1],
94 (*params.file_paths)[2],
95 params.command_line->HasSwitch(kSwitchKeep));
Samuel Huangd943db62017-08-23 21:46:5796}
97
Etienne Pierre-doray559d77a2021-10-28 21:16:0498zucchini::status::Code MainVerify(MainParams params) {
Ali Hijazia709b48b2022-11-09 01:27:4499 CHECK_EQ(1U, params.file_paths->size());
100 return zucchini::VerifyPatch((*params.file_paths)[0]);
Etienne Pierre-doray559d77a2021-10-28 21:16:04101}
102
Samuel Huangd943db62017-08-23 21:46:57103zucchini::status::Code MainRead(MainParams params) {
Ali Hijazia709b48b2022-11-09 01:27:44104 CHECK_EQ(1U, params.file_paths->size());
105 WrappedMappedFileReader input((*params.file_paths)[0]);
Samuel Huang0fe9ae92022-10-31 17:30:13106 if (input.status != kStatusSuccess)
107 return input.status;
Samuel Huangd943db62017-08-23 21:46:57108
Ali Hijazia709b48b2022-11-09 01:27:44109 bool do_dump = params.command_line->HasSwitch(kSwitchDump);
Samuel Huangd943db62017-08-23 21:46:57110 zucchini::status::Code status = zucchini::ReadReferences(
Ali Hijazia709b48b2022-11-09 01:27:44111 {input.data(), input.length()}, do_dump, *params.out);
Samuel Huang0fe9ae92022-10-31 17:30:13112 if (status != kStatusSuccess)
Ali Hijazia709b48b2022-11-09 01:27:44113 *params.err << "Fatal error found when dumping references." << std::endl;
Samuel Huangd943db62017-08-23 21:46:57114 return status;
huangs252600a2017-07-31 22:19:48115}
116
Samuel Huangdd90d832017-11-03 18:14:02117zucchini::status::Code MainDetect(MainParams params) {
Samuel Huang304d2162025-05-15 13:54:12118 zucchini::GenerateOptions options = ReadGenerateOptions(params);
Ali Hijazia709b48b2022-11-09 01:27:44119 CHECK_EQ(1U, params.file_paths->size());
120 WrappedMappedFileReader input((*params.file_paths)[0]);
Samuel Huang0fe9ae92022-10-31 17:30:13121 if (input.status != kStatusSuccess)
122 return input.status;
Samuel Huangdd90d832017-11-03 18:14:02123
124 std::vector<zucchini::ConstBufferView> sub_image_list;
125 zucchini::status::Code result = zucchini::DetectAll(
Samuel Huang304d2162025-05-15 13:54:12126 {input.data(), input.length()}, options, *params.out, &sub_image_list);
Samuel Huang0fe9ae92022-10-31 17:30:13127 if (result != kStatusSuccess)
Ali Hijazia709b48b2022-11-09 01:27:44128 *params.err << "Fatal error found when detecting executables." << std::endl;
Samuel Huangdd90d832017-11-03 18:14:02129 return result;
130}
131
Samuel Huangfdb2f3a2017-12-20 17:45:14132zucchini::status::Code MainMatch(MainParams params) {
Samuel Huang304d2162025-05-15 13:54:12133 zucchini::GenerateOptions options = ReadGenerateOptions(params);
Ali Hijazia709b48b2022-11-09 01:27:44134 CHECK_EQ(2U, params.file_paths->size());
135 WrappedMappedFileReader old_image((*params.file_paths)[0]);
Samuel Huang0fe9ae92022-10-31 17:30:13136 if (old_image.status != kStatusSuccess)
137 return old_image.status;
Ali Hijazia709b48b2022-11-09 01:27:44138 WrappedMappedFileReader new_image((*params.file_paths)[1]);
Samuel Huang0fe9ae92022-10-31 17:30:13139 if (new_image.status != kStatusSuccess)
140 return new_image.status;
Samuel Huang73a64ff2018-04-30 22:47:52141
Samuel Huang304d2162025-05-15 13:54:12142 zucchini::status::Code status = zucchini::MatchAll(
143 {old_image.data(), old_image.length()},
144 {new_image.data(), new_image.length()}, options, *params.out);
Samuel Huang0fe9ae92022-10-31 17:30:13145 if (status != kStatusSuccess)
Ali Hijazia709b48b2022-11-09 01:27:44146 *params.err << "Fatal error found when matching executables." << std::endl;
Samuel Huangfdb2f3a2017-12-20 17:45:14147 return status;
148}
149
huangs252600a2017-07-31 22:19:48150zucchini::status::Code MainCrc32(MainParams params) {
Ali Hijazia709b48b2022-11-09 01:27:44151 CHECK_EQ(1U, params.file_paths->size());
152 WrappedMappedFileReader input((*params.file_paths)[0]);
Samuel Huang0fe9ae92022-10-31 17:30:13153 if (input.status != kStatusSuccess)
154 return input.status;
huangs252600a2017-07-31 22:19:48155
156 uint32_t crc =
Samuel Huang0fe9ae92022-10-31 17:30:13157 zucchini::CalculateCrc32(input.data(), input.data() + input.length());
Ali Hijazia709b48b2022-11-09 01:27:44158 *params.out << "CRC32: " << zucchini::AsHex<8>(crc) << std::endl;
Samuel Huang0fe9ae92022-10-31 17:30:13159 return kStatusSuccess;
160}
161
162zucchini::status::Code MainSuffixArray(MainParams params) {
Ali Hijazia709b48b2022-11-09 01:27:44163 CHECK_EQ(1U, params.file_paths->size());
164 WrappedMappedFileReader input((*params.file_paths)[0]);
Samuel Huang0fe9ae92022-10-31 17:30:13165 if (input.status != kStatusSuccess)
166 return input.status;
167
168 zucchini::ImageIndex image_index(input.region());
169 zucchini::EncodedView view_raw(image_index);
170 std::vector<zucchini::offset_t> sa_raw =
171 zucchini::MakeSuffixArray<zucchini::InducedSuffixSort>(view_raw,
172 size_t(256));
173 return kStatusSuccess;
huangsf953e4072017-07-28 01:16:21174}