am dc61d17d: am 50c17f9d: Merge "GOOGLEGMS-749 Fix integer overflow while applying block based OTA package"

* commit 'dc61d17d5b3c9e85a2863ec461170263325f1466':
  GOOGLEGMS-749 Fix integer overflow while applying block based OTA package
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
old mode 100644
new mode 100755
index 3a07da4..d5c8bb1
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -56,9 +56,9 @@
 #define STASH_FILE_MODE 0600
 
 typedef struct {
-    int count;
-    int size;
-    int pos[0];
+    size_t count;
+    size_t size;
+    size_t pos[0];  // Actual limit is INT_MAX.
 } RangeSet;
 
 #define RANGESET_MAX_POINTS \
@@ -82,16 +82,17 @@
         goto err;
     }
 
+    errno = 0;
     val = strtol(token, NULL, 0);
 
-    if (val < 2 || val > RANGESET_MAX_POINTS) {
+    if (errno != 0 || val < 2 || val > RANGESET_MAX_POINTS) {
         goto err;
     } else if (val % 2) {
         goto err; // must be even
     }
 
     num = (int) val;
-    bufsize = sizeof(RangeSet) + num * sizeof(int);
+    bufsize = sizeof(RangeSet) + num * sizeof(size_t);
 
     out = reinterpret_cast<RangeSet*>(malloc(bufsize));
 
@@ -103,41 +104,50 @@
     out->count = num / 2;
     out->size = 0;
 
-    for (int i = 0; i < num; ++i) {
+    for (int i = 0; i < num; i += 2) {
         token = strtok_r(NULL, ",", &save);
 
         if (!token) {
             goto err;
         }
 
+        errno = 0;
         val = strtol(token, NULL, 0);
 
-        if (val < 0 || val > INT_MAX) {
+        if (errno != 0 || val < 0 || val > INT_MAX) {
             goto err;
         }
 
-        out->pos[i] = (int) val;
+        out->pos[i] = static_cast<size_t>(val);
 
-        if (i % 2) {
-            if (out->pos[i - 1] >= out->pos[i]) {
-                goto err; // empty or negative range
-            }
+        token = strtok_r(NULL, ",", &save);
 
-            if (out->size > INT_MAX - out->pos[i]) {
-                goto err; // overflow
-            }
-
-            out->size += out->pos[i];
-        } else {
-            if (out->size < 0) {
-                goto err;
-            }
-
-            out->size -= out->pos[i];
+        if (!token) {
+            goto err;
         }
+
+        errno = 0;
+        val = strtol(token, NULL, 0);
+
+        if (errno != 0 || val < 0 || val > INT_MAX) {
+            goto err;
+        }
+
+        out->pos[i+1] = static_cast<size_t>(val);
+
+        if (out->pos[i] >= out->pos[i+1]) {
+            goto err; // empty or negative range
+        }
+
+        size_t rs = out->pos[i+1] - out->pos[i];
+        if (out->size > SIZE_MAX - rs) {
+            goto err; // overflow
+        }
+
+        out->size += rs;
     }
 
-    if (out->size <= 0) {
+    if (out->size == 0) {
         goto err;
     }
 
@@ -149,13 +159,13 @@
 }
 
 static bool range_overlaps(const RangeSet& r1, const RangeSet& r2) {
-    for (int i = 0; i < r1.count; ++i) {
-        int r1_0 = r1.pos[i * 2];
-        int r1_1 = r1.pos[i * 2 + 1];
+    for (size_t i = 0; i < r1.count; ++i) {
+        size_t r1_0 = r1.pos[i * 2];
+        size_t r1_1 = r1.pos[i * 2 + 1];
 
-        for (int j = 0; j < r2.count; ++j) {
-            int r2_0 = r2.pos[j * 2];
-            int r2_1 = r2.pos[j * 2 + 1];
+        for (size_t j = 0; j < r2.count; ++j) {
+            size_t r2_0 = r2.pos[j * 2];
+            size_t r2_1 = r2.pos[j * 2 + 1];
 
             if (!(r2_0 >= r1_1 || r1_0 >= r2_1)) {
                 return true;
@@ -219,7 +229,7 @@
 typedef struct {
     int fd;
     RangeSet* tgt;
-    int p_block;
+    size_t p_block;
     size_t p_remain;
 } RangeSinkState;
 
@@ -340,20 +350,18 @@
 }
 
 static int ReadBlocks(RangeSet* src, uint8_t* buffer, int fd) {
-    int i;
     size_t p = 0;
-    size_t size;
 
     if (!src || !buffer) {
         return -1;
     }
 
-    for (i = 0; i < src->count; ++i) {
+    for (size_t i = 0; i < src->count; ++i) {
         if (!check_lseek(fd, (off64_t) src->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
             return -1;
         }
 
-        size = (src->pos[i * 2 + 1] - src->pos[i * 2]) * BLOCKSIZE;
+        size_t size = (src->pos[i * 2 + 1] - src->pos[i * 2]) * BLOCKSIZE;
 
         if (read_all(fd, buffer + p, size) == -1) {
             return -1;
@@ -366,20 +374,18 @@
 }
 
 static int WriteBlocks(RangeSet* tgt, uint8_t* buffer, int fd) {
-    int i;
     size_t p = 0;
-    size_t size;
 
     if (!tgt || !buffer) {
         return -1;
     }
 
-    for (i = 0; i < tgt->count; ++i) {
+    for (size_t i = 0; i < tgt->count; ++i) {
         if (!check_lseek(fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
             return -1;
         }
 
-        size = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * BLOCKSIZE;
+        size_t size = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * BLOCKSIZE;
 
         if (write_all(fd, buffer + p, size) == -1) {
             return -1;
@@ -1140,8 +1146,6 @@
 
 static int PerformCommandZero(CommandParameters* params) {
     char* range = NULL;
-    int i;
-    int j;
     int rc = -1;
     RangeSet* tgt = NULL;
 
@@ -1164,12 +1168,12 @@
     memset(params->buffer, 0, BLOCKSIZE);
 
     if (params->canwrite) {
-        for (i = 0; i < tgt->count; ++i) {
+        for (size_t i = 0; i < tgt->count; ++i) {
             if (!check_lseek(params->fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
                 goto pczout;
             }
 
-            for (j = tgt->pos[i * 2]; j < tgt->pos[i * 2 + 1]; ++j) {
+            for (size_t j = tgt->pos[i * 2]; j < tgt->pos[i * 2 + 1]; ++j) {
                 if (write_all(params->fd, params->buffer, BLOCKSIZE) == -1) {
                     goto pczout;
                 }
@@ -1359,7 +1363,6 @@
 
 static int PerformCommandErase(CommandParameters* params) {
     char* range = NULL;
-    int i;
     int rc = -1;
     RangeSet* tgt = NULL;
     struct stat st;
@@ -1395,7 +1398,7 @@
     if (params->canwrite) {
         fprintf(stderr, " erasing %d blocks\n", tgt->size);
 
-        for (i = 0; i < tgt->count; ++i) {
+        for (size_t i = 0; i < tgt->count; ++i) {
             // offset in bytes
             blocks[0] = tgt->pos[i * 2] * (uint64_t) BLOCKSIZE;
             // length in bytes
@@ -1852,15 +1855,14 @@
     SHA_CTX ctx;
     SHA_init(&ctx);
 
-    int i, j;
-    for (i = 0; i < rs->count; ++i) {
+    for (size_t i = 0; i < rs->count; ++i) {
         if (!check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET)) {
             ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data,
                 strerror(errno));
             goto done;
         }
 
-        for (j = rs->pos[i*2]; j < rs->pos[i*2+1]; ++j) {
+        for (size_t j = rs->pos[i*2]; j < rs->pos[i*2+1]; ++j) {
             if (read_all(fd, buffer, BLOCKSIZE) == -1) {
                 ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data,
                     strerror(errno));