scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 59d709537fae349d525e215d568bf6184fb5af73
parent 131909381604e13b78b084fb3d59c8dc8b6689ac
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 28 Dec 2024 10:10:27 +0100

cc2: Detect unfinished function bodies

The parser was exiting for end of file and it could happen while
we were parsing a function, accepting functions without the
closing brace. Also, several of the global variables that mark
the state of the parser were not initialized at the beginning
of every parsing, openning the door for many different problems.

Also, moreinput() could go in a infinite loop because in case of
EOF only checked for feof() but it could happen due to some error
and have an infinite loop.

And finally, we were through the full main loop every time parser()
finished, even if we didn't parse a function, having to add
continous checks everywhere because curfun could be NULL. This
didn't make sense, and a single check is done in the main loop
keeping safe the function related functions.

Diffstat:
Msrc/cmd/scc-cc/cc2/cc2.h | 1+
Msrc/cmd/scc-cc/cc2/main.c | 14+++++++++-----
Msrc/cmd/scc-cc/cc2/node.c | 5-----
Msrc/cmd/scc-cc/cc2/parser.c | 15++++++++++-----
Msrc/cmd/scc-cc/cc2/qbe/code.c | 2--
Msrc/cmd/scc-cc/cc2/z80-scc/code.c | 2--
6 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/cmd/scc-cc/cc2/cc2.h b/src/cmd/scc-cc/cc2/cc2.h @@ -145,6 +145,7 @@ enum nerrors { ENOSWTC, /* Out of switch statement */ EBBUILT, /* Unknown builtin */ EOVERFL, /* Numerical overflow */ + EBAFFUN, /* Function body not finished */ ENUMERR }; diff --git a/src/cmd/scc-cc/cc2/main.c b/src/cmd/scc-cc/cc2/main.c @@ -29,6 +29,8 @@ moreinput(void) int c; repeat: + if (ferror(stdin)) + error(EFERROR, strerror(errno)); if (feof(stdin)) return 0; if ((c = getchar()) == '\n' || c == EOF) @@ -60,11 +62,13 @@ main(int argc, char *argv[]) while (moreinput()) { parse(); - genaddr(); - gencfg(); - genasm(); - peephole(); - writeout(); + if (curfun) { + genaddr(); + gencfg(); + genasm(); + peephole(); + writeout(); + } } return 0; } diff --git a/src/cmd/scc-cc/cc2/node.c b/src/cmd/scc-cc/cc2/node.c @@ -61,9 +61,6 @@ prforest(char *msg) { Node *np; - if (!curfun) - return; - fprintf(stderr, "tree %s {\n", msg); for (np = body.begin; np; np = np->next) prtree(np); @@ -218,8 +215,6 @@ range(Node *begin, Node *end) void apply(Node *(*fun)(Node *)) { - if (!curfun) - return; body.cur = body.begin; while (body.cur) (*fun)(body.cur) ? nextstmt() : delstmt(); diff --git a/src/cmd/scc-cc/cc2/parser.c b/src/cmd/scc-cc/cc2/parser.c @@ -139,7 +139,7 @@ static struct decoc { ['s'] = { NULL, bswitch, .u.op = OBSWITCH}, }; -static int sclass, inpars, ininit, endf, lineno; +static int sclass, inpars, ininit, beginf, endf, lineno; static void *stack[STACKSIZ], **sp = stack; static Node * @@ -511,7 +511,7 @@ einit(char *token, union tokenop u) static void endpars(void) { - if (!curfun || !inpars) + if (!inpars) error(ESYNTAX); inpars = 0; } @@ -584,7 +584,7 @@ decl(Symbol *sym) break; case SAUTO: case SREG: - if (!curfun) + if (!beginf) error(ESYNTAX); ((inpars) ? defpar : defvar)(sym); break; @@ -684,7 +684,7 @@ static void beginfun(void) { newfun(lastfun); - inpars = 1; + beginf = inpars = 1; pushctx(); addstmt(node(OBFUN), SETCUR); } @@ -703,10 +703,15 @@ parse(void) cleancfg(); cleannodes(); popctx(); - endf = 0; + + inpars = ininit = beginf = endf = 0; while (!endf && nextline()) ; + if (ferror(stdin)) error(EFERROR, strerror(errno)); + + if (beginf && !endf) + error(EBAFFUN); } diff --git a/src/cmd/scc-cc/cc2/qbe/code.c b/src/cmd/scc-cc/cc2/qbe/code.c @@ -407,8 +407,6 @@ writeout(void) char *sep; int haslabel = 0; - if (!curfun) - return; getbblocks(); if (curfun->kind == SGLOB) diff --git a/src/cmd/scc-cc/cc2/z80-scc/code.c b/src/cmd/scc-cc/cc2/z80-scc/code.c @@ -205,8 +205,6 @@ data(Node *np) void writeout(void) { - if (!curfun) - return; label(curfun); for (pc = prog; pc; pc = pc->next) {