fix #K4043 and #K4044 - out of bounds of races[]

character_race() was going out of bounds when scanning the races[]
array, relying on a field value that the fencepost entry didn't set.

This incorporates the previous fix for UNDEFINED_RACE but also changes
character_race() to not care about that anymore.
This commit is contained in:
PatR
2023-11-27 16:43:44 -08:00
parent 8a5ca6f64c
commit 75104c69ab
3 changed files with 46 additions and 36 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 hack.h $NHDT-Date: 1700869696 2023/11/24 23:48:16 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.238 $ */ /* NetHack 3.7 hack.h $NHDT-Date: 1701132211 2023/11/28 00:43:31 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.240 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Pasi Kallinen, 2017. */ /*-Copyright (c) Pasi Kallinen, 2017. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1013,32 +1013,41 @@ typedef struct {
/* The UNDEFINED_ROLE macro is used to initialize Role variables */ /* The UNDEFINED_ROLE macro is used to initialize Role variables */
#define UNDEFINED_ROLE \ #define UNDEFINED_ROLE \
{ {0}, { {0} }, \ { \
/* strings */ \ /* role name, set of rank names */ \
NULL, NULL, NULL, \ { NULL }, { { NULL } }, \
NULL, NULL, NULL, \ /* strings: pantheon deity names */ \
/* indices */ \ NULL, NULL, NULL, \
0, 0, 0, 0, 0, 0, 0, \ /* file code, quest home+goal names */ \
0, 0, 0, \ NULL, NULL, NULL, \
/* Bitmasks */ \ /* indices: base mon type, pet */ \
0, \ NON_PM, NON_PM, \
/* Attributes */ \ /* quest leader, guardians, nemesis */ \
{0}, {0}, {0}, {0}, 0, 0, \ NON_PM, NON_PM, NON_PM, \
/* spell statistics */ \ /* quest enemy types (index, symbol) */ \
NON_PM, NON_PM, '\0', '\0', \
/* quest artifact object index */ \
STRANGE_OBJECT, \
/* Bitmasks */ \
0, \
/* Attributes */ \
{0}, {0}, {0}, {0}, 0, 0, \
/* spell statistics */ \
0, 0, 0, 0, 0, 0, 0 } 0, 0, 0, 0, 0, 0, 0 }
/* The UNDEFINED_RACE macro is used to initialize Race variables */ /* The UNDEFINED_RACE macro is used to initialize Race variables */
#define UNDEFINED_RACE \ #define UNDEFINED_RACE \
{ \ { \
/* strings */ \ /* strings */ \
NULL, NULL, NULL, NULL, {0}, \ NULL, NULL, NULL, NULL, { NULL, NULL }, \
/* Indices */ \ /* Indices: base race, mummy, zombie */ \
NON_PM, 0, 0, \ NON_PM, NON_PM, NON_PM, \
/* Bitmasks */ \ /* Bitmasks */ \
0, 0, 0, 0, \ 0, 0, 0, 0, \
/* Attributes */ \ /* Characteristic limits */ \
{0}, {0}, {0}, {0} \ {0}, {0}, \
/* Properties */ \ /* Level change HP and Pw adjustments */ \
{0}, {0} \
} }
#define MATCH_WARN_OF_MON(mon) \ #define MATCH_WARN_OF_MON(mon) \

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 decl.c $NHDT-Date: 1698264780 2023/10/25 20:13:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.293 $ */ /* NetHack 3.7 decl.c $NHDT-Date: 1701132220 2023/11/28 00:43:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.304 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2009. */ /*-Copyright (c) Michael Allison, 2009. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -829,7 +829,7 @@ const struct instance_globals_u g_init_u = {
FALSE, /* unweapon */ FALSE, /* unweapon */
/* role.c */ /* role.c */
UNDEFINED_ROLE, /* urole */ UNDEFINED_ROLE, /* urole */
UNDEFINED_VALUES, /* urace */ UNDEFINED_RACE, /* urace */
/* save.c */ /* save.c */
{ 0, 0 }, /* uz_save */ { 0, 0 }, /* uz_save */
TRUE, /* havestate*/ TRUE, /* havestate*/

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 role.c $NHDT-Date: 1596498206 2020/08/03 23:43:26 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.71 $ */ /* NetHack 3.7 role.c $NHDT-Date: 1701132222 2023/11/28 00:43:42 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.94 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1301,7 +1301,7 @@ gotrolefilter(void)
if (gr.rfilter.mask) if (gr.rfilter.mask)
return TRUE; return TRUE;
for (i = 0; i < SIZE(roles); ++i) for (i = 0; i < SIZE(roles) - 1; ++i)
if (gr.rfilter.roles[i]) if (gr.rfilter.roles[i])
return TRUE; return TRUE;
return FALSE; return FALSE;
@@ -1317,25 +1317,25 @@ rolefilterstring(char *outbuf, int which)
outbuf[0] = outbuf[1] = '\0'; outbuf[0] = outbuf[1] = '\0';
switch (which) { switch (which) {
case RS_ROLE: case RS_ROLE:
for (i = 0; i < SIZE(roles); ++i) { for (i = 0; i < SIZE(roles) - 1; ++i) {
if (gr.rfilter.roles[i]) if (gr.rfilter.roles[i])
Sprintf(eos(outbuf), " !%.3s", roles[i].name.m); Sprintf(eos(outbuf), " !%.3s", roles[i].name.m);
} }
break; break;
case RS_RACE: case RS_RACE:
for (i = 0; i < SIZE(races); ++i) { for (i = 0; i < SIZE(races) - 1; ++i) {
if ((gr.rfilter.mask & races[i].selfmask) != 0) if ((gr.rfilter.mask & races[i].selfmask) != 0)
Sprintf(eos(outbuf), " !%s", races[i].noun); Sprintf(eos(outbuf), " !%s", races[i].noun);
} }
break; break;
case RS_GENDER: case RS_GENDER:
for (i = 0; i < SIZE(genders); ++i) { for (i = 0; i < SIZE(genders) - 1; ++i) {
if ((gr.rfilter.mask & genders[i].allow) != 0) if ((gr.rfilter.mask & genders[i].allow) != 0)
Sprintf(eos(outbuf), " !%s", genders[i].adj); Sprintf(eos(outbuf), " !%s", genders[i].adj);
} }
break; break;
case RS_ALGNMNT: case RS_ALGNMNT:
for (i = 0; i < SIZE(aligns); ++i) { for (i = 0; i < SIZE(aligns) - 1; ++i) {
if ((gr.rfilter.mask & aligns[i].allow) != 0) if ((gr.rfilter.mask & aligns[i].allow) != 0)
Sprintf(eos(outbuf), " !%s", aligns[i].adj); Sprintf(eos(outbuf), " !%s", aligns[i].adj);
} }
@@ -1359,7 +1359,7 @@ clearrolefilter(int which)
gr.rfilter.mask = 0; /* clear race, gender, and alignment filters */ gr.rfilter.mask = 0; /* clear race, gender, and alignment filters */
/*FALLTHRU*/ /*FALLTHRU*/
case RS_ROLE: case RS_ROLE:
for (i = 0; i < SIZE(roles); ++i) for (i = 0; i < SIZE(roles) - 1; ++i)
gr.rfilter.roles[i] = FALSE; gr.rfilter.roles[i] = FALSE;
break; break;
case RS_RACE: case RS_RACE:
@@ -1822,10 +1822,10 @@ role_menu_extra(int which, winid where, boolean preselect)
case RS_ROLE: case RS_ROLE:
what = "role"; what = "role";
f = r; f = r;
for (i = 0; i < SIZE(roles); ++i) for (i = 0; i < SIZE(roles) - 1; ++i)
if (i != f && !gr.rfilter.roles[i]) if (i != f && !gr.rfilter.roles[i])
break; break;
if (i == SIZE(roles)) { if (i == SIZE(roles) - 1) {
constrainer = "filter"; constrainer = "filter";
forcedvalue = "role"; forcedvalue = "role";
} }
@@ -2139,13 +2139,14 @@ Goodbye(void)
} }
/* if pmindex is any player race (not necessarily the hero's), /* if pmindex is any player race (not necessarily the hero's),
return a pointer to the races[] entry for it */ return a pointer to the races[] entry for it; if pmindex is for some
other type of monster which isn't a player race, return Null */
const struct Race * const struct Race *
character_race(short pmindex) character_race(short pmindex)
{ {
const struct Race *r; const struct Race *r;
for (r = races; r->mnum >= LOW_PM; ++r) for (r = races; r->noun != NULL; ++r)
if (r->mnum == pmindex) if (r->mnum == pmindex)
return r; return r;
return (const struct Race *) NULL; return (const struct Race *) NULL;