From 03eb70acab772db1a59abe93f279c958024c9729 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sat, 28 Jul 2007 03:26:45 +0000 Subject: [PATCH] fix segfault from splitting 1hp long worm Fix the crash From a bug report, where having the hit that cuts a long worm into two also take the original down to 1 HP would result in clone_mon() returning null and nethack crashing due to a segmentation fault or access violation. The same thing could happen if there's been enough long worms created to get them flagged as extinct. This bug was only present in 3.4.3. Prior to that, cut_worm() did its own monster creation inline instead of calling clone_mon(), ignoring extinction and too-low hit points. --- doc/fixes34.4 | 2 ++ src/worm.c | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/doc/fixes34.4 b/doc/fixes34.4 index b967cfce5..be949c6da 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -361,6 +361,8 @@ monsters who want the Amulet won't attack the Wizard to try to get it opening or closing the castle drawbridge via music consumes a turn could get "suddenly you cannot see the " while invisible mon remained displayed due to telepathy or extended detection +cutting a long worm in half would trigger segfault/accvio crash if the hit + took parent down to 1 hit point or if long worms had become extinct Platform- and/or Interface-Specific Fixes diff --git a/src/worm.c b/src/worm.c index 95af0fc28..aac8ce41f 100644 --- a/src/worm.c +++ b/src/worm.c @@ -366,19 +366,29 @@ cutworm(worm, x, y, weap) * it's head at "curr" and its tail at "new_tail". */ + new_worm = 0; + new_wnum = rn2(3) ? 0 : get_wormno(); + if (new_wnum) { + remove_monster(x, y); /* clone_mon puts new head here */ + /* clone_mon() will fail if enough long worms have been + created to have them be marked as extinct or if the hit + that cut the current one has dropped it down to 1 HP */ + new_worm = clone_mon(worm, x, y); + } + /* Sometimes the tail end dies. */ - if (rn2(3) || !(new_wnum = get_wormno())) { - if (context.mon_moving) - pline("Part of the tail of %s is cut off.", mon_nam(worm)); - else + if (!new_worm) { + if (context.mon_moving) { + if (canspotmon(worm)) + pline("Part of %s tail has been cut off.", + s_suffix(mon_nam(worm))); + } else You("cut part of the tail off of %s.", mon_nam(worm)); toss_wsegs(new_tail, TRUE); if (worm->mhp > 1) worm->mhp /= 2; return; } - remove_monster(x, y); /* clone_mon puts new head here */ - new_worm = clone_mon(worm, x, y); new_worm->wormno = new_wnum; /* affix new worm number */ new_worm->mcloned = 0; /* treat second worm as a normal monster */