You observe a Dracula where a Dracula was.
vampire shifting into fog cloud to pass under door "oozed" rather than "flowed"
adult green dragons and the Chromatic Dragon were blinded by gas clouds
+named floating eye (when hit by another monster with reflection) or named
+ silver weapon (when hero hits silver-hating monster) could disrupt
+ message formatting and conceivably trigger crash if name had '%' in it
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
-/* NetHack 3.6 extern.h $NHDT-Date: 1496531111 2017/06/03 23:05:11 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.589 $ */
+/* NetHack 3.6 extern.h $NHDT-Date: 1496860756 2017/06/07 18:39:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.590 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
E char *FDECL(tabexpand, (char *));
E char *FDECL(visctrl, (CHAR_P));
E char *FDECL(strsubst, (char *, const char *, const char *));
+E int FDECL(strNsubst, (char *, const char *, const char *, int));
E const char *FDECL(ordin, (int));
E char *FDECL(sitoa, (int));
E int FDECL(sgn, (int));
-/* NetHack 3.6 hacklib.c $NHDT-Date: 1472006251 2016/08/24 02:37:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
+/* NetHack 3.6 hacklib.c $NHDT-Date: 1496860756 2017/06/07 18:39:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.50 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) Robert Patrick Rankin, 1991 */
/* NetHack may be freely redistributed. See license for details. */
char * tabexpand (char *)
char * visctrl (char)
char * strsubst (char *, const char *, const char *)
+ int strNsubst (char *,const char *,const char *,int)
const char * ordin (int)
char * sitoa (int)
int sgn (int)
boolean pmatchz (const char *, const char *)
int strncmpi (const char *, const char *, int)
char * strstri (const char *, const char *)
- boolean fuzzymatch (const char *,const char *,
+ boolean fuzzymatch (const char *, const char *,
const char *, boolean)
void setrandom (void)
time_t getnow (void)
char *found, buf[BUFSZ];
if (bp) {
+ /* [this could be replaced by strNsubst(bp, orig, replacement, 1)] */
found = strstr(bp, orig);
if (found) {
Strcpy(buf, found + strlen(orig));
return bp;
}
+/* substitute the Nth occurrence of a substring within a string (in place);
+ if N is 0, substitute all occurrences; returns the number of subsitutions;
+ maximum output length is BUFSZ (BUFSZ-1 chars + terminating '\0') */
+int
+strNsubst(inoutbuf, orig, replacement, n)
+char *inoutbuf; /* current string, and result buffer */
+const char *orig, /* old substring; if "" then insert in front of Nth char */
+ *replacement; /* new substring; if "" then delete old substring */
+int n; /* which occurrence to replace; 0 => all */
+{
+ char *bp, *op, workbuf[BUFSZ];
+ const char *rp;
+ unsigned len = (unsigned) strlen(orig);
+ int ocount = 0, /* number of times 'orig' has been matched */
+ rcount = 0; /* number of subsitutions made */
+
+ for (bp = inoutbuf, op = workbuf; *bp && op < &workbuf[BUFSZ - 1]; ) {
+ if ((!len || !strncmp(bp, orig, len)) && (++ocount == n || n == 0)) {
+ /* Nth match found */
+ for (rp = replacement; *rp && op < &workbuf[BUFSZ - 1]; )
+ *op++ = *rp++;
+ ++rcount;
+ if (len) {
+ bp += len; /* skip 'orig' */
+ continue;
+ }
+ }
+ /* no match (or len==0) so retain current character */
+ *op++ = *bp++;
+ }
+ if (!len && n == ocount + 1) {
+ /* special case: orig=="" (!len) and n==strlen(inoutbuf)+1,
+ insert in front of terminator (in other words, append);
+ [when orig=="", ocount will have been incremented once for
+ each input char] */
+ for (rp = replacement; *rp && op < &workbuf[BUFSZ - 1]; )
+ *op++ = *rp++;
+ ++rcount;
+ }
+ if (rcount) {
+ *op = '\0';
+ Strcpy(inoutbuf, workbuf);
+ }
+ return rcount;
+}
+
/* return the ordinal suffix of a number */
const char *
ordin(n)
-/* NetHack 3.6 mhitm.c $NHDT-Date: 1496619132 2017/06/04 23:32:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.96 $ */
+/* NetHack 3.6 mhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.97 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
tmp = 127;
if (magr->mcansee && haseyes(madat) && mdef->mcansee
&& (perceives(madat) || !mdef->minvis)) {
- Sprintf(buf, "%s gaze is reflected by %%s %%s.",
- s_suffix(Monnam(mdef)));
+ /* construct format string; guard against '%' in Monnam */
+ Strcpy(buf, s_suffix(Monnam(mdef)));
+ (void) strNsubst(buf, "%", "%%", 0);
+ Strcat(buf, " gaze is reflected by %s %s.");
if (mon_reflects(magr,
canseemon(magr) ? buf : (char *) 0))
return (mdead | mhit);
-/* NetHack 3.6 uhitm.c $NHDT-Date: 1470819843 2016/08/10 09:04:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.164 $ */
+/* NetHack 3.6 uhitm.c $NHDT-Date: 1496860757 2017/06/07 18:39:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.166 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
else if (barehand_silver_rings == 2)
fmt = "Your silver rings sear %s!";
else if (silverobj && saved_oname[0]) {
- Sprintf(silverobjbuf, "Your %s%s %s %%s!",
+ /* guard constructed format string against '%' in
+ saved_oname[] from xname(via cxname()) */
+ Sprintf(silverobjbuf, "Your %s%s %s",
strstri(saved_oname, "silver") ? "" : "silver ",
saved_oname, vtense(saved_oname, "sear"));
+ (void) strNsubst(silverobjbuf, "%", "%%", 0);
+ Strcat(silverobjbuf, " %s!");
fmt = silverobjbuf;
} else
fmt = "The silver sears %s!";