From: nethack.rankin Date: Thu, 11 May 2006 03:26:55 +0000 (+0000) Subject: water vs acid X-Git-Tag: MOVE2GIT~1024 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a73d997034c7d66b8db2023a6fc5fbb094fd5384;p=nethack water vs acid 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. --- diff --git a/doc/fixes34.4 b/doc/fixes34.4 index e2c7f5d72..995728ce1 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -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 diff --git a/include/extern.h b/include/extern.h index 5e1bb2383..ea7c19a6a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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); diff --git a/src/do.c b/src/do.c index 718ad2f38..fbefe5f1e 100644 --- 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) diff --git a/src/fountain.c b/src/fountain.c index ffcb6a5a6..708a1c698 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -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); diff --git a/src/mon.c b/src/mon.c index 15c4395a9..623a6d902 100644 --- 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); diff --git a/src/objnam.c b/src/objnam.c index 44252b23f..b017c0535 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -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; } diff --git a/src/trap.c b/src/trap.c index f56e5bee9..f567f4cf1 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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);