aboutsummaryrefslogtreecommitdiff
path: root/patch_reader.h
diff options
context:
space:
mode:
authorSamuel Huang <huangs@chromium.org>2018-03-13 18:19:34 +0000
committerEdward Lesmes <ehmaldonado@google.com>2021-07-23 21:50:59 +0000
commit06f1ae9aaca969ee95ef840f22b6b461c304542d (patch)
treef1e5c6624e70628e81fbf38d6cd14b974abe5d93 /patch_reader.h
downloadzucchini-06f1ae9aaca969ee95ef840f22b6b461c304542d.tar.gz
[Zucchini] Move Zucchini from /chrome/installer/ to /components/.
(Use "git log --follow" to see older revisions of files). /components/ is the most logical place to put Zucchini, which only depends on /base and /testing/gtest. This move also enables Zucchini to be used by the Component Updater. Details: - Move all files; run the following to change deps and guards: sed 's/chrome\/installer/components/' *.cc *.h -i sed 's/CHROME_INSTALLER/COMPONENTS/' *.cc *.h -i - Sorting works out pretty well! - Change all 'chrome/installer/zucchini' to 'components/zucchini' throughout other parts of the repo; sort if necessary. - Fix 6 'git cl lint' errors. - Change 1 Bind() usage to BindRepeated(). - Update OWNER. Bug: 729154 Change-Id: I50c5a7d411ea85f707b5994ab319dfb2a1acccf7 Reviewed-on: https://chromium-review.googlesource.com/954923 Reviewed-by: Greg Thompson <grt@chromium.org> Reviewed-by: Jochen Eisinger <jochen@chromium.org> Reviewed-by: Samuel Huang <huangs@chromium.org> Commit-Queue: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/master@{#542857} NOKEYCHECK=True GitOrigin-RevId: 577ef6c435e8d43be6e3e60ccbcbd1881780f4ec
Diffstat (limited to 'patch_reader.h')
-rw-r--r--patch_reader.h277
1 files changed, 277 insertions, 0 deletions
diff --git a/patch_reader.h b/patch_reader.h
new file mode 100644
index 0000000..ef6cd32
--- /dev/null
+++ b/patch_reader.h
@@ -0,0 +1,277 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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 <vector>
+
+#include "base/debug/stack_trace.h"
+#include "base/logging.h"
+#include "base/numerics/checked_math.h"
+#include "base/optional.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.
+ source->Skip(bytes_read);
+ return true;
+}
+
+// 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.
+ source->Skip(bytes_read);
+ return true;
+}
+
+} // 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).
+// - base::Optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and
+// returns the next item as base::Optional (returns base::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);
+ base::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.
+ base::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);
+ base::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);
+ base::Optional<int32_t> GetNext();
+ bool Done() const { return reference_delta_.empty(); }
+
+ // Accessors for unittest.
+ BufferSource reference_delta() const { return reference_delta_; }
+
+ private:
+ BufferSource reference_delta_;
+};
+
+// Source for additional targets.
+class TargetSource {
+ public:
+ TargetSource();
+ TargetSource(const TargetSource&);
+ ~TargetSource();
+
+ // Core functions.
+ bool Initialize(BufferSource* source);
+ base::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.
+ 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:
+ 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 base::nullopt.
+ static base::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_; }
+ PatchType patch_type() const { return patch_type_; }
+ const std::vector<PatchElementReader>& elements() const { return elements_; }
+
+ private:
+ PatchHeader header_;
+ PatchType patch_type_;
+ std::vector<PatchElementReader> elements_;
+};
+
+} // namespace zucchini
+
+#endif // COMPONENTS_ZUCCHINI_PATCH_READER_H_