]> granicus.if.org Git - nethack/commitdiff
Create and use a snprintf wrapper in the core code
authorDean Luick <dean@nethack.org>
Fri, 15 Jan 2021 17:30:02 +0000 (11:30 -0600)
committerDean Luick <dean@nethack.org>
Fri, 15 Jan 2021 17:33:47 +0000 (11:33 -0600)
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.

include/extern.h
src/hacklib.c
src/version.c
src/weapon.c

index e1f96be64c6111a116b18f65be6f39b6c909a8d7..8df78d7207d4c740412d84c3d3c052066b263e2c 100644 (file)
@@ -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 ### */
 
index 3600ec79809f2782322c468eea25624ea2b954de..7495913940cb2b941ef1b2be165b66f9c3931d35 100644 (file)
@@ -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*/
index f8fd308d1a44b021bfe74a293a2c879a33e7a869..ba6523c97ed7dfac1096d2a80ee9dc816677f948 100644 (file)
@@ -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
index 698d090c02e2f3d3b2dd338447f41ac05d33c533..0bb0b95f15ca74fcabacf002dd99bd13e923ce7a 100644 (file)
@@ -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);