From 97181813225447f75785179040be52588d05a8c9 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Apr 2023 03:03:17 -0700 Subject: [PATCH] shapechanger dropping boulders Something I noticed while looking over the recent report about hug attacks. If a monster carrying one or more boulders (picked up while in giant form) polymorphs into a non-giant, it will drop them. If that happens while it's trapped, it could be killed. newcham() would use a stale pointer to continue traversing its inventory after it was dead and its possessions had been dropped. I managed to get a chameleon-as-giant carrying boulders and some other stuff trapped in a bear trap and then transform, but the few attempts I made never killed off its next form so I wasn't able to induce a crash to verify that a problem would actually occur. --- doc/fixes3-7-0.txt | 6 +++++- src/mon.c | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 373dcb22d..19c4c4d82 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1,4 +1,4 @@ -HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1146 $ $NHDT-Date: 1680935652 2023/04/08 06:34:12 $ +HDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1152 $ $NHDT-Date: 1681293789 2023/04/12 10:03:09 $ General Fixes and Modified Features ----------------------------------- @@ -1135,6 +1135,10 @@ if hero had passes-walls capability and was at the location of a closed door, attempting to use 'o' on own spot reported "you don't find anything here to loot"; change to open door for '.' (or '<'), only loot for '>' items thrown by monster landing on an altar did not show BUC flash +a chameleon in giant form who gets trapped (bear trap?) while carrying + boulders and changes shape could be killed when dropping them; + shape-change traversal of its inventory would continue after it + dropped everything, possibly resulting in a crash Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/src/mon.c b/src/mon.c index 88e087b0f..e1dba116d 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 mon.c $NHDT-Date: 1679896593 2023/03/27 05:56:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.491 $ */ +/* NetHack 3.7 mon.c $NHDT-Date: 1681293789 2023/04/12 10:03:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.494 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4735,7 +4735,7 @@ newcham( /* (this code used to try to adjust the monster's health based on a normal one of its type but there are too many special cases - which need to handled in order to do that correctly, so just + which need to be handled in order to do that correctly, so just give the new form the same proportion of HP as its old one had) */ hpn = mtmp->mhp; hpd = mtmp->mhpmax; @@ -4808,8 +4808,15 @@ newcham( /* update swallow glyphs for new monster */ swallowed(0); } - } else if (!sticks(mdat) && !sticks(gy.youmonst.data)) + } else if ((!sticks(mdat) && !sticks(gy.youmonst.data)) + /* sticky hero can't continue to hold mtmp if it has + turned into a non-solid creature; we don't use + uunstick() for that because its message would be + shown out of sequence [before 'if (msg)' below]; + unstuck() doesn't issue any messages */ + || unsolid(mdat)) { unstuck(mtmp); + } } if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) { @@ -4856,7 +4863,9 @@ newcham( if (mtmp->minvent && !throws_rocks(mdat)) { register struct obj *otmp, *otmp2; - for (otmp = mtmp->minvent; otmp; otmp = otmp2) { + /* DEADMONSTER(): it is possible for flooreffects() to kill mtmp; + the rest of its inventory would be dropped making otmp2 stale */ + for (otmp = mtmp->minvent; otmp && !DEADMONSTER(mtmp); otmp = otmp2) { otmp2 = otmp->nobj; if (otmp->otyp == BOULDER) { /* this keeps otmp from being polymorphed in the