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 #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 <optional>
13 #include <vector>
14 
15 #include "base/debug/stack_trace.h"
16 #include "base/logging.h"
17 #include "base/numerics/checked_math.h"
18 #include "components/zucchini/buffer_source.h"
19 #include "components/zucchini/buffer_view.h"
20 #include "components/zucchini/image_utils.h"
21 #include "components/zucchini/patch_utils.h"
22 
23 namespace zucchini {
24 
25 namespace 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.
33 bool ParseElementMatch(BufferSource* source, ElementMatch* element_match);
34 
35 // Parses |source| for the next embedded BufferSource.
36 bool ParseBuffer(BufferSource* source, BufferSource* buffer);
37 
38 // Parses |source| for the next VarUInt.
39 template <class T>
ParseVarUInt(BufferSource * source,T * value)40 bool 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.
53 template <class T>
ParseVarInt(BufferSource * source,T * value)54 bool 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).
80 // - std::optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and
81 //   returns the next item as std::optional (returns std::nullopt on failure).
82 // - 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.
89 class EquivalenceSource {
90  public:
91   EquivalenceSource();
92   EquivalenceSource(const EquivalenceSource&);
93   ~EquivalenceSource();
94 
95   // Core functions.
96   bool Initialize(BufferSource* source);
97   std::optional<Equivalence> GetNext();
Done()98   bool Done() const {
99     return src_skip_.empty() && dst_skip_.empty() && copy_count_.empty();
100   }
101 
102   // Accessors for unittest.
src_skip()103   BufferSource src_skip() const { return src_skip_; }
dst_skip()104   BufferSource dst_skip() const { return dst_skip_; }
copy_count()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.
117 class 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.
126   std::optional<ConstBufferView> GetNext(offset_t size);
Done()127   bool Done() const { return extra_data_.empty(); }
128 
129   // Accessors for unittest.
extra_data()130   BufferSource extra_data() const { return extra_data_; }
131 
132  private:
133   BufferSource extra_data_;
134 };
135 
136 // Source for raw delta.
137 class RawDeltaSource {
138  public:
139   RawDeltaSource();
140   RawDeltaSource(const RawDeltaSource&);
141   ~RawDeltaSource();
142 
143   // Core functions.
144   bool Initialize(BufferSource* source);
145   std::optional<RawDeltaUnit> GetNext();
Done()146   bool Done() const {
147     return raw_delta_skip_.empty() && raw_delta_diff_.empty();
148   }
149 
150   // Accessors for unittest.
raw_delta_skip()151   BufferSource raw_delta_skip() const { return raw_delta_skip_; }
raw_delta_diff()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.
162 class ReferenceDeltaSource {
163  public:
164   ReferenceDeltaSource();
165   ReferenceDeltaSource(const ReferenceDeltaSource&);
166   ~ReferenceDeltaSource();
167 
168   // Core functions.
169   bool Initialize(BufferSource* source);
170   std::optional<int32_t> GetNext();
Done()171   bool Done() const { return source_.empty(); }
172 
173   // Accessors for unittest.
reference_delta()174   BufferSource reference_delta() const { return source_; }
175 
176  private:
177   BufferSource source_;
178 };
179 
180 // Source for additional targets.
181 class TargetSource {
182  public:
183   TargetSource();
184   TargetSource(const TargetSource&);
185   ~TargetSource();
186 
187   // Core functions.
188   bool Initialize(BufferSource* source);
189   std::optional<offset_t> GetNext();
Done()190   bool Done() const { return extra_targets_.empty(); }
191 
192   // Accessors for unittest.
extra_targets()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.
207 class 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 
element_match()217   const ElementMatch& element_match() const { return element_match_; }
old_element()218   const Element& old_element() const { return element_match_.old_element; }
new_element()219   const Element& new_element() const { return element_match_.new_element; }
220 
221   // 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.
GetEquivalenceSource()226   EquivalenceSource GetEquivalenceSource() const { return equivalences_; }
GetExtraDataSource()227   ExtraDataSource GetExtraDataSource() const { return extra_data_; }
GetRawDeltaSource()228   RawDeltaSource GetRawDeltaSource() const { return raw_delta_; }
GetReferenceDeltaSource()229   ReferenceDeltaSource GetReferenceDeltaSource() const {
230     return reference_delta_;
231   }
GetExtraTargetSource(PoolTag tag)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:
238   // Checks that "old" and "new" blocks of each item in |equivalences_| satisfy
239   // 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();
243 
244   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.
256 class EnsemblePatchReader {
257  public:
258   // If data read from |buffer| is well-formed, initializes and returns
259   // an instance of EnsemblePatchReader. Otherwise returns std::nullopt.
260   static std::optional<EnsemblePatchReader> Create(ConstBufferView buffer);
261 
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 
header()275   const PatchHeader& header() const { return header_; }
elements()276   const std::vector<PatchElementReader>& elements() const { return elements_; }
277 
278  private:
279   PatchHeader header_;
280   std::vector<PatchElementReader> elements_;
281 };
282 
283 }  // namespace zucchini
284 
285 #endif  // COMPONENTS_ZUCCHINI_PATCH_READER_H_
286