scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit a6cbaeb182ac4168f2213aa0afd7495c133e04b0
parent cb444f385bf3ba8a4939844473be02af6ad69b95
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 24 Apr 2015 18:46:32 +0200

Add security points in conditions and compounds

Diffstat:
cc1/cc1.h | 7+++++--
cc1/decl.c | 13+++++++++++--
cc1/error.c | 20+++++++++++++++-----
cc1/lex.c | 12+++++-------
cc1/stmt.c | 13+++++++++++--
5 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -4,10 +4,13 @@ extern void error(char *fmt, ...); extern void warn(char *fmt, ...); extern void unexpected(void); extern void softerror(char *fmt, ...); -extern bool setsafe(uint8_t type); +extern void setsafe(uint8_t type); enum { - END_DECL + END_DECL, + END_LDECL, + END_COMP, + END_COND }; /* definitions of types */ diff --git a/cc1/decl.c b/cc1/decl.c @@ -1,5 +1,6 @@ #include <inttypes.h> +#include <setjmp.h> #include <string.h> #include "../inc/sizes.h" @@ -427,12 +428,17 @@ decl(void) Type *tp; Symbol *sym; int8_t sclass, isfun; + extern jmp_buf recover; + setsafe(END_DECL); + setjmp(recover); tp = specifier(&sclass); if (accept(';')) return; do { + setsafe(END_LDECL); + setjmp(recover); sym = declarator(tp, ID_EXPECTED, NS_IDEN); isfun = sym->type->op == FTN; @@ -492,9 +498,10 @@ extdecl(void) int8_t sclass; Symbol *sym; extern Symbol *curfun; + extern jmp_buf recover; - if (!setsafe(END_DECL)) - return; + setsafe(END_DECL); + setjmp(recover); switch (yytoken) { case IDEN: case TYPE: case TYPEIDEN: case SCLASS: case TQUALIFIER: @@ -502,6 +509,8 @@ extdecl(void) if (accept(';')) return; do { + setsafe(END_LDECL); + setjmp(recover); sym = declarator(base, ID_EXPECTED, NS_IDEN); tp = sym->type; sym->isstatic = 1; diff --git a/cc1/error.c b/cc1/error.c @@ -39,13 +39,10 @@ warn(char *fmt, ...) va_end(va); } -bool +void setsafe(uint8_t type) { safe = type; - if (setjmp(recover)) - return 0; - return 1; } void @@ -53,6 +50,7 @@ error(char *fmt, ...) { int c; va_list va; + extern FILE *yyin; va_start(va, fmt); warn_helper(-1, fmt, va); @@ -62,12 +60,24 @@ error(char *fmt, ...) c = yytoken; do { switch (safe) { + case END_COMP: + if (c == '}') + goto jump; + goto semicolon; + case END_COND: + if (c == ')') + goto jump; + break; + case END_LDECL: + if (c == ',') + goto jump; case END_DECL: + semicolon: if (c == ';') goto jump; break; } - } while ((c = getchar()) != EOF); + } while ((c = getc(yyin)) != EOF); jump: yytoken = c; diff --git a/cc1/lex.c b/cc1/lex.c @@ -9,7 +9,7 @@ #include "../inc/cc.h" #include "cc1.h" -static FILE *yyin; +FILE *yyin; uint8_t lex_ns = NS_IDEN; const char *filename; unsigned linenum; @@ -374,11 +374,10 @@ next(void) void expect(uint8_t tok) { - if (yytoken != tok) { - softerror("unexpecetd '%s'", yytext); - yytoken = tok; - } - next(); + if (yytoken != tok) + softerror("expected '%c' before '%s'", tok, yytext); + else + next(); } uint8_t @@ -406,4 +405,3 @@ lexfile(const char *file) } linenum = 1; } - diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -1,6 +1,7 @@ #include <stddef.h> #include <inttypes.h> +#include <setjmp.h> #include <stdio.h> #include "../inc/cc.h" @@ -60,10 +61,16 @@ stmtexp(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) static Node * condition(void) { + extern jmp_buf recover; + extern Symbol *zero; Node *np; expect('('); - np = iszero(expr()); + setsafe(END_COND); + if (!setjmp(recover)) + np = iszero(expr()); + else + np = symbol(zero); expect(')'); return np; } @@ -311,10 +318,13 @@ If(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) { + extern jmp_buf recover; pushctx(); expect('{'); for (;;) { + setsafe(END_COMP); + setjmp(recover); switch (yytoken) { case '}': goto end_compound; @@ -369,4 +379,3 @@ stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) } (*fun)(lbreak, lcont, lswitch); } -