libsparse: Fix overflow of merged sparse chunk length

Merging sparse chunk can make sparse map block bigger than 4GiB,
that can't be covered by unsigned integer type. Fix this by
changing unsigned int to uint64_t type.

Test: sparse build
Bug: 162808120
Change-Id: Id4d3f88f9d531c25c3937c99b2c81efb915605ee
Signed-off-by: Hyeongseok Kim <hyeongseok@gmail.com>
Cc: hyeongseok.kim <hyeongseok.kim@lge.com>
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index b883c13..b2c5407 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -65,9 +65,9 @@
 };
 
 struct sparse_file_ops {
-  int (*write_data_chunk)(struct output_file* out, unsigned int len, void* data);
-  int (*write_fill_chunk)(struct output_file* out, unsigned int len, uint32_t fill_val);
-  int (*write_skip_chunk)(struct output_file* out, int64_t len);
+  int (*write_data_chunk)(struct output_file* out, uint64_t len, void* data);
+  int (*write_fill_chunk)(struct output_file* out, uint64_t len, uint32_t fill_val);
+  int (*write_skip_chunk)(struct output_file* out, uint64_t len);
   int (*write_end_chunk)(struct output_file* out);
 };
 
@@ -316,7 +316,7 @@
   return 0;
 }
 
-static int write_sparse_skip_chunk(struct output_file* out, int64_t skip_len) {
+static int write_sparse_skip_chunk(struct output_file* out, uint64_t skip_len) {
   chunk_header_t chunk_header;
   int ret;
 
@@ -340,9 +340,10 @@
   return 0;
 }
 
-static int write_sparse_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
+static int write_sparse_fill_chunk(struct output_file* out, uint64_t len, uint32_t fill_val) {
   chunk_header_t chunk_header;
-  int rnd_up_len, count;
+  uint64_t rnd_up_len;
+  int count;
   int ret;
 
   /* Round up the fill length to a multiple of the block size */
@@ -370,9 +371,9 @@
   return 0;
 }
 
-static int write_sparse_data_chunk(struct output_file* out, unsigned int len, void* data) {
+static int write_sparse_data_chunk(struct output_file* out, uint64_t len, void* data) {
   chunk_header_t chunk_header;
-  int rnd_up_len, zero_len;
+  uint64_t rnd_up_len, zero_len;
   int ret;
 
   /* Round up the data length to a multiple of the block size */
@@ -437,9 +438,9 @@
     .write_end_chunk = write_sparse_end_chunk,
 };
 
-static int write_normal_data_chunk(struct output_file* out, unsigned int len, void* data) {
+static int write_normal_data_chunk(struct output_file* out, uint64_t len, void* data) {
   int ret;
-  unsigned int rnd_up_len = ALIGN(len, out->block_size);
+  uint64_t rnd_up_len = ALIGN(len, out->block_size);
 
   ret = out->ops->write(out, data, len);
   if (ret < 0) {
@@ -453,10 +454,10 @@
   return ret;
 }
 
-static int write_normal_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
+static int write_normal_fill_chunk(struct output_file* out, uint64_t len, uint32_t fill_val) {
   int ret;
   unsigned int i;
-  unsigned int write_len;
+  uint64_t write_len;
 
   /* Initialize fill_buf with the fill_val */
   for (i = 0; i < out->block_size / sizeof(uint32_t); i++) {
@@ -464,7 +465,7 @@
   }
 
   while (len) {
-    write_len = std::min(len, out->block_size);
+    write_len = std::min(len, (uint64_t)out->block_size);
     ret = out->ops->write(out, out->fill_buf, write_len);
     if (ret < 0) {
       return ret;
@@ -476,7 +477,7 @@
   return 0;
 }
 
-static int write_normal_skip_chunk(struct output_file* out, int64_t len) {
+static int write_normal_skip_chunk(struct output_file* out, uint64_t len) {
   return out->ops->skip(out, len);
 }
 
@@ -639,16 +640,16 @@
 }
 
 /* Write a contiguous region of data blocks from a memory buffer */
-int write_data_chunk(struct output_file* out, unsigned int len, void* data) {
+int write_data_chunk(struct output_file* out, uint64_t len, void* data) {
   return out->sparse_ops->write_data_chunk(out, len, data);
 }
 
 /* Write a contiguous region of data blocks with a fill value */
-int write_fill_chunk(struct output_file* out, unsigned int len, uint32_t fill_val) {
+int write_fill_chunk(struct output_file* out, uint64_t len, uint32_t fill_val) {
   return out->sparse_ops->write_fill_chunk(out, len, fill_val);
 }
 
-int write_fd_chunk(struct output_file* out, unsigned int len, int fd, int64_t offset) {
+int write_fd_chunk(struct output_file* out, uint64_t len, int fd, int64_t offset) {
   auto m = android::base::MappedFile::FromFd(fd, offset, len, PROT_READ);
   if (!m) return -errno;
 
@@ -656,7 +657,7 @@
 }
 
 /* Write a contiguous region of data blocks from a file */
-int write_file_chunk(struct output_file* out, unsigned int len, const char* file, int64_t offset) {
+int write_file_chunk(struct output_file* out, uint64_t len, const char* file, int64_t offset) {
   int ret;
 
   int file_fd = open(file, O_RDONLY | O_BINARY);
@@ -671,6 +672,6 @@
   return ret;
 }
 
-int write_skip_chunk(struct output_file* out, int64_t len) {
+int write_skip_chunk(struct output_file* out, uint64_t len) {
   return out->sparse_ops->write_skip_chunk(out, len);
 }