]> granicus.if.org Git - nethack/commitdiff
avoid crash when thrown potion hits bars before a monster
authorcohrs <cohrs>
Tue, 21 Jun 2005 18:51:48 +0000 (18:51 +0000)
committercohrs <cohrs>
Tue, 21 Jun 2005 18:51:48 +0000 (18:51 +0000)
From a bug report. <Someone> as slashem-Bugs-883643 on 1/24/2004.  To avoid
using the possibly invalid object pointer after calling bhit(), changed as
suggested to add another level of indirection allowing bhit to null the
object pointer before returning.  Callers that are affected update their
object pointers after bhit returns.

doc/fixes34.4
include/extern.h
src/apply.c
src/dokick.c
src/dothrow.c
src/zap.c

index 2e45e750e1a9334d5447850e3bbff0adb1697600..f0926d8b919fa6c3577a469197fdd4ba09bb733c 100644 (file)
@@ -127,6 +127,7 @@ becoming green slime or mimicking gold violates "never changed form" conduct
 when a monster grew into a higher form which had previously been genocided,
        the message explaining its fate was only given if it was sensed via ESP
 hero could still see for brief period after being blinded by potion vapors
+avoid crash when thrown potion hits bars before a monster
 
 
 Platform- and/or Interface-Specific Fixes
index 3ff15a588b95f50a87443a4c1a885d4e8baf83df..9c0ef6e4e48a3ca927d0c178a47d505b228a0db7 100644 (file)
@@ -2467,7 +2467,7 @@ E const char *FDECL(exclam, (int force));
 E void FDECL(hit, (const char *,struct monst *,const char *));
 E void FDECL(miss, (const char *,struct monst *));
 E struct monst *FDECL(bhit, (int,int,int,int,int (*)(MONST_P,OBJ_P),
-                            int (*)(OBJ_P,OBJ_P),struct obj *));
+                            int (*)(OBJ_P,OBJ_P),struct obj **));
 E struct monst *FDECL(boomhit, (int,int));
 E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P,BOOLEAN_P));
 E void FDECL(buzz, (int,int,XCHAR_P,XCHAR_P,int,int));
index 2cc5b17fa951aa97bc83b185f5c2f3828761542f..63b37e0bb1371b3a4c9e43502dcf989f4d351a8c 100644 (file)
@@ -79,7 +79,7 @@ use_camera(obj)
        } else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT,
                                (int FDECL((*),(MONST_P,OBJ_P)))0,
                                (int FDECL((*),(OBJ_P,OBJ_P)))0,
-                               obj)) != 0) {
+                               &obj)) != 0) {
                obj->ox = u.ux,  obj->oy = u.uy;
                (void) flash_hits_mon(mtmp, obj);
        }
@@ -749,7 +749,7 @@ struct obj *obj;
        mtmp = bhit(u.dx, u.dy, COLNO, INVIS_BEAM,
                    (int FDECL((*),(MONST_P,OBJ_P)))0,
                    (int FDECL((*),(OBJ_P,OBJ_P)))0,
-                   obj);
+                   &obj);
        if (!mtmp || !haseyes(mtmp->data))
                return 1;
 
index 42d62283e4c3e4ad66fe3eafc8bcceeb58dc37d0..e1732b9c7409659874e3254c2744865bbb1aaa1c 100644 (file)
@@ -557,7 +557,8 @@ xchar x, y;
        mon = bhit(u.dx, u.dy, range, KICKED_WEAPON,
                   (int FDECL((*),(MONST_P,OBJ_P)))0,
                   (int FDECL((*),(OBJ_P,OBJ_P)))0,
-                  kickobj);
+                  &kickobj);
+       if (!kickobj) return 1;         /* object broken */
 
        if(mon) {
            if (mon->isshk &&
index 32b52c4c4b4bdcfc0e3bc11ad871f83b33e96882..75f1929d6c0e32bfaafb0c8eb632e93de3ae885b 100644 (file)
@@ -873,9 +873,10 @@ struct obj *obj;
     }
 }
 
+/* throw an object, NB: obj may be consumed in the process */
 void
 throwit(obj, wep_mask, twoweap)
-register struct obj *obj;
+struct obj *obj;
 long wep_mask; /* used to re-equip returning boomerang */
 boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
 {
@@ -1000,11 +1001,14 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
                mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
                           (int FDECL((*),(MONST_P,OBJ_P)))0,
                           (int FDECL((*),(OBJ_P,OBJ_P)))0,
-                          obj);
+                          &obj);
+               thrownobj = obj;        /* obj may be null now */
 
                /* have to do this after bhit() so u.ux & u.uy are correct */
                if(Is_airlevel(&u.uz) || Levitation)
                    hurtle(-u.dx, -u.dy, urange, TRUE);
+
+               if (!obj) return;
        }
 
        if (mon) {
@@ -1777,7 +1781,8 @@ struct obj *obj;
                        mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
                                   (int FDECL((*),(MONST_P,OBJ_P)))0,
                                   (int FDECL((*),(OBJ_P,OBJ_P)))0,
-                                  obj);
+                                  &obj);
+                       if (!obj) return 1; /* object is gone */
                        if(mon) {
                            if (ghitm(mon, obj))        /* was it caught? */
                                return 1;
index 4bd9821596548bfb71a33c0efb6da675adbfcf12..31c9ad7f5f24095db2e95da7c3c3899f668e7a9c 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -2465,7 +2465,7 @@ struct obj *obj;  /* wand or spell */
 /* called for various wand and spell effects - M. Stephenson */
 void
 weffects(obj)
-register struct        obj     *obj;
+struct obj     *obj;
 {
        int otyp = obj->otyp;
        boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
@@ -2486,7 +2486,7 @@ register struct   obj     *obj;
            } else if (u.dz) {
                disclose = zap_updown(obj);
            } else {
-               (void) bhit(u.dx,u.dy, rn1(8,6),ZAPPED_WAND, bhitm,bhito, obj);
+               (void) bhit(u.dx,u.dy, rn1(8,6),ZAPPED_WAND, bhitm,bhito, &obj);
            }
            /* give a clue if obj_zapped */
            if (obj_zapped)
@@ -2634,20 +2634,25 @@ int range, *skipstart, *skipend;
  *  function) several objects and monsters on its path.  The return value
  *  is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
  *
+ * Thrown and kicked objects (THROWN_WEAPON or KICKED_WEAPON) may be
+ * destroyed and *pobj set to NULL to indicate this.
+ *
  *  Check !u.uswallow before calling bhit().
  *  This function reveals the absence of a remembered invisible monster in
  *  necessary cases (throwing or kicking weapons).  The presence of a real
  *  one is revealed for a weapon, but if not a weapon is left up to fhitm().
  */
 struct monst *
-bhit(ddx,ddy,range,weapon,fhitm,fhito,obj)
+bhit(ddx,ddy,range,weapon,fhitm,fhito,pobj)
 register int ddx,ddy,range;            /* direction and range */
 int weapon;                            /* see values in hack.h */
 int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
     FDECL((*fhito), (OBJ_P, OBJ_P));
-struct obj *obj;                       /* object tossed/used */
+struct obj **pobj;                     /* object tossed/used, set to NULL
+                                        * if object is destroyed */
 {
        struct monst *mtmp;
+       struct obj *obj = *pobj;
        uchar typ;
        boolean shopdoor = FALSE, point_blank = TRUE;
        boolean in_skip = FALSE, allow_skip = FALSE;
@@ -2697,9 +2702,10 @@ struct obj *obj;                 /* object tossed/used */
            /* iron bars will block anything big enough */
            if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) &&
                    typ == IRONBARS &&
-                   hits_bars(&obj, x - ddx, y - ddy,
+                   hits_bars(pobj, x - ddx, y - ddy,
                              point_blank ? 0 : !rn2(5), 1)) {
                /* caveat: obj might now be null... */
+               obj = *pobj;
                bhitpos.x -= ddx;
                bhitpos.y -= ddy;
                break;