svn commit: r351251 - head/libexec/rtld-elf

Brooks Davis brooks at FreeBSD.org
Tue Aug 20 16:07:18 UTC 2019


Author: brooks
Date: Tue Aug 20 16:07:17 2019
New Revision: 351251
URL: https://svnweb.freebsd.org/changeset/base/351251

Log:
  Remove some compatability with Seventh Edition UNIX realloc().
  
  In Seventh Edition UNIX, the last pointer passed to free() was
  guaranteed to not actually have been freed allowing memory to be
  "compacted" via the following pattern:
  
  free(foo);
  foo = realloc(foo, newsize);
  
  Further, Andrew Koenig reports in "C Traps and Pitfalls" that the
  original realloc() implementation required this pattern.
  
  The C standard is clear that this is Undefined Behavior. Modern
  allocators don't support it and no portable code could rely on it so
  remove this support.
  
  Note: the removed implementation contains an off-by-one error and if
  an item isn't found on the freelist, then twice as much memory as the
  largest possible allocation will be copied.
  
  Reviewed by:	kib, imp
  Obtained from:	CheriBSD
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D21296

Modified:
  head/libexec/rtld-elf/rtld_malloc.c

Modified: head/libexec/rtld-elf/rtld_malloc.c
==============================================================================
--- head/libexec/rtld-elf/rtld_malloc.c	Tue Aug 20 15:14:32 2019	(r351250)
+++ head/libexec/rtld-elf/rtld_malloc.c	Tue Aug 20 16:07:17 2019	(r351251)
@@ -85,7 +85,6 @@ union	overhead {
 
 static void morecore(int bucket);
 static int morepages(int n);
-static int findbucket(union overhead *freep, int srchlen);
 
 #define	MAGIC		0xef		/* magic # on accounting info */
 
@@ -248,19 +247,6 @@ __crt_free(void *cp)
   	nextf[size] = op;
 }
 
-/*
- * When a program attempts "storage compaction" as mentioned in the
- * old malloc man page, it realloc's an already freed block.  Usually
- * this is the last block it freed; occasionally it might be farther
- * back.  We have to search all the free lists for the block in order
- * to determine its bucket: 1st we make one pass through the lists
- * checking only the first block in each; if that fails we search
- * ``realloc_srchlen'' blocks in each list for a match (the variable
- * is extern so the caller can modify it).  If that fails we just copy
- * however many bytes was given to realloc() and hope it's not huge.
- */
-static int realloc_srchlen = 4;	/* 4 should be plenty, -1 =>'s whole list */
-
 void *
 __crt_realloc(void *cp, size_t nbytes)
 {
@@ -268,78 +254,33 @@ __crt_realloc(void *cp, size_t nbytes)
 	int i;
 	union overhead *op;
   	char *res;
-	int was_alloced = 0;
 
   	if (cp == NULL)
 		return (__crt_malloc(nbytes));
 	op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
-	if (op->ov_magic == MAGIC) {
-		was_alloced++;
-		i = op->ov_index;
-	} else {
-		/*
-		 * Already free, doing "compaction".
-		 *
-		 * Search for the old block of memory on the
-		 * free list.  First, check the most common
-		 * case (last element free'd), then (this failing)
-		 * the last ``realloc_srchlen'' items free'd.
-		 * If all lookups fail, then assume the size of
-		 * the memory block being realloc'd is the
-		 * largest possible (so that all "nbytes" of new
-		 * memory are copied into).  Note that this could cause
-		 * a memory fault if the old area was tiny, and the moon
-		 * is gibbous.  However, that is very unlikely.
-		 */
-		if ((i = findbucket(op, 1)) < 0 &&
-		    (i = findbucket(op, realloc_srchlen)) < 0)
-			i = NBUCKETS;
-	}
+	if (op->ov_magic != MAGIC)
+		return (NULL);	/* Double-free or bad argument */
+	i = op->ov_index;
 	onb = 1 << (i + 3);
 	if (onb < (u_int)pagesz)
 		onb -= sizeof(*op);
 	else
 		onb += pagesz - sizeof(*op);
 	/* avoid the copy if same size block */
-	if (was_alloced) {
-		if (i) {
-			i = 1 << (i + 2);
-			if (i < pagesz)
-				i -= sizeof(*op);
-			else
-				i += pagesz - sizeof(*op);
-		}
-		if (nbytes <= onb && nbytes > (size_t)i)
-			return (cp);
-		__crt_free(cp);
+	if (i != 0) {
+		i = 1 << (i + 2);
+		if (i < pagesz)
+			i -= sizeof(*op);
+		else
+			i += pagesz - sizeof(*op);
 	}
+	if (nbytes <= onb && nbytes > (size_t)i)
+		return (cp);
   	if ((res = __crt_malloc(nbytes)) == NULL)
 		return (NULL);
-  	if (cp != res)		/* common optimization if "compacting" */
-		bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
+	bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
+	__crt_free(cp);
   	return (res);
-}
-
-/*
- * Search ``srchlen'' elements of each free list for a block whose
- * header starts at ``freep''.  If srchlen is -1 search the whole list.
- * Return bucket number, or -1 if not found.
- */
-static int
-findbucket(union overhead *freep, int srchlen)
-{
-	union overhead *p;
-	int i, j;
-
-	for (i = 0; i < NBUCKETS; i++) {
-		j = 0;
-		for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
-			if (p == freep)
-				return (i);
-			j++;
-		}
-	}
-	return (-1);
 }
 
 static int


More information about the svn-src-all mailing list