From 435454f6041216d2c38e507c860737c23e3e50fc Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 24 Feb 2019 16:11:16 -0800 Subject: Check for negative array lengths/indices --- decl.c | 8 ++++---- expr.c | 4 +++- expr.h | 2 +- init.c | 2 +- stmt.c | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/decl.c b/decl.c index ac72f23..870d72a 100644 --- a/decl.c +++ b/decl.c @@ -212,7 +212,7 @@ tagspec(struct scope *s) scopeputdecl(s, tok.lit, d); next(); if (consume(TASSIGN)) - i = intconstexpr(s); + i = intconstexpr(s, true); d->value = mkintconst(t->repr, i); if (!consume(TCOMMA)) break; @@ -336,7 +336,7 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspecifier *fs, int *a if (t) { *align = t->align; } else { - i = intconstexpr(s); + i = intconstexpr(s, false); if (!i || i & (i - 1) || i > 16) error(&tok.loc, "invalid alignment: %d", i); *align = (int)i; @@ -511,7 +511,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs i = 0; next(); } else { - i = intconstexpr(s); + i = intconstexpr(s, false); expect(TRBRACK, "after array length"); } if (tq) { @@ -712,7 +712,7 @@ decl(struct scope *s, struct function *f) if (consume(T_STATIC_ASSERT)) { expect(TLPAREN, "after _Static_assert"); - c = intconstexpr(s); + c = intconstexpr(s, true); expect(TCOMMA, "after static assertion expression"); expect(TSTRINGLIT, "after static assertion expression"); if (!c) diff --git a/expr.c b/expr.c index 501e0e5..a09f2d6 100644 --- a/expr.c +++ b/expr.c @@ -847,13 +847,15 @@ condexpr(struct scope *s) } uint64_t -intconstexpr(struct scope *s) +intconstexpr(struct scope *s, bool allowneg) { struct expression *e; e = eval(condexpr(s)); if (e->kind != EXPRCONST || !(typeprop(e->type) & PROPINT)) error(&tok.loc, "not an integer constant expression"); + if (!allowneg && e->type->basic.issigned && e->constant.i > INT64_MAX) + error(&tok.loc, "integer constant expression cannot be negative"); return e->constant.i; } diff --git a/expr.h b/expr.h index 7de6635..8e7aa4c 100644 --- a/expr.h +++ b/expr.h @@ -88,7 +88,7 @@ struct scope; struct expression *expr(struct scope *); struct expression *assignexpr(struct scope *); -uint64_t intconstexpr(struct scope *); +uint64_t intconstexpr(struct scope *, _Bool); void delexpr(struct expression *); void exprpromote(struct expression **); // XXX: move to type diff --git a/init.c b/init.c index ec76ef3..20e2f51 100644 --- a/init.c +++ b/init.c @@ -129,7 +129,7 @@ designator(struct scope *s, struct initparser *p) if (t->kind != TYPEARRAY) error(&tok.loc, "index designator is only valid for array types"); next(); - p->sub->idx = intconstexpr(s); + p->sub->idx = intconstexpr(s, false); if (t->incomplete) updatearray(t, p->sub->idx); else if (p->sub->idx >= t->array.length) diff --git a/stmt.c b/stmt.c index a5192c5..e642353 100644 --- a/stmt.c +++ b/stmt.c @@ -52,7 +52,7 @@ stmt(struct function *f, struct scope *s) error(&tok.loc, "'case' label must be in switch"); label[0] = mkblock("switch_case"); funclabel(f, label[0]); - i = intconstexpr(s); + i = intconstexpr(s, true); switchcase(s->switchcases, i, label[0]); expect(TCOLON, "after case expression"); stmt(f, s); -- cgit v1.2.3