# HG changeset patch # User David A. Holland # Date 1501613464 14400 # Node ID 3a25180d3a5c2dfb51e7609222891d05261bd8c6 # Parent e200cb46ab2396b5c007e18ab51f92a35b1b97b6 Abort on line numbering or column numbering overflow. Line numbers are limited to values that fit in "unsigned int". Also reject input lines longer than 2^32-1 characters. It seems reasonable to presume that any input that violates these constraints is someone screwing around and not a serious attempt to compile or preprocess anything useful. Done in response to n2129, but without getting into any of the silliness found there. diff -r e200cb46ab23 -r 3a25180d3a5c CHANGES --- a/CHANGES Thu Dec 15 23:53:13 2016 -0500 +++ b/CHANGES Tue Aug 01 14:51:04 2017 -0400 @@ -1,4 +1,11 @@ release [pending] + - Abort on line numbering or column numbering overflow. Line + numbers are limited to values that fit in "unsigned int". Also + reject input lines longer than 2^32-1 characters. It seems + reasonable to presume that any input that violates these + constraints is someone screwing around and not a serious attempt + to compile or preprocess anything useful. Done in response to + n2129, but without getting into any of the silliness found there. - Recognize __ia64__ for IA64 builds. release 0.5.2 (20160904) diff -r e200cb46ab23 -r 3a25180d3a5c directive.c --- a/directive.c Thu Dec 15 23:53:13 2016 -0500 +++ b/directive.c Tue Aug 01 14:51:04 2017 -0400 @@ -114,7 +114,7 @@ pos = strcspn(line, ws); if (line[pos] != '\0') { - p2->column += pos; + place_addcolumns(p2, pos); complain(p2, "Garbage after %s argument", what); complain_fail(); line[pos] = '\0'; @@ -348,13 +348,13 @@ argpos = pos; pos = pos + strcspn(line+pos, "()"); if (line[pos] == '(') { - p2->column += pos; + place_addcolumns(p2, pos); complain(p2, "Left parenthesis in macro parameters"); complain_fail(); return; } if (line[pos] != ')') { - p2->column += pos; + place_addcolumns(p2, pos); complain(p2, "Unclosed macro parameter list"); complain_fail(); return; @@ -378,10 +378,10 @@ pos += strspn(line+pos, ws); p3 = *p2; - p3.column += argpos; + place_addcolumns(&p3, argpos); p4 = *p2; - p4.column += pos; + place_addcolumns(&p4, pos); if (argpos) { debuglog(&lp->current, "Defining %s()", line); @@ -490,7 +490,8 @@ errno = 0; val = strtoul(text, &moretext, 10); if (errno) { - complain(&lp->current, "No line number in #line directive"); + complain(&lp->current, + "Invalid line number in #line directive"); goto fail; } #if UINT_MAX < ULONG_MAX @@ -502,7 +503,7 @@ #endif moretext += strspn(moretext, ws); moretextlen = strlen(moretext); - lp->current.column += (moretext - text); + place_addcolumns(&lp->current, moretext - text); if (moretextlen > 2 && moretext[0] == '"' && moretext[moretextlen-1] == '"') { @@ -610,7 +611,7 @@ return; } skip = len + strspn(line+len, ws); - p2.column += skip; + place_addcolumns(&p2, skip); line += skip; len = strlen(line); @@ -667,10 +668,10 @@ pos++; } if (line[pos] == '\n') { - p2.line++; + place_addlines(&p2, 1); p2.column = 0; } else { - p2.column++; + place_addcolumns(&p2, 1); } } @@ -692,13 +693,13 @@ if (len > 0 && line[0] == '#') { skip = 1 + strspn(line + 1, ws); assert(skip <= len); - lp->current.column += skip; + place_addcolumns(&lp->current, skip); assert(line[len] == '\0'); directive_gotdirective(lp, line+skip /*, length = len-skip */); - lp->current.column += len-skip; + place_addcolumns(&lp->current, len-skip); } else if (ifstate->curtrue) { macro_sendline(&lp->current, line, len); - lp->current.column += len; + place_addcolumns(&lp->current, len); } } diff -r e200cb46ab23 -r 3a25180d3a5c eval.c --- a/eval.c Thu Dec 15 23:53:13 2016 -0500 +++ b/eval.c Tue Aug 01 14:51:04 2017 -0400 @@ -708,29 +708,29 @@ while (expr[pos] != '\0') { len = strspn(expr+pos, ws); pos += len; - p->column += len; + place_addcolumns(p, len); /* trailing whitespace is supposed to have been pruned */ assert(expr[pos] != '\0'); if (check_word(p, expr, pos, &len)) { pos += len; - p->column += len; + place_addcolumns(p, len); continue; } if (check_tokens_2(p, expr, pos)) { pos += 2; - p->column += 2; + place_addcolumns(p, 2); continue; } if (check_tokens_1(p, expr, pos)) { pos++; - p->column++; + place_addcolumns(p, 1); continue; } complain(p, "Invalid character %u in #if-expression", (unsigned char)expr[pos]); complain_fail(); pos++; - p->column++; + place_addcolumns(p, 1); } token(p, T_EOF, 0); } diff -r e200cb46ab23 -r 3a25180d3a5c files.c --- a/files.c Thu Dec 15 23:53:13 2016 -0500 +++ b/files.c Tue Aug 01 14:51:04 2017 -0400 @@ -163,6 +163,10 @@ for (i=start; i 0xffffffff) { + complain(&places.current, + "Input line too long"); + die(); + } } if (ateof) { @@ -231,7 +241,7 @@ /* eof in middle of line */ ateof = true; ptmp = places.current; - ptmp.column += bufend - linestart; + place_addcolumns(&ptmp, bufend - linestart); if (buf[bufend - 1] == '\n') { complain(&ptmp, "Unclosed comment"); complain_fail(); @@ -257,7 +267,7 @@ assert(buf[lineend] == '\n'); buf[lineend] = '\0'; nextlinestart = lineend+1; - places.nextline.line++; + place_addlines(&places.nextline, 1); /* check for CR/NL */ if (lineend > 0 && buf[lineend-1] == '\r') { @@ -284,7 +294,8 @@ assert(buf[lineend] == '\0'); /* count how many commented-out newlines we swallowed */ - places.nextline.line += countnls(buf, linestart, lineend); + place_addlines(&places.nextline, + countnls(buf, linestart, lineend)); /* process the line (even if it's empty) */ directive_gotline(&places, buf+linestart, lineend-linestart); diff -r e200cb46ab23 -r 3a25180d3a5c macro.c --- a/macro.c Thu Dec 15 23:53:13 2016 -0500 +++ b/macro.c Tue Aug 01 14:51:04 2017 -0400 @@ -523,7 +523,7 @@ while (params != NULL) { len = strspn(params, ws); params += len; - p->column += len; + place_addcolumns(p, len); s = strchr(params, ','); if (s) { len = s-params; @@ -541,7 +541,7 @@ stringarray_add(&m->params, param, NULL); } params = s; - p->column += len; + place_addcolumns(p, len); } } diff -r e200cb46ab23 -r 3a25180d3a5c main.c --- a/main.c Thu Dec 15 23:53:13 2016 -0500 +++ b/main.c Tue Aug 01 14:51:04 2017 -0400 @@ -155,7 +155,7 @@ if (val) { p2 = *p; - p2.column += strlen(str); + place_addcolumns(&p2, strlen(str)); } else { place_setbuiltin(&p2, 1); } diff -r e200cb46ab23 -r 3a25180d3a5c place.c --- a/place.c Thu Dec 15 23:53:13 2016 -0500 +++ b/place.c Tue Aug 01 14:51:04 2017 -0400 @@ -193,6 +193,34 @@ p->column = 1; } +void +place_addcolumns(struct place *p, unsigned cols) +{ + unsigned newcol; + + newcol = p->column + cols; + if (newcol < p->column) { + /* overflow (use the old place to complain) */ + complain(p, "Column numbering overflow"); + die(); + } + p->column = newcol; +} + +void +place_addlines(struct place *p, unsigned lines) +{ + unsigned nextline; + + nextline = p->line + lines; + if (nextline < p->line) { + /* overflow (use the old place to complain) */ + complain(p, "Line numbering overflow"); + die(); + } + p->line = nextline; +} + const char * place_getname(const struct place *p) { diff -r e200cb46ab23 -r 3a25180d3a5c place.h --- a/place.h Thu Dec 15 23:53:13 2016 -0500 +++ b/place.h Tue Aug 01 14:51:04 2017 -0400 @@ -53,6 +53,9 @@ void place_setcommandline(struct place *p, unsigned word, unsigned column); void place_setfilestart(struct place *p, const struct placefile *pf); +void place_addcolumns(struct place *, unsigned cols); +void place_addlines(struct place *, unsigned lines); + const char *place_getname(const struct place *); const char *place_getparsedir(const struct place *incplace); bool place_eq(const struct place *, const struct place *);