]> granicus.if.org Git - nethack/commitdiff
prompting for #dip
authorPatR <rankin@nethack.org>
Wed, 27 Jan 2016 01:32:05 +0000 (17:32 -0800)
committerPatR <rankin@nethack.org>
Wed, 27 Jan 2016 01:32:05 +0000 (17:32 -0800)
I noticed that my paniclog had a "Query truncated" entry from testing
the post-3.6.0 changes to #dip prompting.  For
"What do you want to dip <the object> into? [xyz or ?*] "
the use of safe_qbuf() didn't account for getobj() appending the list
of choices, so wasn't ensuring that the formatted object name combined
with the other text couldn't overflow QBUFSZ.

I had a more elaborate fix than this that still used safe_qbuf(), but
the extra complexity just wasn't worth it.  This potentially truncates
the formatted object description more severely than necessary but is
simple enough to be comprehensible.

No fixes36.1 entry.  This is updating a post-3.6.0 revision.

src/potion.c

index 484b89806f1ba82437ac911c73a3f7cce951de79..501998ba18e3d350385a4a0b421b32470f0c7c09 100644 (file)
@@ -1750,7 +1750,7 @@ dodip()
     uchar here;
     char allowall[2];
     short mixture;
-    char qbuf[QBUFSZ], qtoo[QBUFSZ];
+    char qbuf[QBUFSZ], obuf[QBUFSZ];
     const char *shortestname; /* last resort obj name for prompt */
 
     allowall[0] = ALL_CLASSES;
@@ -1761,15 +1761,26 @@ dodip()
         return 0;
 
     shortestname = is_plural(obj) ? "them" : "it";
+    /*
+     * Bypass safe_qbuf() since it doesn't handle varying suffix without
+     * an awful lot of support work.  Format the object once, even though
+     * the fountain and pool prompts offer a lot more room for it.
+     * 3.6.0 used thesimpleoname() unconditionally, which posed no risk
+     * of buffer overflow but drew bug reports because it omits user-
+     * supplied type name.
+     * getobj: "What do you want to dip <the object> into? [xyz or ?*] "
+     */
+    Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
+                             /* 128 - (24 + 54 + 1) leaves 49 for <object> */
+                             QBUFSZ - sizeof "What do you want to dip \
+ into? [abdeghjkmnpqstvwyzBCEFHIKLNOQRTUWXZ#-# or ?*] "));
+
     here = levl[u.ux][u.uy].typ;
     /* Is there a fountain to dip into here? */
     if (IS_FOUNTAIN(here)) {
-        Sprintf(qtoo, into_the_something, "fountain");
-        if (flags.verbose)
-            (void) safe_qbuf(qbuf, Dip_, qtoo, obj,
-                             doname, thesimpleoname, shortestname);
-        else
-            Sprintf(qbuf, "%s%s%s", Dip_, shortestname, qtoo);
+        Sprintf(qbuf, "%s%s%s%s", Dip_,
+                flags.verbose ? obuf : shortestname,
+                into_the_something, "fountain");
         /* "Dip <the object> into the fountain?" */
         if (yn(qbuf) == 'y') {
             dipfountain(obj);
@@ -1778,12 +1789,9 @@ dodip()
     } else if (is_pool(u.ux, u.uy)) {
         const char *pooltype = waterbody_name(u.ux, u.uy);
 
-        Sprintf(qtoo, into_the_something, pooltype);
-        if (flags.verbose)
-            (void) safe_qbuf(qbuf, Dip_, qtoo, obj,
-                             doname, thesimpleoname, shortestname);
-        else
-            Sprintf(qbuf, "%s%s%s", Dip_, shortestname, qtoo);
+        Sprintf(qbuf, "%s%s%s%s", Dip_,
+                flags.verbose ? obuf : shortestname,
+                into_the_something, pooltype);
         /* "Dip <the object> into the {pool, moat, &c}?" */
         if (yn(qbuf) == 'y') {
             if (Levitation) {
@@ -1801,20 +1809,9 @@ dodip()
         }
     }
 
-    /* "What do you want to dip <the object> into?" */
-    if (flags.verbose) {
-        /* "What do you want to " is getobj()'s prefix, "dip " is ours */
-        Strcpy(qbuf, safe_qbuf(qtoo, "What do you want to dip ", " into?",
-                               obj, doname, thesimpleoname, shortestname)
-                     /* skip getobj()'s prefix when assigning to qbuf */
-                     + sizeof "What do you want to " - sizeof "");
-        /* we needed the '?' in " into?" so that safe_qbuf() was working
-           with the right overall length, but now we need to take the '?'
-           off because getobj() is going to append one */
-        *(eos(qbuf) - 1) = '\0';
-    } else
-        Sprintf(qbuf, "dip %s into", shortestname);
-    potion = getobj(beverages, qbuf); /* qbuf[] == "dip <obj> into" */
+    /* "What do you want to dip <the object> into? [xyz or ?*] " */
+    Sprintf(qbuf, "dip %s into", flags.verbose ? obuf : shortestname);
+    potion = getobj(beverages, qbuf);
     if (!potion)
         return 0;
     if (potion == obj && potion->quan == 1L) {