• 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/zucchini_commands.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <ostream>
11 #include <string>
12 #include <utility>
13 
14 #include "base/command_line.h"
15 #include "base/files/file.h"
16 #include "base/files/file_path.h"
17 #include "base/files/memory_mapped_file.h"
18 #include "base/logging.h"
19 #include "components/zucchini/buffer_view.h"
20 #include "components/zucchini/crc32.h"
21 #include "components/zucchini/io_utils.h"
22 #include "components/zucchini/mapped_file.h"
23 #include "components/zucchini/patch_writer.h"
24 #include "components/zucchini/zucchini_integration.h"
25 #include "components/zucchini/zucchini_tools.h"
26 
27 namespace {
28 
29 /******** Command-line Switches ********/
30 
31 constexpr char kSwitchDump[] = "dump";
32 constexpr char kSwitchImpose[] = "impose";
33 constexpr char kSwitchKeep[] = "keep";
34 constexpr char kSwitchRaw[] = "raw";
35 
36 }  // namespace
37 
MainGen(MainParams params)38 zucchini::status::Code MainGen(MainParams params) {
39   CHECK_EQ(3U, params.file_paths.size());
40   return zucchini::Generate(
41       params.file_paths[0], params.file_paths[1], params.file_paths[2],
42       params.command_line.HasSwitch(kSwitchKeep),
43       params.command_line.HasSwitch(kSwitchRaw),
44       params.command_line.GetSwitchValueASCII(kSwitchImpose));
45 }
46 
MainApply(MainParams params)47 zucchini::status::Code MainApply(MainParams params) {
48   CHECK_EQ(3U, params.file_paths.size());
49   return zucchini::Apply(params.file_paths[0], params.file_paths[1],
50                          params.file_paths[2],
51                          params.command_line.HasSwitch(kSwitchKeep));
52 }
53 
MainVerify(MainParams params)54 zucchini::status::Code MainVerify(MainParams params) {
55   CHECK_EQ(1U, params.file_paths.size());
56   return zucchini::VerifyPatch(params.file_paths[0]);
57 }
58 
MainRead(MainParams params)59 zucchini::status::Code MainRead(MainParams params) {
60   CHECK_EQ(1U, params.file_paths.size());
61   base::File input_file(params.file_paths[0],
62                         base::File::FLAG_OPEN | base::File::FLAG_READ |
63                             base::File::FLAG_WIN_SHARE_DELETE);
64   zucchini::MappedFileReader input(std::move(input_file));
65   if (input.HasError()) {
66     LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
67                << input.error();
68     return zucchini::status::kStatusFileReadError;
69   }
70 
71   bool do_dump = params.command_line.HasSwitch(kSwitchDump);
72   zucchini::status::Code status = zucchini::ReadReferences(
73       {input.data(), input.length()}, do_dump, params.out);
74   if (status != zucchini::status::kStatusSuccess)
75     params.err << "Fatal error found when dumping references." << std::endl;
76   return status;
77 }
78 
MainDetect(MainParams params)79 zucchini::status::Code MainDetect(MainParams params) {
80   CHECK_EQ(1U, params.file_paths.size());
81   base::File input_file(params.file_paths[0],
82                         base::File::FLAG_OPEN | base::File::FLAG_READ |
83                             base::File::FLAG_WIN_SHARE_DELETE);
84   zucchini::MappedFileReader input(std::move(input_file));
85   if (input.HasError()) {
86     LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
87                << input.error();
88     return zucchini::status::kStatusFileReadError;
89   }
90 
91   std::vector<zucchini::ConstBufferView> sub_image_list;
92   zucchini::status::Code result = zucchini::DetectAll(
93       {input.data(), input.length()}, params.out, &sub_image_list);
94   if (result != zucchini::status::kStatusSuccess)
95     params.err << "Fatal error found when detecting executables." << std::endl;
96   return result;
97 }
98 
MainMatch(MainParams params)99 zucchini::status::Code MainMatch(MainParams params) {
100   CHECK_EQ(2U, params.file_paths.size());
101   using base::File;
102   File old_file(params.file_paths[0], File::FLAG_OPEN | File::FLAG_READ |
103                                           base::File::FLAG_WIN_SHARE_DELETE);
104   zucchini::MappedFileReader old_image(std::move(old_file));
105   if (old_image.HasError()) {
106     LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
107                << old_image.error();
108     return zucchini::status::kStatusFileReadError;
109   }
110   File new_file(params.file_paths[1], File::FLAG_OPEN | File::FLAG_READ |
111                                           base::File::FLAG_WIN_SHARE_DELETE);
112   zucchini::MappedFileReader new_image(std::move(new_file));
113   if (new_image.HasError()) {
114     LOG(ERROR) << "Error with file " << params.file_paths[1].value() << ": "
115                << new_image.error();
116     return zucchini::status::kStatusFileReadError;
117   }
118 
119   std::string imposed_matches =
120       params.command_line.GetSwitchValueASCII(kSwitchImpose);
121   zucchini::status::Code status =
122       zucchini::MatchAll({old_image.data(), old_image.length()},
123                          {new_image.data(), new_image.length()},
124                          std::move(imposed_matches), params.out);
125   if (status != zucchini::status::kStatusSuccess)
126     params.err << "Fatal error found when matching executables." << std::endl;
127   return status;
128 }
129 
MainCrc32(MainParams params)130 zucchini::status::Code MainCrc32(MainParams params) {
131   CHECK_EQ(1U, params.file_paths.size());
132   base::File image_file(params.file_paths[0],
133                         base::File::FLAG_OPEN | base::File::FLAG_READ |
134                             base::File::FLAG_WIN_SHARE_DELETE);
135   zucchini::MappedFileReader image(std::move(image_file));
136   if (image.HasError()) {
137     LOG(ERROR) << "Error with file " << params.file_paths[0].value() << ": "
138                << image.error();
139     return zucchini::status::kStatusFileReadError;
140   }
141 
142   uint32_t crc =
143       zucchini::CalculateCrc32(image.data(), image.data() + image.length());
144   params.out << "CRC32: " << zucchini::AsHex<8>(crc) << std::endl;
145   return zucchini::status::kStatusSuccess;
146 }
147