From: Matthew Fernandez Date: Mon, 1 Mar 2021 04:30:59 +0000 (-0800) Subject: rewrite agxbputc as a function X-Git-Tag: 2.47.0~5^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5dd296165e66f97769fa465b881b0b9c902113af;p=graphviz rewrite agxbputc as a function This solves an issue where the macro implementation did not sufficiently bracket its arguments. Fixes #1814. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 9edd5002b..36442c97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - memory leak in ANN bridge - gvpr on Windows does not support absolute paths #1780 - buffer overflow in unflatten +- agxbputc macro does not bracket its arguments #1814 ## [2.46.1] - 2021-02-13 diff --git a/lib/cgraph/agxbuf.h b/lib/cgraph/agxbuf.h index 4692cf91f..3ed3c736e 100644 --- a/lib/cgraph/agxbuf.h +++ b/lib/cgraph/agxbuf.h @@ -88,7 +88,15 @@ extern "C" { * Add character to buffer. * int agxbputc(agxbuf*, char) */ -#define agxbputc(X,C) ((((X)->ptr >= (X)->eptr) ? agxbmore(X,1) : 0), (void)(*(X)->ptr++ = ((unsigned char)C))) +static inline int agxbputc(agxbuf * xb, char c) { + if (xb->ptr >= xb->eptr) { + if (agxbmore(xb, 1) != 0) { + return -1; + } + } + *xb->ptr++ = (unsigned char)c; + return 0; +} /* agxbuse: * Null-terminates buffer; resets and returns pointer to data. The buffer is diff --git a/lib/common/htmllex.c b/lib/common/htmllex.c index db7687314..866e9af20 100644 --- a/lib/common/htmllex.c +++ b/lib/common/htmllex.c @@ -735,7 +735,7 @@ static void characterData(void *user, const char *s, int length) c = *s++; if (c >= ' ') { cnt++; - agxbputc(state.xb, c); + agxbputc(state.xb, (char)c); } } if (cnt) state.tok = T_string; diff --git a/lib/common/utils.c b/lib/common/utils.c index a811d39d8..e463eab57 100644 --- a/lib/common/utils.c +++ b/lib/common/utils.c @@ -1515,12 +1515,12 @@ char* htmlEntityUTF8 (char* s, graph_t* g) if (v < 0x7F) /* entity needs 1 byte in UTF8 */ c = v; else if (v < 0x07FF) { /* entity needs 2 bytes in UTF8 */ - agxbputc(&xb, (v >> 6) | 0xC0); + agxbputc(&xb, (char)((v >> 6) | 0xC0)); c = (v & 0x3F) | 0x80; } else { /* entity needs 3 bytes in UTF8 */ - agxbputc(&xb, (v >> 12) | 0xE0); - agxbputc(&xb, ((v >> 6) & 0x3F) | 0x80); + agxbputc(&xb, (char)((v >> 12) | 0xE0)); + agxbputc(&xb, (char)(((v >> 6) & 0x3F) | 0x80)); c = (v & 0x3F) | 0x80; } } @@ -1528,7 +1528,7 @@ char* htmlEntityUTF8 (char* s, graph_t* g) else /* copy n byte UTF8 characters */ for (ui = 0; ui < uc; ++ui) if ((*s & 0xC0) == 0x80) { - agxbputc(&xb, c); + agxbputc(&xb, (char)c); c = *(unsigned char*)s++; } else { @@ -1539,7 +1539,7 @@ char* htmlEntityUTF8 (char* s, graph_t* g) c = cvtAndAppend (c, &xb); break; } - agxbputc(&xb, c); + agxbputc(&xb, (char)c); } ns = agxbdisown(&xb); agxbfree(&xb); @@ -1568,15 +1568,15 @@ char* latin1ToUTF8 (char* s) if (!v) v = '&'; } if (v < 0x7F) - agxbputc(&xb, v); + agxbputc(&xb, (char)v); else if (v < 0x07FF) { - agxbputc(&xb, (v >> 6) | 0xC0); - agxbputc(&xb, (v & 0x3F) | 0x80); + agxbputc(&xb, (char)((v >> 6) | 0xC0)); + agxbputc(&xb, (char)((v & 0x3F) | 0x80)); } else { - agxbputc(&xb, (v >> 12) | 0xE0); - agxbputc(&xb, ((v >> 6) & 0x3F) | 0x80); - agxbputc(&xb, (v & 0x3F) | 0x80); + agxbputc(&xb, (char)((v >> 12) | 0xE0)); + agxbputc(&xb, (char)(((v >> 6) & 0x3F) | 0x80)); + agxbputc(&xb, (char)((v & 0x3F) | 0x80)); } } ns = agxbdisown(&xb); @@ -1601,12 +1601,12 @@ utf8ToLatin1 (char* s) while ((c = *(unsigned char*)s++)) { if (c < 0x7F) - agxbputc(&xb, c); + agxbputc(&xb, (char)c); else { outc = (c & 0x03) << 6; c = *(unsigned char*)s++; outc = outc | (c & 0x3F); - agxbputc(&xb, outc); + agxbputc(&xb, (char)outc); } } ns = agxbdisown(&xb); diff --git a/lib/xdot/xdot.c b/lib/xdot/xdot.c index 131eac37a..9a24ef5c4 100644 --- a/lib/xdot/xdot.c +++ b/lib/xdot/xdot.c @@ -23,8 +23,6 @@ typedef struct { int dyna; /* true if buffer is malloc'ed */ } agxbuf; -#define agxbputc(X,C) ((((X)->ptr >= (X)->eptr) ? agxbmore(X,1) : 0), \ - (void)(*(X)->ptr++ = ((unsigned char)C))) #define agxbuse(X) (agxbputc(X,'\0'),(char*)((X)->ptr = (X)->buf)) static void agxbinit(agxbuf * xb, unsigned int hint, unsigned char *init) @@ -77,6 +75,16 @@ static int agxbput(char *s, agxbuf * xb) return ssz; } +static int agxbputc(agxbuf * xb, char c) { + if (xb->ptr >= xb->eptr) { + if (agxbmore(xb, 1) != 0) { + return -1; + } + } + *xb->ptr++ = (unsigned char)c; + return 0; +} + /* agxbfree: * Free any malloced resources. */ diff --git a/plugin/core/gvrender_core_json.c b/plugin/core/gvrender_core_json.c index 054489a6b..b4570a709 100644 --- a/plugin/core/gvrender_core_json.c +++ b/plugin/core/gvrender_core_json.c @@ -82,7 +82,7 @@ static char* stoj (char* ins, state_t* sp) char* s; char* input; static agxbuf xb; - unsigned char c; + char c; if (sp->isLatin) input = latin1ToUTF8 (ins); diff --git a/plugin/pango/gvgetfontlist_pango.c b/plugin/pango/gvgetfontlist_pango.c index a194e42ea..cee44951f 100644 --- a/plugin/pango/gvgetfontlist_pango.c +++ b/plugin/pango/gvgetfontlist_pango.c @@ -420,7 +420,7 @@ static void copyUpper (agxbuf* xb, char* s) int c; while ((c = *s++)) - (void)agxbputc (xb, toupper(c)); + (void)agxbputc (xb, (char)toupper(c)); } /* Returns the font corresponding to a Graphviz PS font.