hirc

IRC client
Log | Files | Refs

commit 67d6eea4a32747083798b70cdef47be47675e9dd
parent 04ae2cd51c8aca6a6a922ef3e21874d9ed8d77a5
Author: hhvn <dev@hhvn.uk>
Date:   Thu, 23 Mar 2023 16:13:43 +0000

Use a buffer for format()

Diffstat:
Msrc/format.y | 64+++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 33 insertions(+), 31 deletions(-)

diff --git a/src/format.y b/src/format.y @@ -430,7 +430,7 @@ raw: char * format(struct Window *window, char *format, struct History *hist) { - static char *ret; + char buf[4096]; char *ts; char *rformat; int x; @@ -504,7 +504,6 @@ format(struct Window *window, char *format, struct History *hist) { parse_dup(0); /* free memory in use for last parse_ */ for (i = 0; i < PARSE_LAST; i++) pfree(&parse_out[i]); - pfree(&ret); parse_in = rformat; parse_divbool = divbool; @@ -526,72 +525,75 @@ format(struct Window *window, char *format, struct History *hist) { alen[i] = parse_out[i] ? strlen(parse_out[i]) : 0; } - /* Space for padding is allocated here (see how len is incremented using pad) */ if (divbool) { - len = alen[PARSE_TIME] + alen[PARSE_LEFT] + alen[PARSE_RIGHT] + strlen(divstr) + 1; - if (clen[PARSE_LEFT] < divlen) - len += divlen - clen[PARSE_LEFT]; - if (window) { + if (window) pad = clen[PARSE_TIME] + divlen + ui_strlenc(NULL, divstr, NULL) + 1; - len += ((clen[PARSE_RIGHT] + 1) / (window->w - pad)) * pad + 1; - } - ret = emalloc(len); - snprintf(ret, len, "%1$s %2$*3$s%4$s%5$s", + snprintf(buf, sizeof(buf), "%1$s %2$*3$s%4$s%5$s", parse_out[PARSE_TIME] ? parse_out[PARSE_TIME] : "", parse_out[PARSE_LEFT] ? parse_out[PARSE_LEFT] : "", divlen + alen[PARSE_LEFT] - clen[PARSE_LEFT], divstr, parse_out[PARSE_RIGHT]); } else { /* If divbool is zero, then all text is in either PARSE_TIME or PARSE_RIGHT */ - len = alen[PARSE_TIME] + alen[PARSE_RIGHT] + 1; - if (window) { + if (window) pad = clen[PARSE_TIME]; - len += ((clen[PARSE_RIGHT] + 1) / (window->w - pad)) * pad; - } - ret = emalloc(len); - snprintf(ret, len, "%s%s", + snprintf(buf, sizeof(buf), "%s%s", parse_out[PARSE_TIME] ? parse_out[PARSE_TIME] : "", parse_out[PARSE_RIGHT] ? parse_out[PARSE_RIGHT] : ""); } + /* Previously this function would attempt to calculate the size needed and allocate a string for it. + * Now it uses a buffer and duplicates the string that is written to the buffer. This should be fine + * since IRC messages are capped at 512 bytes long, leaving plenty of space in 4096 bytes to write + * the formatted string to. */ + if (window) { - for (i = x = 0; ret[i]; i++) { + for (i = x = 0; buf[i]; i++) { + if (i >= sizeof(buf) - 6) { /* 6 due to ^C handling */ + ui_error("The buffer was too small to fit a string. Somehow.", NULL); + break; + } + /* taken from ui_strlenc */ - switch (ret[i]) { + switch (buf[i]) { case 2: case 9: case 15: case 18: case 21: break; case 3: /* ^C */ - if (ret[i] && isdigit(ret[i+1])) + if (buf[i] && isdigit(buf[i+1])) i += 1; - if (ret[i] && isdigit(ret[i+1])) + if (buf[i] && isdigit(buf[i+1])) i += 1; - if (ret[i] && ret[i+1] == ',' && isdigit(ret[i+2])) + if (buf[i] && buf[i+1] == ',' && isdigit(buf[i+2])) i += 2; - if (ret[i] && i && ret[i-1] == ',' && isdigit(ret[i+1])) + if (buf[i] && i && buf[i-1] == ',' && isdigit(buf[i+1])) i += 1; break; default: - if ((ret[i] & 0xC0) != 0x80) - while ((ret[i + 1] & 0xC0) == 0x80) + if ((buf[i] & 0xC0) != 0x80) + while ((buf[i + 1] & 0xC0) == 0x80 && i < sizeof(buf)) i++; x++; } if (x == window->w) { x = 0; - memmove(ret + i + pad, ret + i, strlen(ret + i) + 1); + if (i + pad + strlen(buf + i) >= sizeof(buf) - 1) + break; + memmove(buf + i + pad, buf + i, strlen(buf + i) + 1); if (parse_out[PARSE_TIME]) - memset(ret + i + 1, ' ', clen[PARSE_TIME]); + memset(buf + i + 1, ' ', clen[PARSE_TIME]); if (divbool) { - memset(ret + i + 1 + clen[PARSE_TIME], ' ', pad - clen[PARSE_TIME]); - memcpy(ret + i + 1 + pad - strlen(divstr), divstr, strlen(divstr)); + memset(buf + i + 1 + clen[PARSE_TIME], ' ', pad - clen[PARSE_TIME]); + memcpy(buf + i + 1 + pad - strlen(divstr), divstr, strlen(divstr)); } /* no need to increment i, as all the text - * inserted here is after ret[i] and will be + * inserted here is after buf[i] and will be * counted in this for loop */ } } } - return ret; + buf[i] = '\0'; + + return estrdup(buf); }