From 95772261dcbd8d30dba0ead204d5955a541e0b66 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 13 Nov 2015 20:39:10 -0800 Subject: [PATCH] fix memory leak: obj->oextra->omonst->mextra The memory leak (monst->mextra->edog, monst->mextra->mname, monst->mextra for some monster were not released) I noticed recently was due to recording a pet's full monster attributes with its corpse. During save and restore, obj->oextra->omonst was being treated as a full-fledged monster so worked as intended, but when freed, omonst was treated as a black box and its mextra details weren't handled. --- include/extern.h | 5 +++-- src/mkobj.c | 36 ++++++++++++++++++++++++++---------- src/mon.c | 15 +++++++++------ src/zap.c | 7 +++---- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/include/extern.h b/include/extern.h index 54c6ed2b3..5add97a44 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1447124656 2015/11/10 03:04:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.515 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1447475941 2015/11/14 04:39:01 $ $NHDT-Branch: master $:$NHDT-Revision: 1.516 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1070,6 +1070,7 @@ E int FDECL(monhp_per_lvl, (struct monst *)); E void FDECL(newmonhp, (struct monst *, int)); E struct mextra *NDECL(newmextra); E void FDECL(copy_mextra, (struct monst *, struct monst *)); +E void FDECL(dealloc_mextra, (struct monst *)); E struct monst *FDECL(makemon, (struct permonst *, int, int, int)); E boolean FDECL(create_critters, (int, struct permonst *, BOOLEAN_P)); E struct permonst *NDECL(rndmonst); @@ -1203,7 +1204,7 @@ E const char *FDECL(waterbody_name, (XCHAR_P, XCHAR_P)); E struct oextra *NDECL(newoextra); E void FDECL(copy_oextra, (struct obj *, struct obj *)); -E void FDECL(dealloc_oextra, (struct oextra *)); +E void FDECL(dealloc_oextra, (struct obj *)); E void FDECL(newomonst, (struct obj *)); E void FDECL(free_omonst, (struct obj *)); E void FDECL(newomid, (struct obj *)); diff --git a/src/mkobj.c b/src/mkobj.c index bfc5b6cee..6b56739a2 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1446892448 2015/11/07 10:34:08 $ $NHDT-Branch: master $:$NHDT-Revision: 1.112 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1447475943 2015/11/14 04:39:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -79,21 +79,25 @@ newoextra() } void -dealloc_oextra(x) -struct oextra *x; +dealloc_oextra(o) +struct obj *o; { + struct oextra *x = o->oextra; + if (x) { if (x->oname) free((genericptr_t) x->oname); if (x->omonst) - free((genericptr_t) x->omonst); + free_omonst(o); /* 'o' rather than 'x' */ if (x->omid) free((genericptr_t) x->omid); if (x->olong) free((genericptr_t) x->olong); if (x->omailcmd) free((genericptr_t) x->omailcmd); + free((genericptr_t) x); + o->oextra = (struct oextra *) 0; } } @@ -104,8 +108,13 @@ struct obj *otmp; if (!otmp->oextra) otmp->oextra = newoextra(); if (!OMONST(otmp)) { - OMONST(otmp) = (struct monst *) alloc(sizeof (struct monst)); - (void) memset((genericptr_t) OMONST(otmp), 0, sizeof (struct monst)); + struct monst *m = newmonst(); + + /* newmonst() allocates memory but doesn't initialize anything */ + (void) memset((genericptr_t) m, 0, sizeof (struct monst)); + m->mextra = (struct mextra *) 0; + m->nmon = (struct monst *) 0; + OMONST(otmp) = m; } } @@ -113,9 +122,15 @@ void free_omonst(otmp) struct obj *otmp; { - if (otmp->oextra && OMONST(otmp)) { - free((genericptr_t) OMONST(otmp)); - OMONST(otmp) = (struct monst *) 0; + if (otmp->oextra) { + struct monst *m = OMONST(otmp); + + if (m) { + if (m->mextra) + dealloc_mextra(m); + free((genericptr_t) m); + OMONST(otmp) = (struct monst *) 0; + } } } @@ -1511,6 +1526,7 @@ struct monst *mtmp; newomonst(obj); if (has_omonst(obj)) { struct monst *mtmp2 = OMONST(obj); + *mtmp2 = *mtmp; mtmp2->mextra = (struct mextra *) 0; if (mtmp->data) @@ -2053,7 +2069,7 @@ struct obj *obj; kickedobj = 0; if (obj->oextra) - dealloc_oextra(obj->oextra); + dealloc_oextra(obj); free((genericptr_t) obj); } diff --git a/src/mon.c b/src/mon.c index 889599b84..8e251092c 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1446458009 2015/11/02 09:53:29 $ $NHDT-Branch: master $:$NHDT-Revision: 1.194 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1447475944 2015/11/14 04:39:04 $ $NHDT-Branch: master $:$NHDT-Revision: 1.196 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -18,7 +18,6 @@ STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *)); STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *)); STATIC_DCL int NDECL(pick_animal); STATIC_DCL void FDECL(kill_eggs, (struct obj *)); -STATIC_DCL void FDECL(dealloc_mextra, (struct mextra *)); STATIC_DCL int FDECL(pickvampshape, (struct monst *)); STATIC_DCL boolean FDECL(isspecmon, (struct monst *)); STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int)); @@ -1597,10 +1596,12 @@ struct monst *mtmp2, *mtmp1; MCORPSENM(mtmp2) = MCORPSENM(mtmp1); } -STATIC_OVL void -dealloc_mextra(x) -struct mextra *x; +void +dealloc_mextra(m) +struct monst *m; { + struct mextra *x = m->mextra; + if (x) { if (x->mname) free((genericptr_t) x->mname); @@ -1615,7 +1616,9 @@ struct mextra *x; if (x->edog) free((genericptr_t) x->edog); /* [no action needed for x->mcorpsenm] */ + free((genericptr_t) x); + m->mextra = (struct mextra *) 0; } } @@ -1626,7 +1629,7 @@ struct monst *mon; if (mon->nmon) panic("dealloc_monst with nmon"); if (mon->mextra) - dealloc_mextra(mon->mextra); + dealloc_mextra(mon); free((genericptr_t) mon); } diff --git a/src/zap.c b/src/zap.c index a88ee1b9e..34c4b6d31 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1446887542 2015/11/07 09:12:22 $ $NHDT-Branch: master $:$NHDT-Revision: 1.233 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1447475947 2015/11/14 04:39:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.235 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4462,9 +4462,8 @@ register struct obj *obj; /* no texts here! */ obj->owt = weight(obj); obj->dknown = obj->bknown = obj->rknown = 0; obj->known = objects[obj->otyp].oc_uses_known ? 0 : 1; - if (obj->oextra) - dealloc_oextra(obj->oextra); - obj->oextra = (struct oextra *) 0; + dealloc_oextra(obj); + if (obj->where == OBJ_FLOOR) { obj_extract_self(obj); /* move rocks back on top */ place_object(obj, obj->ox, obj->oy); -- 2.40.0