update_engine: Delta generator should not read past old image size.
This fixes a problem that was introduced by CL:246670 and caused the
delta generator to fail when generating deltas from a source image
that's smaller than the target image.
The bug is fixed by ensuring that the reading and comparing of unused
blocks is not attempted for block indexes that exceed the size of the
old image. Instead, these blocks are assumed to be new and their content
packaged into the payload.
BUG=chromium:477876
TEST=Unit tests
TEST=delta_generator successfully applied to FSI version 2913.331.0
Change-Id: Icc3163cca25ebeaefe05c2ba852664b6f0504053
Reviewed-on: https://chromium-review.googlesource.com/270075
Trybot-Ready: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Alex Deymo <deymo@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
diff --git a/payload_generator/delta_diff_generator.cc b/payload_generator/delta_diff_generator.cc
index 3355c41..ff759f6 100644
--- a/payload_generator/delta_diff_generator.cc
+++ b/payload_generator/delta_diff_generator.cc
@@ -729,6 +729,7 @@
int blobs_fd,
off_t* blobs_length,
const string& old_image_path,
+ const uint64_t old_image_size,
const string& new_image_path,
Vertex* vertex,
uint32_t minor_version) {
@@ -798,9 +799,13 @@
TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
TEST_AND_RETURN_FALSE(static_cast<size_t>(rc) == count);
- rc = pread(old_image_fd, old_buf.data(), count, offset);
+ const off_t old_offset = min(offset, static_cast<off_t>(old_image_size));
+ const size_t old_count =
+ min(static_cast<size_t>(offset + count),
+ static_cast<size_t>(old_image_size)) - old_offset;
+ rc = pread(old_image_fd, old_buf.data(), old_count, old_offset);
TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
- TEST_AND_RETURN_FALSE(static_cast<size_t>(rc) == count);
+ TEST_AND_RETURN_FALSE(static_cast<size_t>(rc) == old_count);
// Compare each block in the buffer to its counterpart in the old image
// and only compress it if its content has changed.
@@ -808,6 +813,7 @@
for (int i = 0; i < copy_block_cnt; ++i) {
int buf_end_offset = buf_offset + kBlockSize;
if (minor_version == kSourceMinorPayloadVersion ||
+ static_cast<size_t>(buf_end_offset) > old_count ||
!std::equal(new_buf.begin() + buf_offset,
new_buf.begin() + buf_end_offset,
old_buf.begin() + buf_offset)) {
@@ -1046,6 +1052,7 @@
data_file_fd,
data_file_size,
config.source.rootfs_part,
+ config.source.rootfs_size,
config.target.rootfs_part,
&unwritten_vertex,
config.minor_version));
diff --git a/payload_generator/delta_diff_generator.h b/payload_generator/delta_diff_generator.h
index d34b9da..5aa506c 100644
--- a/payload_generator/delta_diff_generator.h
+++ b/payload_generator/delta_diff_generator.h
@@ -152,6 +152,7 @@
int blobs_fd,
off_t* blobs_length,
const std::string& old_image_path,
+ const uint64_t old_image_size,
const std::string& new_image_path,
Vertex* vertex,
uint32_t minor_version);
diff --git a/payload_generator/inplace_generator.cc b/payload_generator/inplace_generator.cc
index 869535c..febb5e6 100644
--- a/payload_generator/inplace_generator.cc
+++ b/payload_generator/inplace_generator.cc
@@ -722,6 +722,7 @@
data_file_fd,
data_file_size,
config.source.rootfs_part,
+ config.source.rootfs_size,
config.target.rootfs_part,
&graph.back(),
config.minor_version));