From: PatR Date: Mon, 31 May 2021 22:28:19 +0000 (-0700) Subject: append_str(pager.c) again X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ffddb3ecf9d031ed8fe2e3faf3c635a6bd9cdce1;p=nethack append_str(pager.c) again More for issue #524. The revised append_str() was still vulnerable to unsigned subtraction overflowing from small negative value to huge positive one, if caller ever passed an outbuf buffer which already had more than BUFSZ characters in it. Also the semantics were changed. If there wasn't room for the whole " or "+string to be appended, it used to add as much as would fit. The revised version changed that to all-or-nothing. This changes it back, although players will probably never know the difference. --- diff --git a/src/pager.c b/src/pager.c index 73e1a70bd..266a9efef 100644 --- a/src/pager.c +++ b/src/pager.c @@ -52,27 +52,32 @@ is_swallow_sym(int c) return FALSE; } -/* - * Append new_str to the end of buf if new_str doesn't already exist as - * a substring of buf. Return 1 if the string was appended, 0 otherwise. - * It is expected that buf is of size BUFSZ. - */ +/* Append " or "+new_str to the end of buf if new_str doesn't already exist + as a substring of buf. Return 1 if the string was appended, 0 otherwise. + It is expected that buf is of size BUFSZ. */ static int append_str(char *buf, const char *new_str) { - size_t size2append, space_left; - const char sep[] = " or "; + static const char sep[] = " or "; + size_t oldlen, space_left; if (strstri(buf, new_str)) - return 0; + return 0; /* already present */ + + oldlen = strlen(buf); + if (oldlen >= BUFSZ - 1) { + if (oldlen > BUFSZ - 1) + impossible("append_str: 'buf' contains %lu characters.", + (unsigned long) oldlen); + return 0; /* no space available */ + } - space_left = BUFSZ - strlen(buf); /* space remaining in buf */ - size2append = strlen(new_str) + sizeof sep; /* latter includes '\0' */ - if (space_left < size2append) - return 0; - Strcat(buf, sep); - Strcat(buf, new_str); - return 1; + /* some space available, but not necessarily enough for full append */ + space_left = BUFSZ - 1 - oldlen; /* space remaining in buf */ + (void) strncat(buf, sep, space_left); + if (space_left > sizeof sep - 1) + (void) strncat(buf, new_str, space_left - (sizeof sep - 1)); + return 1; /* something was appended, possibly just part of " or " */ } /* shared by monster probing (via query_objlist!) as well as lookat() */