Merge branch 'naming-overflow-fix2' into NetHack-3.7

This commit is contained in:
nhmall
2023-02-16 18:52:47 -05:00
5 changed files with 151 additions and 80 deletions

View File

@@ -1,4 +1,4 @@
DT-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
very rarely random items are generated eroded, erodeproof, or greased
Nazgul can see invisible
fix a case where punished iron ball yanked hero on top of a monster

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
@@ -1350,17 +1372,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
@@ -1703,14 +1717,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. */
@@ -2569,17 +2569,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;
@@ -2591,18 +2595,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 *
@@ -3847,10 +3862,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)