From: hjl@nynexst.com (H.J. Lu)
Newsgroups: comp.os.linux.announce
Subject: malloc bug (fwd)
Date: 18 Jul 1993 20:13:42 -0400
Approved: linux-announce@tc.cornell.edu (Matt Welsh)
Message-ID: <22covm$bdd@theory.TC.Cornell.EDU>

You have to patch both versions of malloc. If you don't know how,
please wait for the next release of the Linux C library, 4.5.

H.J.
------
Forwarded message:
>From mike@sisters.cs.uoregon.edu Fri Jul 16 23:29:16 1993
Date: Fri, 16 Jul 93 20:29:11 -0700
From: mike@sisters.cs.uoregon.edu
Message-Id: <9307170329.AA27719@sisters.cs.uoregon.edu>
To: hjl@nynexst.com
Subject: malloc bug

A bug in malloc has been brought to my attention.  Consequently I've
made a new version available via anon ftp from sisters.cs.uoregon.edu
file /pub/mike/malloc.tar.z.  There is also a small performance hack
that probably should not make a difference in ordinary use but helps
a certain pathological case.

Enclosed are diffs.  You may wish to post them to comp.os.linux...

diff -ru malloc-930326.dist/free.c malloc-930716.dist/free.c
--- malloc-930326.dist/free.c	Fri Mar 26 16:34:26 1993
+++ malloc-930716.dist/free.c	Fri Jul 16 20:18:48 1993
@@ -89,9 +89,11 @@
 				+ (_heapinfo[block].busy.info.frag.first
 				   << type));
 
-	if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1) {
+	if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1
+	&& _fragblocks[type] > 1) {
 	    /* If all fragments of this block are free, remove them
 	       from the fragment list and free the whole block. */
+	    --_fragblocks[type];
 	    for (next = prev, i = 1; i < BLOCKSIZE >> type; ++i)
 		next = next->next;
 	    prev->prev->next = next;
diff -ru malloc-930326.dist/malloc.c malloc-930716.dist/malloc.c
--- malloc-930326.dist/malloc.c	Fri Mar 26 16:51:05 1993
+++ malloc-930716.dist/malloc.c	Fri Jul 16 20:08:22 1993
@@ -32,6 +32,9 @@
 /* Limit of valid info table indices. */
 int _heaplimit;
 
+/* Count of large blocks allocated for each fragment size. */
+int _fragblocks[BLOCKLOG];
+
 /* Free lists for each fragment size. */
 struct list _fraghead[BLOCKLOG];
 
@@ -155,6 +158,7 @@
 	    result = malloc(BLOCKSIZE);
 	    if (!result)
 		return NULL;
+	    ++_fragblocks[log];
 
 	    /* Link all fragments but the first into the free list. */
 	    for (i = 1; i < BLOCKSIZE >> log; ++i) {
@@ -190,7 +194,11 @@
 		if (_heaplimit && block + lastblocks == _heaplimit
 		    && (*_morecore)(0) == ADDRESS(block + lastblocks)
 		    && morecore((blocks - lastblocks) * BLOCKSIZE)) {
-		    _heapinfo[block].free.size = blocks;
+		    /* Note that morecore() can change the location of
+		       the final block if it moves the info table and the
+		       old one gets coalesced into the final block. */
+		    block = _heapinfo[0].free.prev;
+		    _heapinfo[block].free.size += blocks - lastblocks;
 		    continue;
 		}
 		result = morecore(blocks * BLOCKSIZE);
diff -ru malloc-930326.dist/malloc.h malloc-930716.dist/malloc.h
--- malloc-930326.dist/malloc.h	Fri Mar 26 16:51:22 1993
+++ malloc-930716.dist/malloc.h	Sun May  2 00:09:55 1993
@@ -79,5 +79,8 @@
     struct list *prev;
 };
 
+/* Count of blocks for each fragment size. */
+extern int _fragblocks[];
+
 /* Free list headers for each fragment size. */
 extern struct list _fraghead[];


-- 
H.J. Lu
NYNEX Science and Technology, Inc.			hjl@nynexst.com

-- 
Send submissions for comp.os.linux.announce to: linux-announce@tc.cornell.edu
