From: PatR Date: Sun, 15 Jan 2023 09:45:14 +0000 (-0800) Subject: strange object vs generic objects X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2e1f52e88236d8d0c241e4f0d397512234d92804;p=nethack strange object vs generic objects Try to fix a fuzzer issue. I wasn't able to reproduce it so am not sure whether this actually fixes it. A mimic seemed to be mimicking object #1 (generic ILLOBJ_CLASS object which shouldn't occur) rather than #0 (strange object). Strange object always has dknown==1 and generic objects should always have dknown==0 but farlook of mystery object #1 had its dknown flag set. An earlier fix to force non-Null oc_name when formatting objects in order to pacify the static analyzer might have been the reason that the problem couldn't be reproduced. This includes a few miscellaneous changes made while unsuccessfully hunting for the problem. --- diff --git a/include/display.h b/include/display.h index 5cf72c225..a09ddf027 100644 --- a/include/display.h +++ b/include/display.h @@ -850,25 +850,24 @@ enum glyph_offsets { || glyph_is_male_statue_piletop(glyph)) #define glyph_is_statue(glyph) \ (glyph_is_male_statue(glyph) || glyph_is_fem_statue(glyph)) -/* note: 'strange object' gets [mis?]classified as generic here but that - shouldn't impact anything; to do it properly, glyph_is_normal_generic_obj() - and glyph_is_piletop_generic_obj() should use '>' rather than '>=', and - glyph_is_normal_object() and glyph_is_normal_piletop_obj() should include - (glyph == {GLYPH_OBJ_OFF,GLYPH_OBJ_PILETOP_OFF}) to test for object #0 */ +/* generic objects are after strange object (GLYPH_OBJ_OFF) and before + other objects (GLYPH_OBJ_OFF + MAXOCLASSES) */ #define glyph_is_normal_generic_obj(glyph) \ - ((glyph) >= GLYPH_OBJ_OFF && (glyph) < GLYPH_OBJ_OFF + MAXOCLASSES) + ((glyph) > GLYPH_OBJ_OFF && (glyph) < GLYPH_OBJ_OFF + MAXOCLASSES) #define glyph_is_piletop_generic_obj(glyph) \ - ((glyph) >= GLYPH_OBJ_PILETOP_OFF \ + ((glyph) > GLYPH_OBJ_PILETOP_OFF \ && (glyph) < GLYPH_OBJ_PILETOP_OFF + MAXOCLASSES) #define glyph_is_generic_object(glyph) \ (glyph_is_normal_generic_obj(glyph) \ || glyph_is_piletop_generic_obj(glyph)) #define glyph_is_normal_piletop_obj(glyph) \ - (((glyph) >= GLYPH_OBJ_PILETOP_OFF + MAXOCLASSES) \ - && ((glyph) < (GLYPH_OBJ_PILETOP_OFF + NUM_OBJECTS))) + ((glyph) == GLYPH_OBJ_PILETOP_OFF \ + || ((glyph) > GLYPH_OBJ_PILETOP_OFF + MAXOCLASSES \ + && (glyph) < (GLYPH_OBJ_PILETOP_OFF + NUM_OBJECTS))) #define glyph_is_normal_object(glyph) \ - ((((glyph) >= GLYPH_OBJ_OFF + MAXOCLASSES) \ - && ((glyph) < (GLYPH_OBJ_OFF + NUM_OBJECTS))) \ + ((glyph) == GLYPH_OBJ_OFF \ + || ((glyph) >= GLYPH_OBJ_OFF + MAXOCLASSES \ + && (glyph) < (GLYPH_OBJ_OFF + NUM_OBJECTS)) \ || glyph_is_normal_piletop_obj(glyph)) #if 0 /* [note: out of date] */ diff --git a/include/extern.h b/include/extern.h index bc3f0e97a..c1ba30964 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1443,7 +1443,7 @@ extern void free_omailcmd(struct obj *); extern struct obj *mkobj_at(char, coordxy, coordxy, boolean); extern struct obj *mksobj_at(int, coordxy, coordxy, boolean, boolean); extern struct obj *mksobj_migr_to_species(int, unsigned, boolean, boolean); -extern struct obj *mkobj(int, boolean); +extern struct obj *mkobj(int, boolean) NONNULL; extern int rndmonnum_adj(int, int); extern int rndmonnum(void); extern boolean bogon_is_pname(char); @@ -1457,7 +1457,7 @@ extern void bill_dummy_object(struct obj *); extern void costly_alteration(struct obj *, int); extern void clear_dknown(struct obj *); extern void unknow_object(struct obj *); -extern struct obj *mksobj(int, boolean, boolean); +extern struct obj *mksobj(int, boolean, boolean) NONNULL; extern int bcsign(struct obj *); extern int weight(struct obj *); extern struct obj *mkgold(long, coordxy, coordxy); diff --git a/src/mkobj.c b/src/mkobj.c index 79013ce7f..9eb3dac93 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -789,7 +789,7 @@ unknow_object(struct obj *obj) obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1; } -/* mksobj(): create a specific type of object; result it always non-Null */ +/* mksobj(): create a specific type of object; result is always non-Null */ struct obj * mksobj(int otyp, boolean init, boolean artif) { diff --git a/src/o_init.c b/src/o_init.c index d9902248f..80d4f8f59 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -182,7 +182,9 @@ init_objects(void) prevoclass = (int) oclass; } /* extra entry allows deriving the range of a class via - bases[class] through bases[class+1]-1 for all classes */ + bases[class] through bases[class+1]-1 for all classes + (except for ILLOBJ_CLASS which is separated from WEAPON_CLASS + by generic objects) */ gb.bases[MAXOCLASSES] = NUM_OBJECTS; /* hypothetically someone might remove all objects of some class, or be adding a new class and not populated it yet, leaving gaps @@ -228,13 +230,16 @@ init_oclass_probs(void) int oclass; for (oclass = 0; oclass < MAXOCLASSES; ++oclass) { sum = 0; + /* note: for ILLOBJ_CLASS, bases[oclass+1]-1 isn't the last item + in the class; but all the generic items have probability 0 so + adding them to 'sum' has no impact */ for (i = gb.bases[oclass]; i < gb.bases[oclass + 1]; ++i) { sum += objects[i].oc_prob; } if (sum <= 0 && oclass != ILLOBJ_CLASS && gb.bases[oclass] != gb.bases[oclass + 1]) { - impossible("zero or negative probability total for oclass %d", - oclass); + impossible("%s (%d) probability total for oclass %d", + !sum ? "zero" : "negative", sum, oclass); /* gracefully fail by setting all members of this class to 1 */ for (i = gb.bases[oclass]; i < gb.bases[oclass + 1]; ++i) { objects[i].oc_prob = 1; diff --git a/src/pager.c b/src/pager.c index 59e7489cf..adb6d93ca 100644 --- a/src/pager.c +++ b/src/pager.c @@ -296,8 +296,10 @@ object_from_map(int glyph, coordxy x, coordxy y, struct obj **obj_p) } static void -look_at_object(char *buf, /* output buffer */ - coordxy x, coordxy y, int glyph) +look_at_object( + char *buf, /* output buffer */ + coordxy x, coordxy y, + int glyph) { struct obj *otmp = 0; boolean fakeobj = object_from_map(glyph, x, y, &otmp);