ensemble_apply.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. // Copyright (c) 2011 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. // This file contains the code to apply a Courgette patch.
  5. #include "courgette/ensemble.h"
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <memory>
  9. #include <utility>
  10. #include "base/check.h"
  11. #include "base/files/file.h"
  12. #include "base/files/file_util.h"
  13. #include "base/files/memory_mapped_file.h"
  14. #include "courgette/crc.h"
  15. #include "courgette/patcher_x86_32.h"
  16. #include "courgette/region.h"
  17. #include "courgette/simple_delta.h"
  18. #include "courgette/streams.h"
  19. namespace courgette {
  20. // EnsemblePatchApplication is all the logic and data required to apply the
  21. // multi-stage patch.
  22. class EnsemblePatchApplication {
  23. public:
  24. EnsemblePatchApplication();
  25. EnsemblePatchApplication(const EnsemblePatchApplication&) = delete;
  26. EnsemblePatchApplication& operator=(const EnsemblePatchApplication&) = delete;
  27. ~EnsemblePatchApplication() = default;
  28. Status ReadHeader(SourceStream* header_stream);
  29. Status InitBase(const Region& region);
  30. Status ValidateBase();
  31. Status ReadInitialParameters(SourceStream* initial_parameters);
  32. Status PredictTransformParameters(SinkStreamSet* predicted_parameters);
  33. Status SubpatchTransformParameters(SinkStreamSet* prediction,
  34. SourceStream* correction,
  35. SourceStreamSet* corrected_parameters);
  36. Status TransformUp(SourceStreamSet* parameters,
  37. SinkStreamSet* transformed_elements);
  38. Status SubpatchTransformedElements(SinkStreamSet* elements,
  39. SourceStream* correction,
  40. SourceStreamSet* corrected_elements);
  41. Status TransformDown(SourceStreamSet* transformed_elements,
  42. SinkStream* basic_elements);
  43. Status SubpatchFinalOutput(SourceStream* original,
  44. SourceStream* correction,
  45. SinkStream* corrected_ensemble);
  46. private:
  47. Status SubpatchStreamSets(SinkStreamSet* predicted_items,
  48. SourceStream* correction,
  49. SourceStreamSet* corrected_items,
  50. SinkStream* corrected_items_storage);
  51. Region base_region_; // Location of in-memory copy of 'old' version.
  52. uint32_t source_checksum_;
  53. uint32_t target_checksum_;
  54. uint32_t final_patch_input_size_prediction_;
  55. std::vector<std::unique_ptr<TransformationPatcher>> patchers_;
  56. SinkStream corrected_parameters_storage_;
  57. SinkStream corrected_elements_storage_;
  58. };
  59. EnsemblePatchApplication::EnsemblePatchApplication()
  60. : source_checksum_(0), target_checksum_(0),
  61. final_patch_input_size_prediction_(0) {
  62. }
  63. Status EnsemblePatchApplication::ReadHeader(SourceStream* header_stream) {
  64. uint32_t magic;
  65. if (!header_stream->ReadVarint32(&magic))
  66. return C_BAD_ENSEMBLE_MAGIC;
  67. if (magic != CourgettePatchFile::kMagic)
  68. return C_BAD_ENSEMBLE_MAGIC;
  69. uint32_t version;
  70. if (!header_stream->ReadVarint32(&version))
  71. return C_BAD_ENSEMBLE_VERSION;
  72. if (version != CourgettePatchFile::kVersion)
  73. return C_BAD_ENSEMBLE_VERSION;
  74. if (!header_stream->ReadVarint32(&source_checksum_))
  75. return C_BAD_ENSEMBLE_HEADER;
  76. if (!header_stream->ReadVarint32(&target_checksum_))
  77. return C_BAD_ENSEMBLE_HEADER;
  78. if (!header_stream->ReadVarint32(&final_patch_input_size_prediction_))
  79. return C_BAD_ENSEMBLE_HEADER;
  80. return C_OK;
  81. }
  82. Status EnsemblePatchApplication::InitBase(const Region& region) {
  83. base_region_.assign(region);
  84. return C_OK;
  85. }
  86. Status EnsemblePatchApplication::ValidateBase() {
  87. uint32_t checksum = CalculateCrc(base_region_.start(), base_region_.length());
  88. if (source_checksum_ != checksum)
  89. return C_BAD_ENSEMBLE_CRC;
  90. return C_OK;
  91. }
  92. Status EnsemblePatchApplication::ReadInitialParameters(
  93. SourceStream* transformation_parameters) {
  94. uint32_t number_of_transformations = 0;
  95. if (!transformation_parameters->ReadVarint32(&number_of_transformations))
  96. return C_BAD_ENSEMBLE_HEADER;
  97. for (size_t i = 0; i < number_of_transformations; ++i) {
  98. uint32_t kind;
  99. if (!transformation_parameters->ReadVarint32(&kind))
  100. return C_BAD_ENSEMBLE_HEADER;
  101. std::unique_ptr<TransformationPatcher> patcher;
  102. switch (kind) {
  103. case EXE_WIN_32_X86: // Fall through.
  104. case EXE_ELF_32_X86:
  105. case EXE_WIN_32_X64:
  106. patcher = std::make_unique<PatcherX86_32>(base_region_);
  107. break;
  108. default:
  109. return C_BAD_ENSEMBLE_HEADER;
  110. }
  111. DCHECK(patcher);
  112. patchers_.push_back(std::move(patcher));
  113. }
  114. for (size_t i = 0; i < patchers_.size(); ++i) {
  115. Status status = patchers_[i]->Init(transformation_parameters);
  116. if (status != C_OK)
  117. return status;
  118. }
  119. // All transformation_parameters should have been consumed by the above loop.
  120. if (!transformation_parameters->Empty())
  121. return C_BAD_ENSEMBLE_HEADER;
  122. return C_OK;
  123. }
  124. Status EnsemblePatchApplication::PredictTransformParameters(
  125. SinkStreamSet* all_predicted_parameters) {
  126. for (size_t i = 0; i < patchers_.size(); ++i) {
  127. SinkStreamSet single_predicted_parameters;
  128. Status status =
  129. patchers_[i]->PredictTransformParameters(&single_predicted_parameters);
  130. if (status != C_OK)
  131. return status;
  132. if (!all_predicted_parameters->WriteSet(&single_predicted_parameters))
  133. return C_STREAM_ERROR;
  134. }
  135. return C_OK;
  136. }
  137. Status EnsemblePatchApplication::SubpatchTransformParameters(
  138. SinkStreamSet* predicted_parameters,
  139. SourceStream* correction,
  140. SourceStreamSet* corrected_parameters) {
  141. return SubpatchStreamSets(predicted_parameters,
  142. correction,
  143. corrected_parameters,
  144. &corrected_parameters_storage_);
  145. }
  146. Status EnsemblePatchApplication::TransformUp(
  147. SourceStreamSet* parameters,
  148. SinkStreamSet* transformed_elements) {
  149. for (size_t i = 0; i < patchers_.size(); ++i) {
  150. SourceStreamSet single_parameters;
  151. if (!parameters->ReadSet(&single_parameters))
  152. return C_STREAM_ERROR;
  153. SinkStreamSet single_transformed_element;
  154. Status status = patchers_[i]->Transform(&single_parameters,
  155. &single_transformed_element);
  156. if (status != C_OK)
  157. return status;
  158. if (!single_parameters.Empty())
  159. return C_STREAM_NOT_CONSUMED;
  160. if (!transformed_elements->WriteSet(&single_transformed_element))
  161. return C_STREAM_ERROR;
  162. }
  163. if (!parameters->Empty())
  164. return C_STREAM_NOT_CONSUMED;
  165. return C_OK;
  166. }
  167. Status EnsemblePatchApplication::SubpatchTransformedElements(
  168. SinkStreamSet* predicted_elements,
  169. SourceStream* correction,
  170. SourceStreamSet* corrected_elements) {
  171. return SubpatchStreamSets(predicted_elements,
  172. correction,
  173. corrected_elements,
  174. &corrected_elements_storage_);
  175. }
  176. Status EnsemblePatchApplication::TransformDown(
  177. SourceStreamSet* transformed_elements,
  178. SinkStream* basic_elements) {
  179. // Construct blob of original input followed by reformed elements.
  180. if (!basic_elements->Reserve(final_patch_input_size_prediction_)) {
  181. return C_STREAM_ERROR;
  182. }
  183. // The original input:
  184. if (!basic_elements->Write(base_region_.start(), base_region_.length()))
  185. return C_STREAM_ERROR;
  186. for (size_t i = 0; i < patchers_.size(); ++i) {
  187. SourceStreamSet single_corrected_element;
  188. if (!transformed_elements->ReadSet(&single_corrected_element))
  189. return C_STREAM_ERROR;
  190. Status status = patchers_[i]->Reform(&single_corrected_element,
  191. basic_elements);
  192. if (status != C_OK)
  193. return status;
  194. if (!single_corrected_element.Empty())
  195. return C_STREAM_NOT_CONSUMED;
  196. }
  197. if (!transformed_elements->Empty())
  198. return C_STREAM_NOT_CONSUMED;
  199. // We have totally consumed transformed_elements, so can free the
  200. // storage to which it referred.
  201. corrected_elements_storage_.Retire();
  202. return C_OK;
  203. }
  204. Status EnsemblePatchApplication::SubpatchFinalOutput(
  205. SourceStream* original,
  206. SourceStream* correction,
  207. SinkStream* corrected_ensemble) {
  208. Status delta_status = ApplySimpleDelta(original, correction,
  209. corrected_ensemble);
  210. if (delta_status != C_OK)
  211. return delta_status;
  212. if (CalculateCrc(corrected_ensemble->Buffer(),
  213. corrected_ensemble->Length()) != target_checksum_)
  214. return C_BAD_ENSEMBLE_CRC;
  215. return C_OK;
  216. }
  217. Status EnsemblePatchApplication::SubpatchStreamSets(
  218. SinkStreamSet* predicted_items,
  219. SourceStream* correction,
  220. SourceStreamSet* corrected_items,
  221. SinkStream* corrected_items_storage) {
  222. SinkStream linearized_predicted_items;
  223. if (!predicted_items->CopyTo(&linearized_predicted_items))
  224. return C_STREAM_ERROR;
  225. SourceStream prediction;
  226. prediction.Init(linearized_predicted_items);
  227. Status status = ApplySimpleDelta(&prediction,
  228. correction,
  229. corrected_items_storage);
  230. if (status != C_OK)
  231. return status;
  232. if (!corrected_items->Init(corrected_items_storage->Buffer(),
  233. corrected_items_storage->Length()))
  234. return C_STREAM_ERROR;
  235. return C_OK;
  236. }
  237. Status ApplyEnsemblePatch(SourceStream* base,
  238. SourceStream* patch,
  239. SinkStream* output) {
  240. Status status;
  241. EnsemblePatchApplication patch_process;
  242. status = patch_process.ReadHeader(patch);
  243. if (status != C_OK)
  244. return status;
  245. status = patch_process.InitBase(Region(base->Buffer(), base->Remaining()));
  246. if (status != C_OK)
  247. return status;
  248. status = patch_process.ValidateBase();
  249. if (status != C_OK)
  250. return status;
  251. // The rest of the patch stream is a StreamSet.
  252. SourceStreamSet patch_streams;
  253. patch_streams.Init(patch);
  254. SourceStream* transformation_descriptions = patch_streams.stream(0);
  255. SourceStream* parameter_correction = patch_streams.stream(1);
  256. SourceStream* transformed_elements_correction = patch_streams.stream(2);
  257. SourceStream* ensemble_correction = patch_streams.stream(3);
  258. status = patch_process.ReadInitialParameters(transformation_descriptions);
  259. if (status != C_OK)
  260. return status;
  261. SinkStreamSet predicted_parameters;
  262. status = patch_process.PredictTransformParameters(&predicted_parameters);
  263. if (status != C_OK)
  264. return status;
  265. SourceStreamSet corrected_parameters;
  266. status = patch_process.SubpatchTransformParameters(&predicted_parameters,
  267. parameter_correction,
  268. &corrected_parameters);
  269. if (status != C_OK)
  270. return status;
  271. SinkStreamSet transformed_elements;
  272. status = patch_process.TransformUp(&corrected_parameters,
  273. &transformed_elements);
  274. if (status != C_OK)
  275. return status;
  276. SourceStreamSet corrected_transformed_elements;
  277. status = patch_process.SubpatchTransformedElements(
  278. &transformed_elements,
  279. transformed_elements_correction,
  280. &corrected_transformed_elements);
  281. if (status != C_OK)
  282. return status;
  283. SinkStream original_ensemble_and_corrected_base_elements;
  284. status = patch_process.TransformDown(
  285. &corrected_transformed_elements,
  286. &original_ensemble_and_corrected_base_elements);
  287. if (status != C_OK)
  288. return status;
  289. SourceStream final_patch_prediction;
  290. final_patch_prediction.Init(original_ensemble_and_corrected_base_elements);
  291. status = patch_process.SubpatchFinalOutput(&final_patch_prediction,
  292. ensemble_correction, output);
  293. if (status != C_OK)
  294. return status;
  295. return C_OK;
  296. }
  297. Status ApplyEnsemblePatch(base::File old_file,
  298. base::File patch_file,
  299. base::File new_file) {
  300. base::MemoryMappedFile patch_file_mem;
  301. if (!patch_file_mem.Initialize(std::move(patch_file)))
  302. return C_READ_OPEN_ERROR;
  303. // 'Dry-run' the first step of the patch process to validate format of header.
  304. SourceStream patch_header_stream;
  305. patch_header_stream.Init(patch_file_mem.data(), patch_file_mem.length());
  306. EnsemblePatchApplication patch_process;
  307. Status status = patch_process.ReadHeader(&patch_header_stream);
  308. if (status != C_OK)
  309. return status;
  310. // Read the old_file.
  311. base::MemoryMappedFile old_file_mem;
  312. if (!old_file_mem.Initialize(std::move(old_file)))
  313. return C_READ_ERROR;
  314. // Apply patch on streams.
  315. SourceStream old_source_stream;
  316. SourceStream patch_source_stream;
  317. old_source_stream.Init(old_file_mem.data(), old_file_mem.length());
  318. patch_source_stream.Init(patch_file_mem.data(), patch_file_mem.length());
  319. SinkStream new_sink_stream;
  320. status = ApplyEnsemblePatch(&old_source_stream, &patch_source_stream,
  321. &new_sink_stream);
  322. if (status != C_OK)
  323. return status;
  324. // Write the patched data to |new_file_name|.
  325. int written = new_file.Write(
  326. 0,
  327. reinterpret_cast<const char*>(new_sink_stream.Buffer()),
  328. static_cast<int>(new_sink_stream.Length()));
  329. if (written == -1)
  330. return C_WRITE_OPEN_ERROR;
  331. if (static_cast<size_t>(written) != new_sink_stream.Length())
  332. return C_WRITE_ERROR;
  333. return C_OK;
  334. }
  335. Status ApplyEnsemblePatch(const base::FilePath::CharType* old_file_name,
  336. const base::FilePath::CharType* patch_file_name,
  337. const base::FilePath::CharType* new_file_name) {
  338. Status result = ApplyEnsemblePatch(
  339. base::File(base::FilePath(old_file_name),
  340. base::File::FLAG_OPEN | base::File::FLAG_READ |
  341. base::File::FLAG_WIN_SHARE_DELETE),
  342. base::File(base::FilePath(patch_file_name),
  343. base::File::FLAG_OPEN | base::File::FLAG_READ |
  344. base::File::FLAG_WIN_SHARE_DELETE),
  345. base::File(base::FilePath(new_file_name),
  346. base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
  347. base::File::FLAG_WIN_EXCLUSIVE_WRITE |
  348. base::File::FLAG_WIN_SHARE_DELETE));
  349. if (result != C_OK)
  350. base::DeleteFile(base::FilePath(new_file_name));
  351. return result;
  352. }
  353. } // namespace courgette