scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit d6954f1a841ffe95aacc8c0e8a9dca44a087b1a6
parent 55eb22f73fd61f6a5393869d99d9098aee5b7337
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 18 Aug 2015 18:44:46 +0200

Limit the number of parameters, fields and enum constants

These checks control integer overflows related to xrealloc.

Diffstat:
Mcc1/decl.c | 14++++++++------
Mcc1/stmt.c | 3++-
2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/cc1/decl.c b/cc1/decl.c @@ -159,9 +159,9 @@ parameter(struct decl *dcl) sym->type = tp; sym->flags |= ISUSED; /* avoid non used warnings in prototypes */ - if (n++ == NR_FUNPARAM) + if (n == NR_FUNPARAM) error("too much parameters in function definition"); - funtp->p.pars = xrealloc(funtp->p.pars, n * sizeof(Type *)); + funtp->p.pars = xrealloc(funtp->p.pars, ++n * sizeof(Type *)); funtp->p.pars[n-1] = tp; funtp->n.elem = n; @@ -441,7 +441,7 @@ enumdcl(void) { Type *tp; Symbol *sym, *tagsym; - int val; + int val, nctes; tagsym = newtag(); tp = tagsym->type; @@ -451,13 +451,15 @@ enumdcl(void) if (tp->defined) error("redefinition of enumeration '%s'", tagsym->name); tp->defined = 1; - for (val = 0; yytoken != ')'; ++val) { + for (nctes = val = 0; yytoken != ')'; ++nctes, ++val) { if (yytoken != IDEN) unexpected(); if ((sym = install(NS_IDEN, yylval.sym)) == NULL) { error("'%s' redeclared as different kind of symbol", yytext); } + if (nctes == NR_ENUM_CTES) + error("too much enum constants in a single enum"); next(); sym->flags |= ISCONSTANT; sym->type = inttype; @@ -517,9 +519,9 @@ field(struct decl *dcl) sym->type = tp; sym->flags |= ISFIELD; - if (n++ == NR_FUNPARAM) + if (n == NR_FIELDS) error("too much fields in struct/union"); - structp->p.fields = xrealloc(structp->p.fields, n * sizeof(*sym)); + structp->p.fields = xrealloc(structp->p.fields, ++n * sizeof(*sym)); structp->p.fields[n-1] = sym; structp->n.elem = n; diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -226,7 +226,8 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) pcase->next = lswitch->head; emit(OLABEL, pcase->label = newsym(NS_LABEL)); lswitch->head = pcase; - ++lswitch->nr; + if (++lswitch->nr == NR_SWITCH) + error("too case labels for a switch statement"); stmt(lbreak, lcont, lswitch); }