]> granicus.if.org Git - nethack/commitdiff
simpleonames() fix
authorPatR <rankin@nethack.org>
Fri, 8 Oct 2021 20:53:21 +0000 (13:53 -0700)
committerPatR <rankin@nethack.org>
Fri, 8 Oct 2021 20:53:21 +0000 (13:53 -0700)
Some code from about a month back changed xname() and doname() to
only use a single 'obuf[]'.  That was to make sure that perm_invent
update also used at most one obuf.  They use some slightly convoluted
code when they called other routines which returned an obuf because
only the most recently allocated one can be explicitly released for
re-use.  That works, so I did the same for simpleonames() and
thesimpleoname() and for some reason neglected the convolution for
simpleonames().

For the case where plural was needed, it needs two obufs and tried
to release the first, which is a no-op.  So if it was used in a loop
like display_pickinv() uses doname(), it could have cycled through
all the obufs and clobbered one a caller was expecting to remember.
I'm not aware of any instances of this being an actual problem, just
happened to notice that simpleonames() was different from other
similar routines.

src/objnam.c

index cd9274c8b78763872e1f0c74fe15cc8f21660599..b285a750784868fdb30ed0bfddb6b8fd099e03a4 100644 (file)
@@ -828,7 +828,7 @@ xname_flags(
      potion of object detection -- if discovered
  */
 static char *
-minimal_xname(struct objobj)
+minimal_xname(struct obj *obj)
 {
     char *bufp;
     struct obj bareobj;
@@ -861,6 +861,7 @@ minimal_xname(struct obj* obj)
     if (obj->otyp == SLIME_MOLD)
         bareobj.spe = obj->spe;
 
+    /* bufp will be an obuf[] and a pointer into middle of that is viable */
     bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
     if (!strncmp(bufp, "uncursed ", 9))
         bufp += 9; /* Role_if(PM_CLERIC) */
@@ -2006,7 +2007,12 @@ simpleonames(struct obj* obj)
     char *obufp, *simpleoname = minimal_xname(obj);
 
     if (obj->quan != 1L) {
-        simpleoname = makeplural(obufp = simpleoname);
+        /* 'simpleoname' points to an obuf; makeplural() will allocate
+           another one and only that one can be explicitly released for
+           re-use, so this is slightly convoluted to cope with that;
+           makeplural() will be fully evaluated and done with its input
+           argument before strcpy() touches its output argument */
+        Strcpy(simpleoname, obufp = makeplural(simpleoname));
         releaseobuf(obufp);
     }
     return simpleoname;