]> granicus.if.org Git - nethack/commitdiff
fix segfault from splitting 1hp long worm
authornethack.rankin <nethack.rankin>
Sat, 28 Jul 2007 03:26:45 +0000 (03:26 +0000)
committernethack.rankin <nethack.rankin>
Sat, 28 Jul 2007 03:26:45 +0000 (03:26 +0000)
     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
src/worm.c

index b967cfce51999f54ad8bc36fd78ce0c9838161d8..be949c6da8b5804a38e365f2bb3cb691f0e2cc4d 100644 (file)
@@ -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 <mon>" 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
index 95af0fc285bb3de973899d87c3080e07bbdfcdc5..aac8ce41f48e181cdb064f68643e9660d7afe6df 100644 (file)
@@ -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 */