fix unnaming types of objects

docall() would access freed memory if the player used space(s) as
a fake object type name in order to remove an existing name without
giving any new one.

3.4.3 had this bug too; I didn't go farther back.
This commit is contained in:
PatR
2023-12-27 04:59:44 -08:00
parent 94b59cbd35
commit 97272d3627
2 changed files with 14 additions and 13 deletions
+2
View File
@@ -1338,6 +1338,8 @@ amulet of unchanging cannot be polymorphed
wishing for a "lit candle" provided one, but the feedback as it was added into wishing for a "lit candle" provided one, but the feedback as it was added into
invent was "partly used candle (lit)" because of how 'lit' timer works invent was "partly used candle (lit)" because of how 'lit' timer works
don't fall off steed because of Fumbling if saddle is cursed don't fall off steed because of Fumbling if saddle is cursed
using <space(s)> to remove an existing name given to a type of object was
accessing freed memory
Fixes to 3.7.0-x General Problems Exposed Via git Repository Fixes to 3.7.0-x General Problems Exposed Via git Repository
+12 -13
View File
@@ -1765,40 +1765,39 @@ void
docall(struct obj *obj) docall(struct obj *obj)
{ {
char buf[BUFSZ], qbuf[QBUFSZ]; char buf[BUFSZ], qbuf[QBUFSZ];
char **str1; char **uname_p;
boolean had_name = FALSE;
if (!obj->dknown) if (!obj->dknown)
return; /* probably blind */ return; /* probably blind; Blind || Hallucination for 'fromsink' */
flush_screen(1); /* buffered updates might matter to player's response */ flush_screen(1); /* buffered updates might matter to player's response */
if (obj->oclass == POTION_CLASS && obj->fromsink) if (obj->oclass == POTION_CLASS && obj->fromsink)
/* kludge, meaning it's sink water */ /* fromsink: kludge, meaning it's sink water */
Sprintf(qbuf, "Call a stream of %s fluid:", Sprintf(qbuf, "Call a stream of %s fluid:",
OBJ_DESCR(objects[obj->otyp])); OBJ_DESCR(objects[obj->otyp]));
else else
(void) safe_qbuf(qbuf, "Call ", ":", obj, (void) safe_qbuf(qbuf, "Call ", ":", obj,
docall_xname, simpleonames, "thing"); docall_xname, simpleonames, "thing");
/* pointer to old name */ /* pointer to old name */
str1 = &(objects[obj->otyp].oc_uname); uname_p = &(objects[obj->otyp].oc_uname);
/* use getlin() to get a name string from the player */ /* use getlin() to get a name string from the player */
if (!name_from_player(buf, qbuf, *str1)) if (!name_from_player(buf, qbuf, *uname_p))
return; return;
/* clear old name */ /* clear old name */
if (*str1) if (*uname_p) {
free((genericptr_t) *str1); had_name = TRUE;
free((genericptr_t) *uname_p), *uname_p = NULL; /* clear oc_uname */
}
/* strip leading and trailing spaces; uncalls item if all spaces */ /* strip leading and trailing spaces; uncalls item if all spaces */
(void) mungspaces(buf); (void) mungspaces(buf);
if (!*buf) { if (!*buf) {
if (*str1) { /* had name, so possibly remove from disco[] */ if (had_name) /* possibly remove from disco[]; old *uname_p is gone */
/* strip name first, for the update_inventory() call
from undiscover_object() */
*str1 = (char *) 0;
undiscover_object(obj->otyp); undiscover_object(obj->otyp);
}
} else { } else {
*str1 = dupstr(buf); *uname_p = dupstr(buf);
discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */ discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
} }
} }