changeset 14854:f5ea64b67bec

allocator: 'die' routine is now given requested size * lib/allocator.h (struct allocator.die): New size arg. * lib/careadlinkat.c (careadlinkat): Pass size to 'die' function. If the actual problem is an ssize_t limitation, not a size_t or malloc failure, fail with errno==ENAMETOOLONG instead of calling 'die'.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 02 Jun 2011 01:15:18 -0700
parents bdc85db78f47
children d08e35db9bba
files ChangeLog lib/allocator.h lib/careadlinkat.c
diffstat 3 files changed, 20 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-06-02  Paul Eggert  <eggert@cs.ucla.edu>
+
+	allocator: 'die' routine is now given requested size
+	* lib/allocator.h (struct allocator.die): New size arg.
+	* lib/careadlinkat.c (careadlinkat): Pass size to 'die' function.
+	If the actual problem is an ssize_t limitation, not a size_t or
+	malloc failure, fail with errno==ENAMETOOLONG instead of calling 'die'.
+
 2011-06-01  Eric Blake  <eblake@redhat.com>
 
 	strerror: drop strerror_r dependency
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -45,10 +45,11 @@
   /* Call FREE to free memory, like 'free'.  */
   void (*free) (void *);
 
-  /* If nonnull, call DIE if MALLOC or REALLOC fails.  DIE should not
-     return.  DIE can be used by code that detects memory overflow
-     while calculating sizes to be passed to MALLOC or REALLOC.  */
-  void (*die) (void);
+  /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (...,
+     SIZE) fails.  DIE should not return.  SIZE should equal SIZE_MAX
+     if size_t overflow was detected while calculating sizes to be
+     passed to MALLOC or REALLOC.  */
+  void (*die) (size_t);
 };
 
 /* An allocator using the stdlib functions and a null DIE function.  */
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -135,6 +135,7 @@
           if (buf == stack_buf)
             {
               char *b = (char *) alloc->allocate (link_size);
+              buf_size = link_size;
               if (! b)
                 break;
               memcpy (b, buf, link_size);
@@ -158,6 +159,11 @@
         buf_size *= 2;
       else if (buf_size < buf_size_max)
         buf_size = buf_size_max;
+      else if (buf_size_max < SIZE_MAX)
+        {
+          errno = ENAMETOOLONG;
+          return NULL;
+        }
       else
         break;
       buf = (char *) alloc->allocate (buf_size);
@@ -165,7 +171,7 @@
   while (buf);
 
   if (alloc->die)
-    alloc->die ();
+    alloc->die (buf_size);
   errno = ENOMEM;
   return NULL;
 }