summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/component/updater_test.cpp42
-rw-r--r--updater/blockimg.cpp5
2 files changed, 46 insertions, 1 deletions
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 24c63e776..c611c2291 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -664,6 +664,48 @@ TEST_F(UpdaterTest, block_image_update_patch_data) {
ASSERT_EQ(tgt_content, updated_content);
}
+TEST_F(UpdaterTest, block_image_update_patch_underrun) {
+ std::string src_content = std::string(4096, 'a') + std::string(4096, 'c');
+ std::string tgt_content = std::string(4096, 'b') + std::string(4096, 'd');
+
+ // Generate the patch data. We intentionally provide one-byte short target to trigger the underrun
+ // path.
+ TemporaryFile patch_file;
+ ASSERT_EQ(0,
+ bsdiff::bsdiff(reinterpret_cast<const uint8_t*>(src_content.data()), src_content.size(),
+ reinterpret_cast<const uint8_t*>(tgt_content.data()),
+ tgt_content.size() - 1, patch_file.path, nullptr));
+ std::string patch_content;
+ ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch_content));
+
+ // Create the transfer list that contains a bsdiff.
+ std::string src_hash = get_sha1(src_content);
+ std::string tgt_hash = get_sha1(tgt_content);
+ std::vector<std::string> transfer_list{
+ // clang-format off
+ "4",
+ "2",
+ "0",
+ "2",
+ "stash " + src_hash + " 2,0,2",
+ android::base::StringPrintf("bsdiff 0 %zu %s %s 2,0,2 2 - %s:2,0,2", patch_content.size(),
+ src_hash.c_str(), tgt_hash.c_str(), src_hash.c_str()),
+ "free " + src_hash,
+ // clang-format on
+ };
+
+ PackageEntries entries{
+ { "new_data", "" },
+ { "patch_data", patch_content },
+ { "transfer_list", android::base::Join(transfer_list, '\n') },
+ };
+
+ ASSERT_TRUE(android::base::WriteStringToFile(src_content, image_file_));
+
+ // The update should fail due to underrun.
+ RunBlockImageUpdate(false, entries, image_file_, "", kPatchApplicationFailure);
+}
+
TEST_F(UpdaterTest, block_image_update_fail) {
std::string src_content(4096 * 2, 'e');
std::string src_hash = get_sha1(src_content);
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 47849a155..c4c09098e 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1399,7 +1399,10 @@ static int PerformCommandDiff(CommandParameters& params) {
// We expect the output of the patcher to fill the tgt ranges exactly.
if (!writer.Finished()) {
- LOG(ERROR) << "range sink underrun?";
+ LOG(ERROR) << "Failed to fully write target blocks (range sink underrun): Missing "
+ << writer.AvailableSpace() << " bytes";
+ failure_type = kPatchApplicationFailure;
+ return -1;
}
} else {
LOG(INFO) << "skipping " << blocks << " blocks already patched to " << tgt.blocks() << " ["