]> granicus.if.org Git - nethack/commitdiff
water vs acid
authornethack.rankin <nethack.rankin>
Thu, 11 May 2006 03:26:55 +0000 (03:26 +0000)
committernethack.rankin <nethack.rankin>
Thu, 11 May 2006 03:26:55 +0000 (03:26 +0000)
     Fix the bug From a bug report.alt.org server, where killing a monster by closing the
castle drawbridge resulted in a panic after the dead monster's possessions
were dropped into the moat and a potion of acid exploded in the process.
water_damage() deleted the object but had no way to tell flooreffects()
that it was gone, so flooreffects() couldn't tell its own caller not to
place and stack the object.  After that, a chunk of freed memory became
part of the floor objects chain and eventually triggered a panic which
tried to make a save file but whose reason didn't get logged properly.

doc/fixes34.4
include/extern.h
src/do.c
src/fountain.c
src/mon.c
src/objnam.c
src/trap.c

index e2c7f5d724ee4bc38a6b89edc41244c47d1489e8..995728ce16bdf73ad65793d74fa26762343b54d6 100644 (file)
@@ -217,6 +217,8 @@ properly handle destruction of equipment carried by monsters hit by
 don't exercize or abuse wisdom when rumors get used for random graffiti
 create_object() created lizard corpses without timers and troll corpses with
        their revive timers, then changed the corpsenm field
+when a potion of acid was dropped into water and exploded, nethack would
+       continue to use already freed memory and later might panic or crash
 
 
 Platform- and/or Interface-Specific Fixes
index 5e1bb238390c4bda5270714324773f14462950ec..ea7c19a6a46990d59a800ed5609d3f1bdf09d81b 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)extern.h   3.5     2004/06/12      */
+/*     SCCS Id: @(#)extern.h   3.5     2006/05/08      */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2173,7 +2173,7 @@ E void FDECL(fill_pit, (int,int));
 E int FDECL(float_down, (long, long));
 E void NDECL(climb_pit);
 E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P));
-E void FDECL(water_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P));
+E void FDECL(water_damage, (struct obj **,BOOLEAN_P,BOOLEAN_P));
 E boolean NDECL(drown);
 E void FDECL(drain_en, (int));
 E int NDECL(dountrap);
index 718ad2f38cccf9f475d28210c82fda2389a87c0b..fbefe5f1eaec4100cd6d8b426c8b3944c49935a1 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)do.c       3.5     2006/03/20      */
+/*     SCCS Id: @(#)do.c       3.5     2006/05/08      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -129,9 +129,9 @@ boolean pushing;
  * away.
  */
 boolean
-flooreffects(obj,x,y,verb)
+flooreffects(obj, x, y, verb)
 struct obj *obj;
-int x,y;
+int x, y;
 const char *verb;
 {
        struct trap *t;
@@ -192,8 +192,8 @@ const char *verb;
                return fire_damage(obj, FALSE, FALSE, x, y);
        } else if (is_pool(x, y)) {
                /* Reasonably bulky objects (arbitrary) splash when dropped.
-                * If you're floating above the water even small things make noise.
-                * Stuff dropped near fountains always misses */
+                * If you're floating above the water even small things make
+                * noise.  Stuff dropped near fountains always misses */
                if ((Blind || (Levitation || Flying)) && !Deaf &&
                    ((x == u.ux) && (y == u.uy))) {
                    if (!Underwater) {
@@ -206,7 +206,8 @@ const char *verb;
                    map_background(x, y, 0);
                    newsym(x, y);
                }
-               water_damage(obj, FALSE, FALSE);
+               water_damage(&obj, FALSE, FALSE);
+               if (!obj) return TRUE;
        } else if (u.ux == x && u.uy == y &&
                (t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) {
                if (Blind && !Deaf)
index ffcb6a5a6b7fbeabae39fa5c3e87a3a55d51aa8b..708a1c698361d6f765a38884d8dcb5fa4fc5aec7 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)fountain.c 3.5     2005/06/22      */
+/*     SCCS Id: @(#)fountain.c 3.5     2006/05/08      */
 /*     Copyright Scott R. Turner, srt@ucla, 10/27/86 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -125,7 +125,7 @@ genericptr_t poolcnt;
        levl[x][y].typ = POOL;
        /* No kelp! */
        del_engr_at(x, y);
-       water_damage(level.objects[x][y], FALSE, TRUE);
+       water_damage(&level.objects[x][y], FALSE, TRUE);
 
        if ((mtmp = m_at(x, y)) != 0)
                (void) minliquid(mtmp);
index 15c4395a95d918e191c5fa23a7c17b4e87d0c482..623a6d902e6504203f28d03520c3f9f92619eb62 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)mon.c      3.5     2006/04/14      */
+/*     SCCS Id: @(#)mon.c      3.5     2006/05/08      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -398,7 +398,7 @@ register struct monst *mtmp;
     if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) {
        if (split_mon(mtmp, (struct monst *)0))
            dryup(mtmp->mx, mtmp->my, FALSE);
-       if (inpool) water_damage(mtmp->minvent, FALSE, FALSE);
+       if (inpool) water_damage(&mtmp->minvent, FALSE, FALSE);
        return (0);
     } else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
        int dam = d(2,6);
@@ -410,7 +410,7 @@ register struct monst *mtmp;
            mondead(mtmp);
            if (mtmp->mhp < 1) return (1);
        }
-       water_damage(mtmp->minvent, FALSE, FALSE);
+       water_damage(&mtmp->minvent, FALSE, FALSE);
        return (0);
     }
 
@@ -463,8 +463,8 @@ register struct monst *mtmp;
            }
            mondead(mtmp);
            if (mtmp->mhp > 0) {
+               water_damage(&mtmp->minvent, FALSE, FALSE);
                (void) rloc(mtmp, FALSE);
-               water_damage(mtmp->minvent, FALSE, FALSE);
                return 0;
            }
            return (1);
index 44252b23f436724c6d6d66ff67651d72a01a6d48..b017c0535988ef7b96cc64b4dffe117dc81c2c95 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)objnam.c   3.5     2006/04/14      */
+/*     SCCS Id: @(#)objnam.c   3.5     2006/05/08      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2583,7 +2583,7 @@ srch:
                        del_engr_at(u.ux, u.uy);
                        pline("A pool.");
                        /* Must manually make kelp! */
-                       water_damage(level.objects[u.ux][u.uy], FALSE, TRUE);
+                       water_damage(&level.objects[u.ux][u.uy], FALSE, TRUE);
                        newsym(u.ux, u.uy);
                        return &zeroobj;
                }
index f56e5bee98b1e1388b8f41f145f168d4fdcbb3ac..f567f4cf11d3a13e45e0cfcfcbb8c8876d25eff0 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)trap.c     3.5     2006/04/14      */
+/*     SCCS Id: @(#)trap.c     3.5     2006/05/08      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2860,11 +2860,21 @@ xchar x, y;
 }
 
 void
-water_damage(obj, force, here)
-register struct obj *obj;
-register boolean force, here;
+water_damage(objp, force, here)
+struct obj **objp;
+boolean force, here;
 {
-       struct obj *otmp;
+       register struct obj *obj = *objp, *otmp;
+       boolean loose_obj = (obj && obj->where == OBJ_FREE);
+
+       if (loose_obj && (obj->nobj || obj->nexthere)) {
+               /* [this should actually be a panic()] */
+               impossible("water_damage: loose object has%s%s%s list%s?",
+                          obj->nobj ? " nobj" : "",
+                          (obj->nobj && obj->nexthere) ? " and" : "",
+                          obj->nexthere ? " nexthere" : "",
+                          (obj->nobj && obj->nexthere) ? "s" : "");
+       }
 
        /* Scrolls, spellbooks, potions, weapons and
           pieces of armor may get affected by the water */
@@ -2879,7 +2889,7 @@ register boolean force, here;
                        if (force || !rn2(2)) obj->greased = 0;
                } else if(Is_container(obj) && !Is_box(obj) &&
                        (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
-                       water_damage(obj->cobj, force, FALSE);
+                       water_damage(&obj->cobj, force, FALSE);
                } else if (!force && (Luck + 5) > rn2(20)) {
                        /*  chance per item of sustaining damage:
                         *      max luck (full moon):    5%
@@ -2902,8 +2912,14 @@ register boolean force, here;
                        else obj->otyp = SPE_BLANK_PAPER;
                } else if (obj->oclass == POTION_CLASS) {
                        if (obj->otyp == POT_ACID) {
-                               /* damage player/monster? */
+                               /* [should we damage player/monster?] */
                                pline("A potion explodes!");
+                               /* let caller know that obj has gone away
+                                  [when obj is part of a list, delobj()'s
+                                  obj_extract_self() takes care of this;
+                                  for loose_obj, obj should always equal
+                                  *objp and otmp should always be null] */
+                               if (loose_obj && obj == *objp) *objp = otmp;
                                delobj(obj);
                                continue;
                        } else if (obj->odiluted) {
@@ -3024,7 +3040,7 @@ drown()
                        Hallucination ? "the Titanic" : "a rock");
        }
 
-       water_damage(invent, FALSE, FALSE);
+       water_damage(&invent, FALSE, FALSE);
 
        if (u.umonnum == PM_GREMLIN && rn2(3))
            (void)split_mon(&youmonst, (struct monst *)0);