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.
This commit is contained in:
@@ -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
|
don't exercize or abuse wisdom when rumors get used for random graffiti
|
||||||
create_object() created lizard corpses without timers and troll corpses with
|
create_object() created lizard corpses without timers and troll corpses with
|
||||||
their revive timers, then changed the corpsenm field
|
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
|
Platform- and/or Interface-Specific Fixes
|
||||||
|
|||||||
@@ -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. */
|
/* Copyright (c) Steve Creps, 1988. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* 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 int FDECL(float_down, (long, long));
|
||||||
E void NDECL(climb_pit);
|
E void NDECL(climb_pit);
|
||||||
E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P));
|
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 boolean NDECL(drown);
|
||||||
E void FDECL(drain_en, (int));
|
E void FDECL(drain_en, (int));
|
||||||
E int NDECL(dountrap);
|
E int NDECL(dountrap);
|
||||||
|
|||||||
13
src/do.c
13
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. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -129,9 +129,9 @@ boolean pushing;
|
|||||||
* away.
|
* away.
|
||||||
*/
|
*/
|
||||||
boolean
|
boolean
|
||||||
flooreffects(obj,x,y,verb)
|
flooreffects(obj, x, y, verb)
|
||||||
struct obj *obj;
|
struct obj *obj;
|
||||||
int x,y;
|
int x, y;
|
||||||
const char *verb;
|
const char *verb;
|
||||||
{
|
{
|
||||||
struct trap *t;
|
struct trap *t;
|
||||||
@@ -192,8 +192,8 @@ const char *verb;
|
|||||||
return fire_damage(obj, FALSE, FALSE, x, y);
|
return fire_damage(obj, FALSE, FALSE, x, y);
|
||||||
} else if (is_pool(x, y)) {
|
} else if (is_pool(x, y)) {
|
||||||
/* Reasonably bulky objects (arbitrary) splash when dropped.
|
/* Reasonably bulky objects (arbitrary) splash when dropped.
|
||||||
* If you're floating above the water even small things make noise.
|
* If you're floating above the water even small things make
|
||||||
* Stuff dropped near fountains always misses */
|
* noise. Stuff dropped near fountains always misses */
|
||||||
if ((Blind || (Levitation || Flying)) && !Deaf &&
|
if ((Blind || (Levitation || Flying)) && !Deaf &&
|
||||||
((x == u.ux) && (y == u.uy))) {
|
((x == u.ux) && (y == u.uy))) {
|
||||||
if (!Underwater) {
|
if (!Underwater) {
|
||||||
@@ -206,7 +206,8 @@ const char *verb;
|
|||||||
map_background(x, y, 0);
|
map_background(x, y, 0);
|
||||||
newsym(x, y);
|
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 &&
|
} else if (u.ux == x && u.uy == y &&
|
||||||
(t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) {
|
(t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) {
|
||||||
if (Blind && !Deaf)
|
if (Blind && !Deaf)
|
||||||
|
|||||||
@@ -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 */
|
/* Copyright Scott R. Turner, srt@ucla, 10/27/86 */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ genericptr_t poolcnt;
|
|||||||
levl[x][y].typ = POOL;
|
levl[x][y].typ = POOL;
|
||||||
/* No kelp! */
|
/* No kelp! */
|
||||||
del_engr_at(x, y);
|
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)
|
if ((mtmp = m_at(x, y)) != 0)
|
||||||
(void) minliquid(mtmp);
|
(void) minliquid(mtmp);
|
||||||
|
|||||||
@@ -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. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* 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 (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) {
|
||||||
if (split_mon(mtmp, (struct monst *)0))
|
if (split_mon(mtmp, (struct monst *)0))
|
||||||
dryup(mtmp->mx, mtmp->my, FALSE);
|
dryup(mtmp->mx, mtmp->my, FALSE);
|
||||||
if (inpool) water_damage(mtmp->minvent, FALSE, FALSE);
|
if (inpool) water_damage(&mtmp->minvent, FALSE, FALSE);
|
||||||
return (0);
|
return (0);
|
||||||
} else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
|
} else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
|
||||||
int dam = d(2,6);
|
int dam = d(2,6);
|
||||||
@@ -410,7 +410,7 @@ register struct monst *mtmp;
|
|||||||
mondead(mtmp);
|
mondead(mtmp);
|
||||||
if (mtmp->mhp < 1) return (1);
|
if (mtmp->mhp < 1) return (1);
|
||||||
}
|
}
|
||||||
water_damage(mtmp->minvent, FALSE, FALSE);
|
water_damage(&mtmp->minvent, FALSE, FALSE);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,8 +463,8 @@ register struct monst *mtmp;
|
|||||||
}
|
}
|
||||||
mondead(mtmp);
|
mondead(mtmp);
|
||||||
if (mtmp->mhp > 0) {
|
if (mtmp->mhp > 0) {
|
||||||
|
water_damage(&mtmp->minvent, FALSE, FALSE);
|
||||||
(void) rloc(mtmp, FALSE);
|
(void) rloc(mtmp, FALSE);
|
||||||
water_damage(mtmp->minvent, FALSE, FALSE);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
|
|||||||
@@ -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. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -2583,7 +2583,7 @@ srch:
|
|||||||
del_engr_at(u.ux, u.uy);
|
del_engr_at(u.ux, u.uy);
|
||||||
pline("A pool.");
|
pline("A pool.");
|
||||||
/* Must manually make kelp! */
|
/* 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);
|
newsym(u.ux, u.uy);
|
||||||
return &zeroobj;
|
return &zeroobj;
|
||||||
}
|
}
|
||||||
|
|||||||
32
src/trap.c
32
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. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -2860,11 +2860,21 @@ xchar x, y;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
water_damage(obj, force, here)
|
water_damage(objp, force, here)
|
||||||
register struct obj *obj;
|
struct obj **objp;
|
||||||
register boolean force, here;
|
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
|
/* Scrolls, spellbooks, potions, weapons and
|
||||||
pieces of armor may get affected by the water */
|
pieces of armor may get affected by the water */
|
||||||
@@ -2879,7 +2889,7 @@ register boolean force, here;
|
|||||||
if (force || !rn2(2)) obj->greased = 0;
|
if (force || !rn2(2)) obj->greased = 0;
|
||||||
} else if(Is_container(obj) && !Is_box(obj) &&
|
} else if(Is_container(obj) && !Is_box(obj) &&
|
||||||
(obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
|
(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)) {
|
} else if (!force && (Luck + 5) > rn2(20)) {
|
||||||
/* chance per item of sustaining damage:
|
/* chance per item of sustaining damage:
|
||||||
* max luck (full moon): 5%
|
* max luck (full moon): 5%
|
||||||
@@ -2902,8 +2912,14 @@ register boolean force, here;
|
|||||||
else obj->otyp = SPE_BLANK_PAPER;
|
else obj->otyp = SPE_BLANK_PAPER;
|
||||||
} else if (obj->oclass == POTION_CLASS) {
|
} else if (obj->oclass == POTION_CLASS) {
|
||||||
if (obj->otyp == POT_ACID) {
|
if (obj->otyp == POT_ACID) {
|
||||||
/* damage player/monster? */
|
/* [should we damage player/monster?] */
|
||||||
pline("A potion explodes!");
|
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);
|
delobj(obj);
|
||||||
continue;
|
continue;
|
||||||
} else if (obj->odiluted) {
|
} else if (obj->odiluted) {
|
||||||
@@ -3024,7 +3040,7 @@ drown()
|
|||||||
Hallucination ? "the Titanic" : "a rock");
|
Hallucination ? "the Titanic" : "a rock");
|
||||||
}
|
}
|
||||||
|
|
||||||
water_damage(invent, FALSE, FALSE);
|
water_damage(&invent, FALSE, FALSE);
|
||||||
|
|
||||||
if (u.umonnum == PM_GREMLIN && rn2(3))
|
if (u.umonnum == PM_GREMLIN && rn2(3))
|
||||||
(void)split_mon(&youmonst, (struct monst *)0);
|
(void)split_mon(&youmonst, (struct monst *)0);
|
||||||
|
|||||||
Reference in New Issue
Block a user