From: Matthew Fernandez Date: Tue, 13 Sep 2022 03:15:13 +0000 (-0700) Subject: cgraph: rewrite scanner to use an agxbuf X-Git-Tag: 6.0.2~39^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69e27d48eb0be7aecfe897b5c15e5e267185de1e;p=graphviz cgraph: rewrite scanner to use an agxbuf This is a reattempt of 2d7852a049b729fb0db71c5a8ef2366215ae2035. The original change introduced a bug where unterminated strings (both `qstring` and `hstring`) would not reset the buffer, causing an assertion failure the next time a graph was parsed. This failed attempt was reverted in 16a04fe061bf6c9b3fe5fdc6250255a9b55cd337. The approach taken here is essentially the same as 2d7852a049b729fb0db71c5a8ef2366215ae2035, except that it resets the buffer on error conditions. This appears to be the only way to exit the `qstring` and `hstring` states that was not covered by the original attempt. Gitlab: related to #2272 --- diff --git a/lib/cgraph/scan.l b/lib/cgraph/scan.l index 597c79c19..5b2ba3809 100644 --- a/lib/cgraph/scan.l +++ b/lib/cgraph/scan.l @@ -23,6 +23,7 @@ %option noinput %{ +#include #include #include #include @@ -69,40 +70,25 @@ int gv_isatty_suppression; #endif /* buffer for arbitrary length strings (longer than BUFSIZ) */ -static char *Sbuf,*Sptr,*Send; +static agxbuf Sbuf; + static void beginstr(void) { - if (Sbuf == NULL) { - Sbuf = malloc(BUFSIZ); - Send = Sbuf + BUFSIZ; - } - Sptr = Sbuf; - *Sptr = 0; + // nothing required, but we should not have pending string data + assert(agxblen(&Sbuf) == 0 && + "pending string data that was not consumed (missing " + "endstr()/endhtmlstr()?)"); } static void addstr(char *src) { - char c; - if (Sptr > Sbuf) Sptr--; - do { - do {c = *Sptr++ = *src++;} while (c && Sptr < Send); - if (c) { - long sz = Send - Sbuf; - long off = Sptr - Sbuf; - sz *= 2; - Sbuf = realloc(Sbuf,sz); - Send = Sbuf + sz; - Sptr = Sbuf + off; - } - } while (c); + agxbput(&Sbuf, src); } static void endstr(void) { - aaglval.str = agstrdup(Ag_G_global,Sbuf); - *Sbuf = 0; + aaglval.str = agstrdup(Ag_G_global, agxbuse(&Sbuf)); } static void endstr_html(void) { - aaglval.str = agstrdup_html(Ag_G_global,Sbuf); - *Sbuf = 0; + aaglval.str = agstrdup_html(Ag_G_global, agxbuse(&Sbuf)); } static void @@ -246,24 +232,28 @@ void aagerror(const char *str) agxbprint(&xb, " near '%s'", aagtext); } else switch (YYSTATE) { - case qstring : + case qstring: { agxbprint(&xb, " scanning a quoted string (missing endquote? longer than %d?)", YY_BUF_SIZE); - if (*Sbuf) { - size_t len = strlen(Sbuf); + size_t len = agxblen(&Sbuf); + if (len > 0) { if (len > 80) - Sbuf[80] = '\0'; - agxbprint (&xb, "\nString starting:\"%s", Sbuf); + len = 80; + agxbprint(&xb, "\nString starting:\"%.*s", (int)len, Sbuf.buf); } + agxbclear(&Sbuf); break; - case hstring : + } + case hstring: { agxbprint(&xb, " scanning a HTML string (missing '>'? bad nesting? longer than %d?)", YY_BUF_SIZE); - if (*Sbuf) { - size_t len = strlen(Sbuf); + size_t len = agxblen(&Sbuf); + if (len > 0) { if (len > 80) - Sbuf[80] = '\0'; - agxbprint (&xb, "\nString starting:<%s", Sbuf); + len = 80; + agxbprint(&xb, "\nString starting:<%.*s", (int)len, Sbuf.buf); } + agxbclear(&Sbuf); break; + } case comment : agxbprint(&xb, " scanning a /*...*/ comment (missing '*/? longer than %d?)", YY_BUF_SIZE); break;