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:
committed by
Rom Lemarchand
parent
56deefba73
commit
806f72f9e6
+71
-10
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user