fix #H7659 - accessing freed memory by cutworm()
hmon() can destroy the weapon being used, and known_hitum() would still pass the pointer to the freed object to cutworm(). Remember the relevant weapon attribute before using and maybe freeing the object, then pass that attribute instead of the whole weapon. Also pass 'more-likely-to-cut' for axes in addition to blades. thimonst() behaved similarly, although due to much different code paths none of the objects that might get to hmon() were then passed to cutworm(), so it wasn't vulnerable. But pass 'more-likely-to-cut' for axes instead of for blades when thrown.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 dothrow.c $NHDT-Date: 1525012611 2018/04/29 14:36:51 $ $NHDT-Branch: master $:$NHDT-Revision: 1.137 $ */
|
||||
/* NetHack 3.6 dothrow.c $NHDT-Date: 1543892215 2018/12/04 02:56:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.152 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2013. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -1652,13 +1652,16 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
|
||||
}
|
||||
|
||||
if (tmp >= dieroll) {
|
||||
boolean wasthrown = (thrownobj != 0);
|
||||
boolean wasthrown = (thrownobj != 0),
|
||||
/* remember weapon attribute; hmon() might destroy obj */
|
||||
chopper = is_axe(obj);
|
||||
|
||||
/* attack hits mon */
|
||||
if (hmode == HMON_APPLIED)
|
||||
u.uconduct.weaphit++;
|
||||
if (hmon(mon, obj, hmode, dieroll)) { /* mon still alive */
|
||||
cutworm(mon, bhitpos.x, bhitpos.y, obj);
|
||||
if (mon->wormno)
|
||||
cutworm(mon, bhitpos.x, bhitpos.y, chopper);
|
||||
}
|
||||
exercise(A_DEX, TRUE);
|
||||
/* if hero was swallowed and projectile killed the engulfer,
|
||||
@@ -1668,8 +1671,9 @@ register struct obj *obj; /* thrownobj or kickedobj or uwep */
|
||||
if (wasthrown && !thrownobj)
|
||||
return 1;
|
||||
|
||||
/* projectiles other than magic stones
|
||||
sometimes disappear when thrown */
|
||||
/* projectiles other than magic stones sometimes disappear
|
||||
when thrown; projectiles aren't among the types of weapon
|
||||
that hmon() might have destroyed so obj is intact */
|
||||
if (objects[otyp].oc_skill < P_NONE
|
||||
&& objects[otyp].oc_skill > -P_BOOMERANG
|
||||
&& !objects[otyp].oc_magic) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 uhitm.c $NHDT-Date: 1542765366 2018/11/21 01:56:06 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.185 $ */
|
||||
/* NetHack 3.6 uhitm.c $NHDT-Date: 1543892215 2018/12/04 02:56:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.195 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2012. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -449,7 +449,9 @@ int rollneeded, armorpenalty; /* for monks */
|
||||
struct attack *uattk;
|
||||
int dieroll;
|
||||
{
|
||||
register boolean malive = TRUE;
|
||||
boolean malive = TRUE,
|
||||
/* hmon() might destroy weapon; remember aspect for cutworm */
|
||||
slice_or_chop = (weapon && (is_blade(weapon) || is_axe(weapon)));
|
||||
|
||||
if (override_confirmation) {
|
||||
/* this may need to be generalized if weapons other than
|
||||
@@ -490,7 +492,7 @@ int dieroll;
|
||||
u.uconduct.weaphit = oldweaphit;
|
||||
}
|
||||
if (mon->wormno && *mhit)
|
||||
cutworm(mon, x, y, weapon);
|
||||
cutworm(mon, x, y, slice_or_chop);
|
||||
}
|
||||
}
|
||||
return malive;
|
||||
|
||||
16
src/worm.c
16
src/worm.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 worm.c $NHDT-Date: 1456528599 2016/02/26 23:16:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
|
||||
/* NetHack 3.6 worm.c $NHDT-Date: 1543892216 2018/12/04 02:56:56 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.28 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2009. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -314,10 +314,10 @@ register struct monst *worm;
|
||||
* that both halves will survive.
|
||||
*/
|
||||
void
|
||||
cutworm(worm, x, y, weap)
|
||||
cutworm(worm, x, y, cuttier)
|
||||
struct monst *worm;
|
||||
xchar x, y;
|
||||
struct obj *weap;
|
||||
boolean cuttier; /* hit is by wielded blade or axe or by thrown axe */
|
||||
{
|
||||
register struct wseg *curr, *new_tail;
|
||||
register struct monst *new_worm;
|
||||
@@ -330,12 +330,10 @@ struct obj *weap;
|
||||
if (x == worm->mx && y == worm->my)
|
||||
return; /* hit on head */
|
||||
|
||||
/* cutting goes best with a bladed weapon */
|
||||
cut_chance = rnd(20); /* Normally 1-16 does not cut */
|
||||
/* Normally 17-20 does */
|
||||
|
||||
if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */
|
||||
cut_chance += 10; /* 7-20 does */
|
||||
/* cutting goes best with a cuttier weapon */
|
||||
cut_chance = rnd(20); /* Normally 1-16 does not cut, 17-20 does, */
|
||||
if (cuttier)
|
||||
cut_chance += 10; /* with a blade 1- 6 does not cut, 7-20 does. */
|
||||
|
||||
if (cut_chance < 17)
|
||||
return; /* not good enough */
|
||||
|
||||
Reference in New Issue
Block a user