Add checking for sparse file format

Sparse file can come from an untrusted source.
Need more checking to ensure that it is not a malformed
file and would not cause any OOB read access.

Update fuzz test for decoding also.

Test: adb reboot fastboot
      fuzzy_fastboot --gtest_filter=Fuzz.Sparse*
      fuzzy_fastboot --gtest_filter=Conformance.Sparse*
      sparse_fuzzer
Bug: 212705418
Change-Id: I7622df307bb00e59faaba8bb2c67cb474cffed8e
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 7bef72a..44dc81f 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -119,9 +119,11 @@
 }
 
 int FlashSparseData(int fd, std::vector<char>& downloaded_data) {
-    struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(), true, false);
+    struct sparse_file* file = sparse_file_import_buf(downloaded_data.data(),
+                                                      downloaded_data.size(), true, false);
     if (!file) {
-        return -ENOENT;
+        // Invalid sparse format
+        return -EINVAL;
     }
     return sparse_file_callback(file, false, false, WriteCallback, reinterpret_cast<void*>(fd));
 }
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 8593adc..055a047 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -977,6 +977,63 @@
     }
 }
 
+TEST_F(Fuzz, SparseZeroBlkSize) {
+    // handcrafted malform sparse file with zero as block size
+    const std::vector<char> buf = {
+        '\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
+        '\x00', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x00', '\x00', '\x00', '\x00', '\xc2', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'
+    };
+
+    ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
+    ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
+
+    // It can either reject this download or reject it during flash
+    if (HandleResponse() != DEVICE_FAIL) {
+        EXPECT_EQ(fb->Flash("userdata"), DEVICE_FAIL)
+                << "Flashing a zero block size in sparse file should fail";
+    }
+}
+
+TEST_F(Fuzz, SparseTrimmed) {
+    // handcrafted malform sparse file which is trimmed
+    const std::vector<char> buf = {
+        '\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
+        '\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x00', '\x00', '\x00', '\x80', '\x11', '\x22', '\x33', '\x44'
+    };
+
+    ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
+    ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
+
+    // It can either reject this download or reject it during flash
+    if (HandleResponse() != DEVICE_FAIL) {
+        EXPECT_EQ(fb->Flash("userdata"), DEVICE_FAIL)
+                << "Flashing a trimmed sparse file should fail";
+    }
+}
+
+TEST_F(Fuzz, SparseInvalidChurk) {
+    // handcrafted malform sparse file with invalid churk
+    const std::vector<char> buf = {
+        '\x3a', '\xff', '\x26', '\xed', '\x01', '\x00', '\x00', '\x00', '\x1c', '\x00', '\x0c', '\x00',
+        '\x00', '\x10', '\x00', '\x00', '\x00', '\x00', '\x08', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x00', '\x00', '\x00', '\x00', '\xc1', '\xca', '\x00', '\x00', '\x01', '\x00', '\x00', '\x00',
+        '\x10', '\x00', '\x00', '\x00', '\x11', '\x22', '\x33', '\x44'
+    };
+
+    ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
+    ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
+
+    // It can either reject this download or reject it during flash
+    if (HandleResponse() != DEVICE_FAIL) {
+        EXPECT_EQ(fb->Flash("userdata"), DEVICE_FAIL)
+                << "Flashing a sparse file with invalid churk should fail";
+    }
+}
+
 TEST_F(Fuzz, SparseTooManyChunks) {
     SparseWrapper sparse(4096, 4096);  // 1 block, but we send two chunks that will use 2 blocks
     ASSERT_TRUE(*sparse) << "Sparse image creation failed";