app: aboot: Fix download userdata.img fail
The userdata.img can't be download due to overflow of int32.
The chunk in userdata.img might be bigger than 4GB in some
case.
Change-Id: Id54196b59d168cf2789d756354231c75cf2abb36
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 3daaef5..639a42e 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -2251,10 +2251,9 @@
void cmd_flash_mmc_sparse_img(const char *arg, void *data, unsigned sz)
{
unsigned int chunk;
- unsigned int chunk_data_sz;
+ uint64_t chunk_data_sz;
uint32_t *fill_buf = NULL;
uint32_t fill_val;
- uint32_t chunk_blk_cnt = 0;
sparse_header_t *sparse_header;
chunk_header_t *chunk_header;
uint32_t total_blocks = 0;
@@ -2342,15 +2341,13 @@
return;
}
- chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
-
- /* Make sure multiplication does not overflow uint32 size */
- if (sparse_header->blk_sz && (chunk_header->chunk_sz != chunk_data_sz / sparse_header->blk_sz))
- {
- fastboot_fail("Bogus size sparse and chunk header");
+ if (!sparse_header->blk_sz ){
+ fastboot_fail("Invalid block size\n");
return;
}
+ chunk_data_sz = (uint64_t)sparse_header->blk_sz * chunk_header->chunk_sz;
+
/* Make sure that the chunk size calculated from sparse image does not
* exceed partition size
*/
@@ -2363,7 +2360,7 @@
switch (chunk_header->chunk_type)
{
case CHUNK_TYPE_RAW:
- if(chunk_header->total_sz != (sparse_header->chunk_hdr_sz +
+ if((uint64_t)chunk_header->total_sz != ((uint64_t)sparse_header->chunk_hdr_sz +
chunk_data_sz))
{
fastboot_fail("Bogus chunk size for chunk type Raw");
@@ -2375,8 +2372,11 @@
return;
}
+ /* chunk_header->total_sz is uint32,So chunk_data_sz is now less than 2^32
+ otherwise it will return in the line above
+ */
if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
- chunk_data_sz,
+ (uint32_t)chunk_data_sz,
(unsigned int*)data))
{
fastboot_fail("flash write failure");
@@ -2387,7 +2387,7 @@
return;
}
total_blocks += chunk_header->chunk_sz;
- data += chunk_data_sz;
+ data += (uint32_t)chunk_data_sz;
break;
case CHUNK_TYPE_FILL:
@@ -2411,14 +2411,13 @@
}
fill_val = *(uint32_t *)data;
data = (char *) data + sizeof(uint32_t);
- chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
for (i = 0; i < (sparse_header->blk_sz / sizeof(fill_val)); i++)
{
fill_buf[i] = fill_val;
}
- for (i = 0; i < chunk_blk_cnt; i++)
+ for (i = 0; i < chunk_header->chunk_sz; i++)
{
/* Make sure that the data written to partition does not exceed partition size */
if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + sparse_header->blk_sz > size)
@@ -2453,7 +2452,7 @@
case CHUNK_TYPE_CRC:
if(chunk_header->total_sz != sparse_header->chunk_hdr_sz)
{
- fastboot_fail("Bogus chunk size for chunk type Dont Care");
+ fastboot_fail("Bogus chunk size for chunk type CRC");
return;
}
if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
@@ -2465,7 +2464,7 @@
fastboot_fail("integer overflow occured");
return;
}
- data += chunk_data_sz;
+ data += (uint32_t)chunk_data_sz;
if (data_end < (uint32_t)data) {
fastboot_fail("buffer overreads occured due to invalid sparse header");
return;