Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6253753a authored by Sami Tolvanen's avatar Sami Tolvanen Committed by Gerrit Code Review
Browse files

Merge "Add error and range checks to parse_range"

parents cd7d9d83 f2bac04e
Loading
Loading
Loading
Loading
+71 −10
Original line number Diff line number Diff line
@@ -60,30 +60,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);
        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) {