Add error and range checks to parse_range

Only trusted input is passed to parse_range, but check for invalid
input to catch possible problems in transfer lists.

Bug: 21033983
Bug: 21034030
Bug: 21034172
Bug: 21034406
Change-Id: I1e266de3de15c99ee596ebdb034419fdfe7eba1f
(cherry picked from commit f2bac04e1b)
This commit is contained in:
Sami Tolvanen
2015-05-12 12:48:46 +01:00
committed by Rom Lemarchand
parent 56deefba73
commit 806f72f9e6
+71 -10
View File
@@ -61,30 +61,91 @@ typedef struct {
int pos[0];
} RangeSet;
#define RANGESET_MAX_POINTS \
((int)((INT_MAX / sizeof(int)) - sizeof(RangeSet)))
static RangeSet* parse_range(char* text) {
char* save;
int num;
num = strtol(strtok_r(text, ",", &save), NULL, 0);
char* token;
int i, num;
long int val;
RangeSet* out = NULL;
size_t bufsize;
RangeSet* out = malloc(sizeof(RangeSet) + num * sizeof(int));
if (out == NULL) {
fprintf(stderr, "failed to allocate range of %zu bytes\n",
sizeof(RangeSet) + num * sizeof(int));
exit(1);
if (!text) {
goto err;
}
token = strtok_r(text, ",", &save);
if (!token) {
goto err;
}
val = strtol(token, NULL, 0);
if (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);
out = malloc(bufsize);
if (!out) {
fprintf(stderr, "failed to allocate range of %zu bytes\n", bufsize);
goto err;
}
out->count = num / 2;
out->size = 0;
int i;
for (i = 0; i < num; ++i) {
out->pos[i] = strtol(strtok_r(NULL, ",", &save), NULL, 0);
if (i%2) {
token = strtok_r(NULL, ",", &save);
if (!token) {
goto err;
}
val = strtol(token, NULL, 0);
if (val < 0 || val > INT_MAX) {
goto err;
}
out->pos[i] = (int) val;
if (i % 2) {
if (out->pos[i - 1] >= out->pos[i]) {
goto err; // empty or negative range
}
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 (out->size <= 0) {
goto err;
}
return out;
err:
fprintf(stderr, "failed to parse range '%s'\n", text ? text : "NULL");
exit(1);
}
static int range_overlaps(RangeSet* r1, RangeSet* r2) {