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