shithub: scc

Download patch

ref: d6954f1a841ffe95aacc8c0e8a9dca44a087b1a6
parent: 55eb22f73fd61f6a5393869d99d9098aee5b7337
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Aug 18 14:44:46 EDT 2015

Limit the number of parameters, fields and enum constants

These checks control integer overflows related to xrealloc.

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -159,9 +159,9 @@
 	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 @@
 {
 	Type *tp;
 	Symbol *sym, *tagsym;
-	int val;
+	int val, nctes;
 
 	tagsym = newtag();
 	tp = tagsym->type;
@@ -451,7 +451,7 @@
 	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) {
@@ -458,6 +458,8 @@
 			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 @@
 	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;
 
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
@@ -226,7 +226,8 @@
 	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);
 }