fix pull request #621 - potential divide by 0

The pull request by argrath changes weight_cap() to never return a
value less than 1 because try_lift() divides by that return value
and a 0 would trigger a crash.  The code involved is used when
attempting to pull a monster out of a pit via #untrap.

I'm fairly sure that weight_cap() can never produce a value that's
less than 1 already, but have put in a variation of the PR's fix.
I've also implemented a different fix that removes the division
from try_lift().  The original code seems to have gone out of its
way to avoid calculating inv_weight() twice, but doing the latter
(for the once in a hundred games where it might happen) greatly
simplifies things by removing details of carrying capacity.

Fixes #621
This commit is contained in:
PatR
2021-10-25 14:51:26 -07:00
parent 27fcf8999f
commit b4908f6928
3 changed files with 20 additions and 20 deletions
+2
View File
@@ -660,6 +660,8 @@ using 'F'orcefight against iron bars while wielding something breakable could
called twice and could yield results that conflicted called twice and could yield results that conflicted
have applying a polearm give feedback similar to 'F' for melee weapon when have applying a polearm give feedback similar to 'F' for melee weapon when
attacking a wall or boulder attacking a wall or boulder
if weight_cap() ever returned 0 (which probably can't happen), using #untrap
to pull a monster out of a pit would trigger a divide by 0 crash
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
+1 -3
View File
@@ -3330,8 +3330,6 @@ weight_cap(void)
if (EWounded_legs & RIGHT_SIDE) if (EWounded_legs & RIGHT_SIDE)
carrcap -= 100; carrcap -= 100;
} }
if (carrcap < 0)
carrcap = 0;
} }
if (ELevitation != save_ELev || BLevitation != save_BLev) { if (ELevitation != save_ELev || BLevitation != save_BLev) {
@@ -3340,7 +3338,7 @@ weight_cap(void)
float_vs_flight(); float_vs_flight();
} }
return (int) carrcap; return (int) max(carrcap, 1L); /* never return 0 */
} }
/* returns how far beyond the normal capacity the player is currently. */ /* returns how far beyond the normal capacity the player is currently. */
+17 -17
View File
@@ -4687,18 +4687,15 @@ disarm_shooting_trap(struct trap* ttmp, int otyp)
return 1; return 1;
} }
/* Is the weight too heavy? /* trying to #untrap a monster from a pit; is the weight too heavy? */
* Formula as in near_capacity() & check_capacity() */
static int static int
try_lift( try_lift(
struct monst *mtmp, struct monst *mtmp, /* trapped monster */
struct trap *ttmp, struct trap *ttmp, /* pit, possibly made by hero, or spiked pit */
int wt, int xtra_wt, /* monster (corpse weight) + (stuff ? minvent weight : 0) */
boolean stuff) boolean stuff) /* False: monster w/o minvent; True: w/ minvent */
{ {
int wc = weight_cap(); if (calc_capacity(xtra_wt) >= HVY_ENCUMBER) {
if (((wt * 2) / wc) >= HVY_ENCUMBER) {
pline("%s is %s for you to lift.", Monnam(mtmp), pline("%s is %s for you to lift.", Monnam(mtmp),
stuff ? "carrying too much" : "too heavy"); stuff ? "carrying too much" : "too heavy");
if (!ttmp->madeby_u && !mtmp->mpeaceful && mtmp->mcanmove if (!ttmp->madeby_u && !mtmp->mpeaceful && mtmp->mcanmove
@@ -4719,7 +4716,7 @@ help_monster_out(
struct monst *mtmp, struct monst *mtmp,
struct trap *ttmp) struct trap *ttmp)
{ {
int wt; int xtra_wt;
struct obj *otmp; struct obj *otmp;
boolean uprob; boolean uprob;
@@ -4788,15 +4785,18 @@ help_monster_out(
} }
/* is the monster too heavy? */ /* is the monster too heavy? */
wt = inv_weight() + mtmp->data->cwt; xtra_wt = mtmp->data->cwt;
if (!try_lift(mtmp, ttmp, wt, FALSE)) if (!try_lift(mtmp, ttmp, xtra_wt, FALSE))
return 1; return 1;
/* is the monster with inventory too heavy? */ /* monster without its inventory isn't too heavy; if it carries
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) anything, include that minvent weight and check again */
wt += otmp->owt; if (mtmp->minvent) {
if (!try_lift(mtmp, ttmp, wt, TRUE)) for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
return 1; xtra_wt += otmp->owt;
if (!try_lift(mtmp, ttmp, xtra_wt, TRUE))
return 1;
}
You("pull %s out of the pit.", mon_nam(mtmp)); You("pull %s out of the pit.", mon_nam(mtmp));
mtmp->mtrapped = 0; mtmp->mtrapped = 0;