Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8542502f authored by Tianjie Xu's avatar Tianjie Xu Committed by android-build-merger
Browse files

Merge "Fix a rare failure for imgdiff when random data equals gzip header"

am: b87a166a

Change-Id: Ic3c7d102cc7a2b992c699add012076a4bda549c6
parents c24d97fa b87a166a
Loading
Loading
Loading
Loading
+14 −11
Original line number Diff line number Diff line
@@ -693,6 +693,20 @@ static bool ReadImage(const char* filename, std::vector<ImageChunk>* chunks,
        continue;
      }

      // The footer contains the size of the uncompressed data.  Double-check to make sure that it
      // matches the size of the data we got when we actually did the decompression.
      size_t footer_index = pos + raw_data_len + GZIP_FOOTER_LEN - 4;
      if (sz - footer_index < 4) {
        printf("Warning: invalid footer position; treating as a nomal chunk\n");
        continue;
      }
      size_t footer_size = get_unaligned<uint32_t>(img->data() + footer_index);
      if (footer_size != uncompressed_len) {
        printf("Warning: footer size %zu != decompressed size %zu; treating as a nomal chunk\n",
               footer_size, uncompressed_len);
        continue;
      }

      ImageChunk body(CHUNK_DEFLATE, pos, img, raw_data_len);
      uncompressed_data.resize(uncompressed_len);
      body.SetUncompressedData(std::move(uncompressed_data));
@@ -704,17 +718,6 @@ static bool ReadImage(const char* filename, std::vector<ImageChunk>* chunks,
      chunks->emplace_back(CHUNK_NORMAL, pos, img, GZIP_FOOTER_LEN);

      pos += GZIP_FOOTER_LEN;

      // The footer (that we just skipped over) contains the size of
      // the uncompressed data.  Double-check to make sure that it
      // matches the size of the data we got when we actually did
      // the decompression.
      size_t footer_size = get_unaligned<uint32_t>(img->data() + pos - 4);
      if (footer_size != body.DataLengthForPatch()) {
        printf("Error: footer size %zu != decompressed size %zu\n", footer_size,
               body.GetRawDataLength());
        return false;
      }
    } else {
      // Use a normal chunk to take all the contents until the next gzip chunk (or EOF); we expect
      // the number of chunks to be small (5 for typical boot and recovery images).
+33 −0
Original line number Diff line number Diff line
@@ -328,6 +328,39 @@ TEST(ImgdiffTest, image_mode_simple) {
  verify_patched_image(src, patch, tgt);
}

TEST(ImgdiffTest, image_mode_bad_gzip) {
  // Modify the uncompressed length in the gzip footer.
  const std::vector<char> src_data = { 'a',    'b',    'c',    'd',    'e',    'f',    'g',
                                       'h',    '\x1f', '\x8b', '\x08', '\x00', '\xc4', '\x1e',
                                       '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xac',
                                       '\x02', '\x00', '\x67', '\xba', '\x8e', '\xeb', '\x03',
                                       '\xff', '\xff', '\xff' };
  const std::string src(src_data.cbegin(), src_data.cend());
  TemporaryFile src_file;
  ASSERT_TRUE(android::base::WriteStringToFile(src, src_file.path));

  // Modify the uncompressed length in the gzip footer.
  const std::vector<char> tgt_data = {
    'a',    'b',    'c',    'd',    'e',    'f',    'g',    'x',    'y',    'z',    '\x1f', '\x8b',
    '\x08', '\x00', '\x62', '\x1f', '\x53', '\x58', '\x00', '\x03', '\xab', '\xa8', '\xa8', '\xac',
    '\xac', '\xaa', '\x02', '\x00', '\x96', '\x30', '\x06', '\xb7', '\x06', '\xff', '\xff', '\xff'
  };
  const std::string tgt(tgt_data.cbegin(), tgt_data.cend());
  TemporaryFile tgt_file;
  ASSERT_TRUE(android::base::WriteStringToFile(tgt, tgt_file.path));

  TemporaryFile patch_file;
  std::vector<const char*> args = {
    "imgdiff", src_file.path, tgt_file.path, patch_file.path,
  };
  ASSERT_EQ(0, imgdiff(args.size(), args.data()));

  // Verify.
  std::string patch;
  ASSERT_TRUE(android::base::ReadFileToString(patch_file.path, &patch));
  verify_patched_image(src, patch, tgt);
}

TEST(ImgdiffTest, image_mode_different_num_chunks) {
  // src: "abcdefgh" + gzipped "xyz" (echo -n "xyz" | gzip -f | hd) + gzipped "test".
  const std::vector<char> src_data = {