From: Dean Luick Date: Fri, 15 Jan 2021 17:30:02 +0000 (-0600) Subject: Create and use a snprintf wrapper in the core code X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8143d55d762fbc016c90632c352ddb2adfd22a0b;p=nethack Create and use a snprintf wrapper in the core code Use a wrapper around snprintf to consilidate all use, add error checking, and remove gcc 9 warnings about not checking the result. Replace the prevous use of snprintf added to weapon.c with the new scheme. Update a second spot that has a gcc sprintf warning. While there, simplify the code. --- diff --git a/include/extern.h b/include/extern.h index e1f96be64..8df78d720 100644 --- a/include/extern.h +++ b/include/extern.h @@ -953,6 +953,12 @@ E void FDECL(strbuf_nl_to_crlf, (strbuf_t *)); E char *FDECL(nonconst, (const char *, char *)); E int FDECL(swapbits, (int, int, int)); E void FDECL(shuffle_int_array, (int *, int)); +/* note: the snprintf CPP wrapper includes the "fmt" argument in "..." + (__VA_ARGS__) to allow for zero arguments after fmt */ +#define Snprintf(str, size, ...) \ + nh_snprintf(__func__, __LINE__, str, size, __VA_ARGS__) +extern void nh_snprintf(const char *func, int line, char *str, size_t size, + const char *fmt, ...); /* ### insight.c ### */ diff --git a/src/hacklib.c b/src/hacklib.c index 3600ec798..749591394 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -74,6 +74,8 @@ char * nonconst (const char *, char *) int swapbits (int, int, int) void shuffle_int_array (int *, int) + void nh_snprintf (const char *, int, char *, size_t, + const char *, ...) =*/ #ifdef LINT #define Static /* pacify lint */ @@ -1319,4 +1321,39 @@ int count; } } +/* + * Wrap snprintf for use in the main code. + * + * Wrap reasons: + * 1. If there are any platform issues, we have one spot to fix them - + * snprintf is a routine with a troubling history of bad implementations. + * 2. Add combersome error checking in one spot. Problems with text wrangling + * do not have to be fatal. + * 3. Gcc 9+ will issue a warning unless the return value is used. + * Annoyingly, explicitly casting to void does not remove the error. + * So, use the result - see reason #2. + */ +void +nh_snprintf(const char *func, int line, char *str, size_t size, + const char *fmt, ...) +{ + va_list ap; + int n; + + va_start(ap, fmt); +#ifdef NO_VSNPRINTF + n = vsprintf(str, fmt, ap); +#else + n = vsnprintf(str, size, fmt, ap); +#endif + va_end(ap); + if (n < 0 || (size_t)n >= size) { /* is there a problem? */ + impossible("snprintf %s: func %s, file line %d", + n < 0 ? "format error" + : "overflow", + func, line); + str[size-1] = 0; /* make sure it is nul terminated */ + } +} + /*hacklib.c*/ diff --git a/src/version.c b/src/version.c index f8fd308d1..ba6523c97 100644 --- a/src/version.c +++ b/src/version.c @@ -251,19 +251,23 @@ void early_version_info(pastebuf) boolean pastebuf; { - char buf[BUFSZ], buf2[BUFSZ]; - char *tmp = getversionstring(buf); + char buf1[BUFSZ], buf2[BUFSZ]; + char *buf, *tmp; - /* this is early enough that we have to do - our own line-splitting */ + Snprintf(buf1, sizeof(buf1), "test"); + /* this is early enough that we have to do our own line-splitting */ + getversionstring(buf1); + tmp = strstri(buf1, " ("); /* split at start of version info */ if (tmp) { - tmp = strstri(buf," ("); - if (tmp) *tmp++ = '\0'; + /* retain one buffer so that it all goes into the paste buffer */ + *tmp++ = '\0'; + Snprintf(buf2, sizeof(buf2), "%s\n%s", buf1, tmp); + buf = buf2; + } else { + buf = buf1; } - Sprintf(buf2, "%s\n", buf); - if (tmp) Sprintf(eos(buf2), "%s\n", tmp); - raw_printf("%s", buf2); + raw_printf("%s", buf); if (pastebuf) { #if defined(RUNTIME_PASTEBUF_SUPPORT) && !defined(LIBNH) @@ -272,7 +276,7 @@ boolean pastebuf; * version information into a paste buffer. Useful for * easy inclusion in bug reports. */ - port_insert_pastebuf(buf2); + port_insert_pastebuf(buf); #else raw_printf("%s", "Paste buffer copy is not available.\n"); #endif diff --git a/src/weapon.c b/src/weapon.c index 698d090c0..0bb0b95f1 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1271,23 +1271,21 @@ enhance_weapon_skill() (void) skill_level_name(i, sklnambuf); if (wizard) { if (!iflags.menu_tab_sep) - n = snprintf(buf, sizeof(buf), " %s%-*s %-12s %5d(%4d)", prefix, - longest, P_NAME(i), sklnambuf, P_ADVANCE(i), - practice_needed_to_advance(P_SKILL(i))); + Snprintf(buf, sizeof(buf), " %s%-*s %-12s %5d(%4d)", prefix, + longest, P_NAME(i), sklnambuf, P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); else - n = snprintf(buf, sizeof(buf), " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i), - sklnambuf, P_ADVANCE(i), - practice_needed_to_advance(P_SKILL(i))); + Snprintf(buf, sizeof(buf), " %s%s\t%s\t%5d(%4d)", prefix, P_NAME(i), + sklnambuf, P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); } else { if (!iflags.menu_tab_sep) - n = snprintf(buf, sizeof(buf), " %s %-*s [%s]", prefix, longest, - P_NAME(i), sklnambuf); + Snprintf(buf, sizeof(buf), " %s %-*s [%s]", prefix, longest, + P_NAME(i), sklnambuf); else - n = snprintf(buf, sizeof(buf), " %s%s\t[%s]", prefix, P_NAME(i), - sklnambuf); + Snprintf(buf, sizeof(buf), " %s%s\t[%s]", prefix, P_NAME(i), + sklnambuf); } - if (n >= sizeof(buf)) /* check for overflow */ - buf[sizeof(buf)-1] = 0; /* terminate string */ any.a_int = can_advance(i, speedy) ? i + 1 : 0; add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, buf, MENU_ITEMFLAGS_NONE);