blob: 93d64b04747d3670e2d2bf108b7d638851132715 [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#ifndef COMPONENTS_ZUCCHINI_PATCH_READER_H_
6#define COMPONENTS_ZUCCHINI_PATCH_READER_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <map>
12#include <vector>
13
14#include "base/debug/stack_trace.h"
15#include "base/logging.h"
16#include "base/numerics/checked_math.h"
Samuel Huang06f1ae92018-03-13 18:19:34 +000017#include "components/zucchini/buffer_source.h"
18#include "components/zucchini/buffer_view.h"
19#include "components/zucchini/image_utils.h"
20#include "components/zucchini/patch_utils.h"
Anton Bikineev1a965512021-05-15 22:35:36 +000021#include "third_party/abseil-cpp/absl/types/optional.h"
Samuel Huang06f1ae92018-03-13 18:19:34 +000022
23namespace zucchini {
24
25namespace patch {
26
27// The Parse*() functions below attempt to extract data of a specific type from
28// the beginning of |source|. A parse function: On success, consumes the used
29// portion of |source|, writes data into the output parameter, and returns
30// true. Otherwise returns false and does not consume |source|.
31
32// Parses |source| for the next ElementMatch.
33bool ParseElementMatch(BufferSource* source, ElementMatch* element_match);
34
35// Parses |source| for the next embedded BufferSource.
36bool ParseBuffer(BufferSource* source, BufferSource* buffer);
37
38// Parses |source| for the next VarUInt.
39template <class T>
40bool ParseVarUInt(BufferSource* source, T* value) {
41 auto bytes_read = DecodeVarUInt(source->begin(), source->end(), value);
42 if (!bytes_read) {
43 LOG(ERROR) << "Impossible to read VarUInt from source.";
44 LOG(ERROR) << base::debug::StackTrace().ToString();
45 return false;
46 }
47 // Advance |source| beyond the VarUInt value.
48 source->Skip(bytes_read);
49 return true;
50}
51
52// Parses |source| for the next VarInt.
53template <class T>
54bool ParseVarInt(BufferSource* source, T* value) {
55 auto bytes_read = DecodeVarInt(source->begin(), source->end(), value);
56 if (!bytes_read) {
57 LOG(ERROR) << "Impossible to read VarInt from source.";
58 LOG(ERROR) << base::debug::StackTrace().ToString();
59 return false;
60 }
61 // Advance |source| beyond the VarInt value.
62 source->Skip(bytes_read);
63 return true;
64}
65
66} // namespace patch
67
68// The *Source classes below are light-weight (i.e., allows copying) visitors to
69// read patch data. Each of them has an associated "main type", and performs the
70// following:
71// - Consumes portions of a BufferSource (required to remain valid for the
72// lifetime of the object).
73// - Decodes consumed data, which represent a list of items with "main type".
74// - Dispenses "main type" elements (hence "Source" in the name).
75//
76// Common "core functions" implemented by *Source classes are:
77// - bool Initialize(BufferSource* source): Consumes data from BufferSource and
78// initializes internal states. Returns true if successful, and false
79// otherwise (|source| may be partially consumed).
Anton Bikineev1a965512021-05-15 22:35:36 +000080// - absl::optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and
81// returns the next item as absl::optional (returns absl::nullopt on failure).
Samuel Huang06f1ae92018-03-13 18:19:34 +000082// - bool Done() const: Returns true if no more items remain; otherwise false.
83//
84// Usage of *Source instances don't mix, and GetNext() have dissimilar
85// interfaces. Therefore we do not use inheritance to relate *Source classes,
86// and simply implement "core functions" with matching names.
87
88// Source for Equivalences.
89class EquivalenceSource {
90 public:
91 EquivalenceSource();
92 EquivalenceSource(const EquivalenceSource&);
93 ~EquivalenceSource();
94
95 // Core functions.
96 bool Initialize(BufferSource* source);
Anton Bikineev1a965512021-05-15 22:35:36 +000097 absl::optional<Equivalence> GetNext();
Samuel Huang06f1ae92018-03-13 18:19:34 +000098 bool Done() const {
99 return src_skip_.empty() && dst_skip_.empty() && copy_count_.empty();
100 }
101
102 // Accessors for unittest.
103 BufferSource src_skip() const { return src_skip_; }
104 BufferSource dst_skip() const { return dst_skip_; }
105 BufferSource copy_count() const { return copy_count_; }
106
107 private:
108 BufferSource src_skip_;
109 BufferSource dst_skip_;
110 BufferSource copy_count_;
111
112 base::CheckedNumeric<offset_t> previous_src_offset_ = 0;
113 base::CheckedNumeric<offset_t> previous_dst_offset_ = 0;
114};
115
116// Source for extra data.
117class ExtraDataSource {
118 public:
119 ExtraDataSource();
120 ExtraDataSource(const ExtraDataSource&);
121 ~ExtraDataSource();
122
123 // Core functions.
124 bool Initialize(BufferSource* source);
125 // |size| is the size in bytes of the buffer requested.
Anton Bikineev1a965512021-05-15 22:35:36 +0000126 absl::optional<ConstBufferView> GetNext(offset_t size);
Samuel Huang06f1ae92018-03-13 18:19:34 +0000127 bool Done() const { return extra_data_.empty(); }
128
129 // Accessors for unittest.
130 BufferSource extra_data() const { return extra_data_; }
131
132 private:
133 BufferSource extra_data_;
134};
135
136// Source for raw delta.
137class RawDeltaSource {
138 public:
139 RawDeltaSource();
140 RawDeltaSource(const RawDeltaSource&);
141 ~RawDeltaSource();
142
143 // Core functions.
144 bool Initialize(BufferSource* source);
Anton Bikineev1a965512021-05-15 22:35:36 +0000145 absl::optional<RawDeltaUnit> GetNext();
Samuel Huang06f1ae92018-03-13 18:19:34 +0000146 bool Done() const {
147 return raw_delta_skip_.empty() && raw_delta_diff_.empty();
148 }
149
150 // Accessors for unittest.
151 BufferSource raw_delta_skip() const { return raw_delta_skip_; }
152 BufferSource raw_delta_diff() const { return raw_delta_diff_; }
153
154 private:
155 BufferSource raw_delta_skip_;
156 BufferSource raw_delta_diff_;
157
158 base::CheckedNumeric<offset_t> copy_offset_compensation_ = 0;
159};
160
161// Source for reference delta.
162class ReferenceDeltaSource {
163 public:
164 ReferenceDeltaSource();
165 ReferenceDeltaSource(const ReferenceDeltaSource&);
166 ~ReferenceDeltaSource();
167
168 // Core functions.
169 bool Initialize(BufferSource* source);
Anton Bikineev1a965512021-05-15 22:35:36 +0000170 absl::optional<int32_t> GetNext();
Calder Kitagawa02a83192018-05-02 15:27:28 +0000171 bool Done() const { return source_.empty(); }
Samuel Huang06f1ae92018-03-13 18:19:34 +0000172
173 // Accessors for unittest.
Calder Kitagawa02a83192018-05-02 15:27:28 +0000174 BufferSource reference_delta() const { return source_; }
Samuel Huang06f1ae92018-03-13 18:19:34 +0000175
176 private:
Calder Kitagawa02a83192018-05-02 15:27:28 +0000177 BufferSource source_;
Samuel Huang06f1ae92018-03-13 18:19:34 +0000178};
179
180// Source for additional targets.
181class TargetSource {
182 public:
183 TargetSource();
184 TargetSource(const TargetSource&);
185 ~TargetSource();
186
187 // Core functions.
188 bool Initialize(BufferSource* source);
Anton Bikineev1a965512021-05-15 22:35:36 +0000189 absl::optional<offset_t> GetNext();
Samuel Huang06f1ae92018-03-13 18:19:34 +0000190 bool Done() const { return extra_targets_.empty(); }
191
192 // Accessors for unittest.
193 BufferSource extra_targets() const { return extra_targets_; }
194
195 private:
196 BufferSource extra_targets_;
197
198 base::CheckedNumeric<offset_t> target_compensation_ = 0;
199};
200
201// Following are utility classes providing a structured view on data forming a
202// patch.
203
204// Utility to read a patch element. A patch element contains all the information
205// necessary to patch a single element. This class provide access
206// to the multiple streams of data forming the patch element.
207class PatchElementReader {
208 public:
209 PatchElementReader();
210 PatchElementReader(PatchElementReader&&);
211 ~PatchElementReader();
212
213 // If data read from |source| is well-formed, initialize cached sources to
214 // read from it, and returns true. Otherwise returns false.
215 bool Initialize(BufferSource* source);
216
217 const ElementMatch& element_match() const { return element_match_; }
218 const Element& old_element() const { return element_match_.old_element; }
219 const Element& new_element() const { return element_match_.new_element; }
220
Calder Kitagawa673bf592018-04-27 22:37:45 +0000221 // The Get*() functions below return copies of cached sources. Callers may
222 // assume the following:
223 // - Equivalences satisfy basic boundary constraints
224 // - "Old" / "new" blocks lie entirely in "old" / "new" images.
225 // - "New" blocks are sorted.
Samuel Huang06f1ae92018-03-13 18:19:34 +0000226 EquivalenceSource GetEquivalenceSource() const { return equivalences_; }
227 ExtraDataSource GetExtraDataSource() const { return extra_data_; }
228 RawDeltaSource GetRawDeltaSource() const { return raw_delta_; }
229 ReferenceDeltaSource GetReferenceDeltaSource() const {
230 return reference_delta_;
231 }
232 TargetSource GetExtraTargetSource(PoolTag tag) const {
233 auto pos = extra_targets_.find(tag);
234 return pos != extra_targets_.end() ? pos->second : TargetSource();
235 }
236
237 private:
Calder Kitagawa673bf592018-04-27 22:37:45 +0000238 // Checks that "old" and "new" blocks of each item in |equivalences_| satisfy
Calder Kitagawa02a83192018-05-02 15:27:28 +0000239 // basic order and image bound constraints (using |element_match_| data). Also
240 // validates that the amount of extra data is correct. Returns true if
241 // successful.
242 bool ValidateEquivalencesAndExtraData();
Calder Kitagawa673bf592018-04-27 22:37:45 +0000243
Samuel Huang06f1ae92018-03-13 18:19:34 +0000244 ElementMatch element_match_;
245
246 // Cached sources.
247 EquivalenceSource equivalences_;
248 ExtraDataSource extra_data_;
249 RawDeltaSource raw_delta_;
250 ReferenceDeltaSource reference_delta_;
251 std::map<PoolTag, TargetSource> extra_targets_;
252};
253
254// Utility to read a Zucchini ensemble patch. An ensemble patch is the
255// concatenation of a patch header with a vector of patch elements.
256class EnsemblePatchReader {
257 public:
258 // If data read from |buffer| is well-formed, initializes and returns
Anton Bikineev1a965512021-05-15 22:35:36 +0000259 // an instance of EnsemblePatchReader. Otherwise returns absl::nullopt.
260 static absl::optional<EnsemblePatchReader> Create(ConstBufferView buffer);
Samuel Huang06f1ae92018-03-13 18:19:34 +0000261
262 EnsemblePatchReader();
263 EnsemblePatchReader(EnsemblePatchReader&&);
264 ~EnsemblePatchReader();
265
266 // If data read from |source| is well-formed, initialize internal state to
267 // read from it, and returns true. Otherwise returns false.
268 bool Initialize(BufferSource* source);
269
270 // Check old / new image file validity, comparing against expected size and
271 // CRC32. Return true if file matches expectations, false otherwise.
272 bool CheckOldFile(ConstBufferView old_image) const;
273 bool CheckNewFile(ConstBufferView new_image) const;
274
275 const PatchHeader& header() const { return header_; }
Samuel Huang06f1ae92018-03-13 18:19:34 +0000276 const std::vector<PatchElementReader>& elements() const { return elements_; }
277
278 private:
279 PatchHeader header_;
Samuel Huang06f1ae92018-03-13 18:19:34 +0000280 std::vector<PatchElementReader> elements_;
281};
282
283} // namespace zucchini
284
285#endif // COMPONENTS_ZUCCHINI_PATCH_READER_H_