Pending 3.7 edition of the naming overflow patch.

Like the 3.6.7 one, the original pieces have been combined into one
commit.  But it is separate from the one added to that version.
This commit is contained in:
PatR
2023-01-27 16:35:35 -08:00
parent 4575d564c7
commit b9bbf0205b
5 changed files with 151 additions and 80 deletions

View File

@@ -1,4 +1,4 @@
HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1051 $ $NHDT-Date: 1665130022 2022/10/07 08:07:02 $
HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1093 $ $NHDT-Date: 1672605786 2023/01/01 20:43:06 $
General Fixes and Modified Features
-----------------------------------
@@ -1101,6 +1101,8 @@ eating garlic makes nearby monsters flee
giants occasionally get a battle axe or a two-handed sword
give gremlin the property it stole, if possible
'F'orcefighting with a war hammer has a small chance of breaking iron bars
player assigned name for monsters, specific objects, or object types could be
longer than what was intented to be allowed; for 'curses', much longer
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 do_name.c $NHDT-Date: 1655663780 2022/06/19 18:36:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.254 $ */
/* NetHack 3.7 do_name.c $NHDT-Date: 1672605786 2023/01/01 20:43:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.280 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2018. */
/* NetHack may be freely redistributed. See license for details. */
@@ -19,6 +19,7 @@ static void gloc_filter_done(void);
static boolean gather_locs_interesting(coordxy, coordxy, int);
static void gather_locs(coord **, int *, int);
static void truncate_to_map(int *, int *, schar, schar);
static char *name_from_player(char *, const char *, const char *);
static void do_mgivenname(void);
static boolean alreadynamed(struct monst *, char *, char *);
static void do_oname(struct obj *);
@@ -1180,6 +1181,34 @@ safe_oname(struct obj *obj)
return "";
}
/* get a name for a monster or an object from player;
truncate if longer than PL_PSIZ, then return it */
static char *
name_from_player(
char *outbuf, /* output buffer, assumed to be at least BUFSZ long;
* anything longer than PL_PSIZ will be truncated */
const char *prompt,
const char *defres) /* only used if EDIT_GETLIN is enabled; only useful
* if windowport xxx's xxx_getlin() supports that */
{
outbuf[0] = '\0';
#ifdef EDIT_GETLIN
if (defres && *defres)
Strcpy(outbuf, defres); /* default response from getlin() */
#else
nhUse(defres);
#endif
getlin(prompt, outbuf);
if (!*outbuf || *outbuf == '\033')
return NULL;
/* strip leading and trailing spaces, condense internal sequences */
(void) mungspaces(outbuf);
if (strlen(outbuf) >= PL_PSIZ)
outbuf[PL_PSIZ - 1] = '\0';
return outbuf;
}
/* historical note: this returns a monster pointer because it used to
allocate a new bigger block of memory to hold the monster and its name */
struct monst *
@@ -1290,17 +1319,10 @@ do_mgivenname(void)
/* special case similar to the one in lookat() */
Sprintf(qbuf, "What do you want to call %s?",
distant_monnam(mtmp, ARTICLE_THE, monnambuf));
buf[0] = '\0';
#ifdef EDIT_GETLIN
/* if there's an existing name, make it be the default answer */
if (has_mgivenname(mtmp))
Strcpy(buf, MGIVENNAME(mtmp));
#endif
getlin(qbuf, buf);
if (!*buf || *buf == '\033')
/* use getlin() to get a name string from the player */
if (!name_from_player(buf, qbuf,
has_mgivenname(mtmp) ? MGIVENNAME(mtmp) : NULL))
return;
/* strip leading and trailing spaces; unnames monster if all spaces */
(void) mungspaces(buf);
/* Unique monsters have their own specific names or titles.
* Shopkeepers, temple priests and other minions use alternate
@@ -1348,17 +1370,9 @@ do_oname(struct obj *obj)
Sprintf(qbuf, "What do you want to name %s ",
is_plural(obj) ? "these" : "this");
(void) safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
buf[0] = '\0';
#ifdef EDIT_GETLIN
/* if there's an existing name, make it be the default answer */
if (has_oname(obj))
Strcpy(buf, ONAME(obj));
#endif
getlin(qbuf, buf);
if (!*buf || *buf == '\033')
/* use getlin() to get a name string from the player */
if (!name_from_player(buf, qbuf, safe_oname(obj)))
return;
/* strip leading and trailing spaces; unnames item if all spaces */
(void) mungspaces(buf);
/*
* We don't violate illiteracy conduct here, although it is
@@ -1701,14 +1715,8 @@ docall(struct obj *obj)
docall_xname, simpleonames, "thing");
/* pointer to old name */
str1 = &(objects[obj->otyp].oc_uname);
buf[0] = '\0';
#ifdef EDIT_GETLIN
/* if there's an existing name, make it be the default answer */
if (*str1)
Strcpy(buf, *str1);
#endif
getlin(qbuf, buf);
if (!*buf || *buf == '\033')
/* use getlin() to get a name string from the player */
if (!name_from_player(buf, qbuf, *str1))
return;
/* clear old name */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 invent.c $NHDT-Date: 1661240719 2022/08/23 07:45:19 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.424 $ */
/* NetHack 3.7 invent.c $NHDT-Date: 1672827802 2023/01/04 10:23:22 $ $NHDT-Branch: naming-overflow-fix $:$NHDT-Revision: 1.439 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2567,17 +2567,21 @@ prinv(const char *prefix, struct obj *obj, long quan)
DISABLE_WARNING_FORMAT_NONLITERAL
char *
xprname(struct obj *obj,
const char *txt, /* text to print instead of obj */
char let, /* inventory letter */
boolean dot, /* append period; (dot && cost => Iu) */
long cost, /* cost (for inventory of unpaid or expended items) */
long quan) /* if non-0, print this quantity, not obj->quan */
xprname(
struct obj *obj,
const char *txt, /* text to print instead of obj */
char let, /* inventory letter */
boolean dot, /* append period; (dot && cost => Iu) */
long cost, /* cost (for inventory of unpaid or expended items) */
long quan) /* if non-0, print this quantity, not obj->quan */
{
static char li[BUFSZ];
char suffix[80]; /* plenty of room for count and hallucinatory currency */
int sfxlen, txtlen; /* signed int for %*s formatting */
const char *fmt;
boolean use_invlet = (flags.invlet_constant
&& let != CONTAINED_SYM && let != HANDS_SYM);
long savequan = 0;
long savequan = 0L;
if (quan && obj) {
savequan = obj->quan;
@@ -2589,18 +2593,33 @@ xprname(struct obj *obj,
* * Then obj == null and we are printing a total amount.
* > Then the object is contained and doesn't have an inventory letter.
*/
if (cost != 0 || let == '*') {
fmt = "%c - %.*s%s";
if (!txt)
txt = doname(obj);
txtlen = (int) strlen(txt);
if (cost != 0L || let == '*') {
/* if dot is true, we're doing Iu, otherwise Ix */
Sprintf(li,
iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
: "%c - %-45s %6ld %s",
(dot && use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), cost, currency(cost));
if (dot && use_invlet)
let = obj->invlet;
Sprintf(suffix, "%c%6ld %.50s", iflags.menu_tab_sep ? '\t' : ' ',
cost, currency(cost));
if (!iflags.menu_tab_sep) {
fmt = "%c - %-45.*s%s";
if (txtlen < 45)
txtlen = 45;
}
} else {
/* ordinary inventory display or pickup message */
Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), (dot ? "." : ""));
if (use_invlet)
let = obj->invlet;
Strcpy(suffix, dot ? "." : "");
}
sfxlen = (int) strlen(suffix);
if (txtlen > BUFSZ - 1 - (4 + sfxlen)) /* 4: "c - " prefix */
txtlen = BUFSZ - 1 - (4 + sfxlen);
Sprintf(li, fmt, let, txtlen, txt, suffix);
if (savequan)
obj->quan = savequan;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 o_init.c $NHDT-Date: 1646950588 2022/03/10 22:16:28 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.56 $ */
/* NetHack 3.7 o_init.c $NHDT-Date: 1672829455 2023/01/04 10:50:55 $ $NHDT-Branch: naming-overflow-fix $:$NHDT-Revision: 1.68 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -11,6 +11,7 @@ static void shuffle_all(void);
static int QSORTCALLBACK discovered_cmp(const genericptr, const genericptr);
static char *sortloot_descr(int, char *);
static char *disco_typename(int);
static void disco_append_typename(char *, int);
static char *oclass_to_name(char, char *);
#ifdef TILES_IN_GLYPHMAP
@@ -651,6 +652,30 @@ disco_typename(int otyp)
return result;
}
/* append typename(dis) to buf[], possibly truncating in the process */
static void
disco_append_typename(char *buf, int dis)
{
unsigned len = (unsigned) strlen(buf);
char *p, *typnm = disco_typename(dis);
if (len + (unsigned) strlen(typnm) < BUFSZ) {
/* ordinary */
Strcat(buf, typnm);
} else if ((p = strrchr(typnm, '(')) != 0
&& p > typnm && p[-1] == ' ' && strchr(p, ')') != 0) {
/* typename() returned "really long user-applied name (actual type)"
and we want to truncate from "really long user-applied name" while
keeping " (actual type)" intact */
--p; /* back up to space in front of open paren */
(void) strncat(buf, typnm, BUFSZ - 1 - (len + (unsigned) strlen(p)));
Strcat(buf, p);
} else {
/* unexpected; just truncate from end of typename */
(void) strncat(buf, typnm, BUFSZ - 1 - len);
}
}
/* the #known command - show discovered object types */
int
dodiscovered(void) /* free after Robert Viduya */
@@ -734,7 +759,7 @@ dodiscovered(void) /* free after Robert Viduya */
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
if (lootsort)
(void) sortloot_descr(dis, &buf[2]);
Strcat(buf, disco_typename(dis));
disco_append_typename(buf, dis);
if (!alphabetized && !lootsort)
putstr(tmpwin, 0, buf);
@@ -966,7 +991,7 @@ doclassdisco(void)
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
if (lootsort)
(void) sortloot_descr(dis, &buf[2]);
Strcat(buf, disco_typename(dis));
disco_append_typename(buf, dis);
if (!alphabetized && !lootsort)
putstr(tmpwin, 0, buf);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 objnam.c $NHDT-Date: 1654557302 2022/06/06 23:15:02 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.368 $ */
/* NetHack 3.7 objnam.c $NHDT-Date: 1672829441 2023/01/04 10:50:41 $ $NHDT-Branch: naming-overflow-fix $:$NHDT-Revision: 1.386 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -35,6 +35,7 @@ struct _readobjnam_data {
static char *strprepend(char *, const char *);
static char *nextobuf(void);
static void releaseobuf(char *);
static void xcalled(char *, int, const char *, const char *);
static char *xname_flags(struct obj *, unsigned);
static char *minimal_xname(struct obj *);
static void add_erosion_words(struct obj *, char *);
@@ -187,6 +188,7 @@ obj_typename(int otyp)
if (!actualn)
actualn = (otyp > 0 && otyp < MAXOCLASSES) ? "generic" : "object?";
buf[0] = '\0'; /* redundant */
switch (ocl->oc_class) {
case COIN_CLASS:
Strcpy(buf, "coin");
@@ -217,7 +219,7 @@ obj_typename(int otyp)
else
Strcpy(buf, "amulet");
if (un)
Sprintf(eos(buf), " called %s", un);
xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
return buf;
@@ -226,8 +228,8 @@ obj_typename(int otyp)
Strcpy(buf, actualn);
if (GemStone(otyp))
Strcat(buf, " stone");
if (un)
Sprintf(eos(buf), " called %s", un);
if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
} else {
@@ -236,7 +238,7 @@ obj_typename(int otyp)
Strcat(buf,
(ocl->oc_material == MINERAL) ? " stone" : " gem");
if (un)
Sprintf(eos(buf), " called %s", un);
xcalled(buf, BUFSZ, "", un);
}
return buf;
}
@@ -247,8 +249,8 @@ obj_typename(int otyp)
else
Sprintf(eos(buf), " of %s", actualn);
}
if (un)
Sprintf(eos(buf), " called %s", un);
if (un) /* 3: length of " (" + ")" which will enclose 'dn' */
xcalled(buf, BUFSZ - (dn ? (int) strlen(dn) + 3 : 0), "", un);
if (dn)
Sprintf(eos(buf), " (%s)", dn);
return buf;
@@ -498,6 +500,24 @@ reorder_fruit(boolean forward)
}
}
/* add "<pfx> called <sfx>" to end of buf, truncating if necessary */
static void
xcalled(
char *buf, /* eos(obuf) or eos(&obuf[PREFIX]) */
int siz, /* BUFSZ or BUFSZ-PREFIX */
const char *pfx, /* usually class string, sometimes more specific */
const char *sfx) /* user assigned type name */
{
int bufsiz = siz - 1 - (int) strlen(buf),
pfxlen = (int) (strlen(pfx) + sizeof " called " - sizeof "");
if (pfxlen > bufsiz)
panic("xcalled: not enough room for prefix (%d > %d)",
pfxlen, bufsiz);
Sprintf(eos(buf), "%s called %.*s", pfx, bufsiz - pfxlen, sfx);
}
char *
xname(struct obj* obj)
{
@@ -530,7 +550,7 @@ xname_flags(
for those; pacify static analyzer without resorting to impossible() */
if (!actualn)
actualn = (typ > 0 && typ < MAXOCLASSES) ? "generic" : "object?";
/* As of 3.6.2: this used to be part of 'dn's initialization, but it
/* 3.6.2: this used to be part of 'dn's initialization, but it
needs to come after possibly overriding 'actualn' */
if (!dn)
dn = actualn;
@@ -592,7 +612,7 @@ xname_flags(
else if (nn)
Strcpy(buf, actualn);
else if (un)
Sprintf(buf, "amulet called %s", un);
xcalled(buf, BUFSZ - PREFIX, "amulet", un);
else
Sprintf(buf, "%s amulet", dn);
break;
@@ -611,11 +631,9 @@ xname_flags(
Strcat(buf, dn);
else if (nn)
Strcat(buf, actualn);
else if (un) {
Strcat(buf, dn);
Strcat(buf, " called ");
Strcat(buf, un);
} else
else if (un)
xcalled(buf, BUFSZ - PREFIX, dn, un);
else
Strcat(buf, dn);
if (typ == FIGURINE && omndx != NON_PM) {
@@ -650,7 +668,7 @@ xname_flags(
if (nn)
Strcat(buf, actualn);
else if (un)
Sprintf(eos(buf), "%s called %s", armor_simple_name(obj), un);
xcalled(buf, BUFSZ - PREFIX, armor_simple_name(obj), un);
else
Strcat(buf, dn);
break;
@@ -750,8 +768,7 @@ xname_flags(
}
Strcat(buf, actualn);
} else {
Strcat(buf, " called ");
Strcat(buf, un);
xcalled(buf, BUFSZ - PREFIX, "", un);
}
} else {
Strcat(buf, dn);
@@ -766,8 +783,7 @@ xname_flags(
Strcat(buf, " of ");
Strcat(buf, actualn);
} else if (un) {
Strcat(buf, " called ");
Strcat(buf, un);
xcalled(buf, BUFSZ - PREFIX, "", un);
} else if (ocl->oc_magic) {
Strcat(buf, " labeled ");
Strcat(buf, dn);
@@ -782,7 +798,7 @@ xname_flags(
else if (nn)
Sprintf(buf, "wand of %s", actualn);
else if (un)
Sprintf(buf, "wand called %s", un);
xcalled(buf, BUFSZ - PREFIX, "wand", un);
else
Sprintf(buf, "%s wand", dn);
break;
@@ -793,7 +809,7 @@ xname_flags(
else if (nn)
Strcpy(buf, actualn);
else if (un)
Sprintf(buf, "novel called %s", un);
xcalled(buf, BUFSZ - PREFIX, "novel", un);
else
Sprintf(buf, "%s book", dn);
break;
@@ -805,7 +821,7 @@ xname_flags(
Strcpy(buf, "spellbook of ");
Strcat(buf, actualn);
} else if (un) {
Sprintf(buf, "spellbook called %s", un);
xcalled(buf, BUFSZ - PREFIX, "spellbook", un);
} else
Sprintf(buf, "%s spellbook", dn);
break;
@@ -815,7 +831,7 @@ xname_flags(
else if (nn)
Sprintf(buf, "ring of %s", actualn);
else if (un)
Sprintf(buf, "ring called %s", un);
xcalled(buf, BUFSZ - PREFIX, "ring", un);
else
Sprintf(buf, "%s ring", dn);
break;
@@ -826,7 +842,7 @@ xname_flags(
Strcpy(buf, rock);
} else if (!nn) {
if (un)
Sprintf(buf, "%s called %s", rock, un);
xcalled(buf, BUFSZ - PREFIX, rock, un);
else
Sprintf(buf, "%s %s", dn, rock);
} else {
@@ -879,7 +895,8 @@ xname_flags(
Strcat(buf, " named ");
nameit:
obufp = eos(buf);
Strcat(buf, ONAME(obj));
(void) strncat(buf, ONAME(obj),
BUFSZ - 1 - PREFIX - (unsigned) strlen(buf));
/* downcase "The" in "<quest-artifact-item> named The ..." */
if (obj->oartifact && !strncmp(obufp, "The ", 4))
*obufp = lowc(*obufp); /* = 't'; */
@@ -1866,7 +1883,7 @@ just_an(char *outbuf, const char *str)
}
char *
an(const char* str)
an(const char *str)
{
char *buf = nextobuf();
@@ -1875,11 +1892,11 @@ an(const char* str)
return strcpy(buf, "an []");
}
(void) just_an(buf, str);
return strcat(buf, str);
return strncat(buf, str, BUFSZ - 1 - Strlen(buf));
}
char *
An(const char* str)
An(const char *str)
{
char *tmp = an(str);
@@ -1950,9 +1967,7 @@ the(const char* str)
Strcpy(buf, "the ");
else
buf[0] = '\0';
Strcat(buf, str);
return buf;
return strncat(buf, str, BUFSZ - 1 - Strlen(buf));
}
char *
@@ -3846,10 +3861,12 @@ readobjnam_postparse1(struct _readobjnam_data *d)
*/
if ((d->p = strstri(d->bp, " named ")) != 0) {
*d->p = 0;
/* note: if 'name' is too long, oname() will truncate it */
d->name = d->p + 7;
}
if ((d->p = strstri(d->bp, " called ")) != 0) {
*d->p = 0;
/* note: if 'un' is too long, obj lookup just won't match anything */
d->un = d->p + 8;
/* "helmet called telepathy" is not "helmet" (a specific type)
* "shield called reflection" is not "shield" (a general type)