summaryrefslogtreecommitdiffstats
path: root/updater/blockimg.cpp
diff options
context:
space:
mode:
authorTao Bao <tbao@google.com>2015-08-26 02:57:42 +0200
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-08-26 02:57:42 +0200
commit50c17f9da69ed3de0cd3ed032c50af067c1dc1f1 (patch)
treefb5c91291a7b453063e642d5ff08230101456dd5 /updater/blockimg.cpp
parentMerge "edify: Switch to C++." (diff)
parentGOOGLEGMS-749 Fix integer overflow while applying block based OTA package (diff)
downloadandroid_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar.gz
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar.bz2
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar.lz
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar.xz
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.tar.zst
android_bootable_recovery-50c17f9da69ed3de0cd3ed032c50af067c1dc1f1.zip
Diffstat (limited to 'updater/blockimg.cpp')
-rwxr-xr-x[-rw-r--r--]updater/blockimg.cpp94
1 files changed, 48 insertions, 46 deletions
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 3a07da404..d5c8bb195 100644..100755
--- 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 @@ static RangeSet* parse_range(char* text) {
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 @@ static RangeSet* parse_range(char* text) {
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
- }
+ if (!token) {
+ goto err;
+ }
- out->size += out->pos[i];
- } else {
- if (out->size < 0) {
- goto err;
- }
+ errno = 0;
+ val = strtol(token, NULL, 0);
- out->size -= out->pos[i];
+ 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 @@ err:
}
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 @@ static void allocate(size_t size, uint8_t** buffer, size_t* buffer_alloc) {
typedef struct {
int fd;
RangeSet* tgt;
- int p_block;
+ size_t p_block;
size_t p_remain;
} RangeSinkState;
@@ -340,20 +350,18 @@ static void* unzip_new_data(void* cookie) {
}
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 ReadBlocks(RangeSet* src, uint8_t* buffer, int fd) {
}
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 PerformCommandFree(CommandParameters* params) {
static int PerformCommandZero(CommandParameters* params) {
char* range = NULL;
- int i;
- int j;
int rc = -1;
RangeSet* tgt = NULL;
@@ -1164,12 +1168,12 @@ static int PerformCommandZero(CommandParameters* params) {
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 @@ pcdout:
static int PerformCommandErase(CommandParameters* params) {
char* range = NULL;
- int i;
int rc = -1;
RangeSet* tgt = NULL;
struct stat st;
@@ -1395,7 +1398,7 @@ static int PerformCommandErase(CommandParameters* params) {
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 @@ Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) {
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));