diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 81f06cce1..c0240e8ce 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -928,6 +928,12 @@ ball and chain could be accessed after having been freed if bones were saved early post-3.4.3 tried to fix the "naming artifacts trick" which could be used to distinguish the type of some undiscovered items, but using a name that only matched an artifact after capitalization was exploitable +the u.ustuck hierarchy is: swallowed by ustuck, hero poly'd into sticky form + is holding ustuck even if ustuck is sticky, ustuck is holding hero; + but some code assumed that the first two cases were reversed and + could make formerly sticky pold'd hero clear ustuck, leaving hero + swallowed by nothing (u.uswallow==1 with u.ustuck==NULL); that could + cause a crash if u.ustuck got dereferenced Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/botl.c b/src/botl.c index 5a79f6e3f..5d97eff97 100644 --- a/src/botl.c +++ b/src/botl.c @@ -887,23 +887,30 @@ bot_via_windowport(void) && !condtests[bl_tethered].test); } condtests[bl_grab].test = condtests[bl_held].test +#if 0 + = condtests[bl_engulfed].test +#endif = condtests[bl_holding].test = FALSE; if (u.ustuck) { - if (Upolyd && sticks(g.youmonst.data)) { + /* it is possible for a hero in sticks() form to be swallowed, + so swallowed needs to be checked first; it is not possible for + a hero in sticks() form to be held--sticky hero does the holding + even if u.ustuck is also a holder */ + if (u.uswallow) { + /* engulfed/swallowed isn't currently a tracked status condition; + "held" might look odd for it but seems better than blank */ +#if 0 + test_if_enabled(bl_engulfed) = TRUE; +#else + test_if_enabled(bl_held) = TRUE; +#endif + } else if (Upolyd && sticks(g.youmonst.data)) { test_if_enabled(bl_holding) = TRUE; } else { + /* grab == hero is held by sea monster and about to be drowned; + held == hero is held by something else and can't move away */ test_if_enabled(bl_grab) = (u.ustuck->data->mlet == S_EEL); -#if 0 - test_if_enabled(bl_engulfed) = u.uswallow ? TRUE : FALSE; - test_if_enabled(bl_held) = (!condtests[bl_grab].test - && !condtests[bl_engulfed].test); -#else - test_if_enabled(bl_held) = (!condtests[bl_grab].test - /* engulfed/swallowed isn't currently a tracked condition - and showing "held" when in that state looks a bit odd, - so suppress "held" if swallowed */ - && !u.uswallow); -#endif + test_if_enabled(bl_held) = !condtests[bl_grab].test; } } condtests[bl_blind].test = (Blind) ? TRUE : FALSE; diff --git a/src/cmd.c b/src/cmd.c index 293c611e2..73d175105 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -146,6 +146,7 @@ static void mon_chain(winid, const char *, struct monst *, boolean, long *, long *); static void contained_stats(winid, const char *, long *, long *); static void misc_stats(winid, long *, long *); +static void you_sanity_check(void); static boolean accept_menu_prefix(const struct ext_func_tab *); static void reset_cmd_vars(boolean); static void mcmd_addmenu(winid, int, const char *); @@ -3630,10 +3631,25 @@ wiz_show_stats(void) RESTORE_WARNING_FORMAT_NONLITERAL +static void +you_sanity_check(void) +{ + if (u.uswallow && !u.ustuck) { + /* this probably ought to be panic() */ + impossible("sanity_check: swallowed by nothing?"); + display_nhwindow(WIN_MESSAGE, TRUE); + /* try to recover from whatever the problem is */ + u.uswallow = 0; + u.uswldtim = 0; + docrt(); + } + (void) check_invent_gold("invent"); +} + void sanity_check(void) { - (void) check_invent_gold("invent"); + you_sanity_check(); obj_sanity_check(); timer_sanity_check(); mon_sanity_check(); diff --git a/src/zap.c b/src/zap.c index 52a0558e2..095e852dc 100644 --- a/src/zap.c +++ b/src/zap.c @@ -489,13 +489,7 @@ release_hold(void) if (!mtmp) { impossible("release_hold when not held?"); - } else if (sticks(g.youmonst.data)) { - /* order matters if 'holding' status condition is enabled; - set_ustuck() will set flag for botl update, You() pline will - trigger a status update with "UHold" removed */ - set_ustuck((struct monst *) 0); - You("release %s.", mon_nam(mtmp)); - } else if (u.uswallow) { + } else if (u.uswallow) { /* possible for sticky hero to be swallowed */ if (is_animal(mtmp->data)) { if (!Blind) pline("%s opens its mouth!", Monnam(mtmp)); @@ -504,6 +498,12 @@ release_hold(void) } /* gives "you get regurgitated" or "you get expelled from " */ expels(mtmp, mtmp->data, TRUE); + } else if (sticks(g.youmonst.data)) { + /* order matters if 'holding' status condition is enabled; + set_ustuck() will set flag for botl update, You() pline will + trigger a status update with "UHold" removed */ + set_ustuck((struct monst *) 0); + You("release %s.", mon_nam(mtmp)); } else { /* held but not swallowed */ char relbuf[BUFSZ];