]> granicus.if.org Git - nethack/commitdiff
fix memory leak: obj->oextra->omonst->mextra
authorPatR <rankin@nethack.org>
Sat, 14 Nov 2015 04:39:10 +0000 (20:39 -0800)
committerPatR <rankin@nethack.org>
Sat, 14 Nov 2015 04:39:10 +0000 (20:39 -0800)
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
src/mkobj.c
src/mon.c
src/zap.c

index 54c6ed2b301a0acbbd0ef0093314b9f234e3153e..5add97a441de0056fed3a0124f75e345a2a30b83 100644 (file)
@@ -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 *));
index bfc5b6ceef4dab9f0dff24edc3e93176edf4346c..6b56739a22dada6deaddd6e2439bc86fe3c41ae1 100644 (file)
@@ -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);
 }
 
index 889599b84513704e0d190a64b08988492d560d2f..8e251092cf4d82fef335bd4d0f110ecc47a390ae 100644 (file)
--- 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);
 }
 
index a88ee1b9ec36714e7254bf2da17d9e1186829c52..34c4b6d310db2c70ed47443b1488994c3aba4418 100644 (file)
--- 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);