Merge "Add error and range checks to parse_range"
This commit is contained in:
+71
-10
@@ -60,30 +60,91 @@ typedef struct {
|
|||||||
int pos[0];
|
int pos[0];
|
||||||
} RangeSet;
|
} RangeSet;
|
||||||
|
|
||||||
|
#define RANGESET_MAX_POINTS \
|
||||||
|
((int)((INT_MAX / sizeof(int)) - sizeof(RangeSet)))
|
||||||
|
|
||||||
static RangeSet* parse_range(char* text) {
|
static RangeSet* parse_range(char* text) {
|
||||||
char* save;
|
char* save;
|
||||||
int num;
|
char* token;
|
||||||
num = strtol(strtok_r(text, ",", &save), NULL, 0);
|
int i, num;
|
||||||
|
long int val;
|
||||||
|
RangeSet* out = NULL;
|
||||||
|
size_t bufsize;
|
||||||
|
|
||||||
RangeSet* out = malloc(sizeof(RangeSet) + num * sizeof(int));
|
if (!text) {
|
||||||
if (out == NULL) {
|
goto err;
|
||||||
fprintf(stderr, "failed to allocate range of %zu bytes\n",
|
|
||||||
sizeof(RangeSet) + num * sizeof(int));
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->count = num / 2;
|
||||||
out->size = 0;
|
out->size = 0;
|
||||||
int i;
|
|
||||||
for (i = 0; i < num; ++i) {
|
for (i = 0; i < num; ++i) {
|
||||||
out->pos[i] = strtol(strtok_r(NULL, ",", &save), NULL, 0);
|
token = strtok_r(NULL, ",", &save);
|
||||||
if (i%2) {
|
|
||||||
|
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];
|
out->size += out->pos[i];
|
||||||
} else {
|
} else {
|
||||||
|
if (out->size < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
out->size -= out->pos[i];
|
out->size -= out->pos[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (out->size <= 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
err:
|
||||||
|
fprintf(stderr, "failed to parse range '%s'\n", text ? text : "NULL");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int range_overlaps(RangeSet* r1, RangeSet* r2) {
|
static int range_overlaps(RangeSet* r1, RangeSet* r2) {
|
||||||
|
|||||||
Reference in New Issue
Block a user