findutils-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Findutils-patches] [PATCH 1/3] Support extendbuf buffers larger than SI


From: James Youngman
Subject: [Findutils-patches] [PATCH 1/3] Support extendbuf buffers larger than SIZE_MAX/2.
Date: Mon, 5 Apr 2010 01:22:51 +0100

* lib/extendbuf.c (xextendbuf): New function; extends the buffer,
but calls xalloc_die on failure.  On the the other hand, extendbuf
returns NULL on failure.
(decide_size): If wanted>SIZE_MAX/2, return wanted.  This means
that for very large buffers, performance on repeated extension
degrades from linear to quadratic (instead of just failing at that
point, as before).
* lib/savedirinfo.c (xsavedir): Use xextendbuf rather than
extendbuf, now that there is a difference in semantics.
* find/fstype.c (get_mounted_filesystems): If extendbuf returns
NULL, fail (by returning NULL ourselves).
(get_mounted_devices):  Likewise.

Signed-off-by: James Youngman <address@hidden>
---
 ChangeLog         |   16 ++++++++++++++++
 find/fstype.c     |   37 +++++++++++++++++++++++++++++--------
 lib/extendbuf.c   |   27 ++++++++++++++++++++++-----
 lib/extendbuf.h   |    1 +
 lib/savedirinfo.c |    6 +++---
 5 files changed, 71 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 709235a..3035d74 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2010-04-05  James Youngman  <address@hidden>
+
+       Support extendbuf buffers larger than SIZE_MAX/2.
+       * lib/extendbuf.c (xextendbuf): New function; extends the buffer,
+       but calls xalloc_die on failure.  On the the other hand, extendbuf
+       returns NULL on failure.
+       (decide_size): If wanted>SIZE_MAX/2, return wanted.  This means
+       that for very large buffers, performance on repeated extension
+       degrades from linear to quadratic (instead of just failing at that
+       point, as before).
+       * lib/savedirinfo.c (xsavedir): Use xextendbuf rather than
+       extendbuf, now that there is a difference in semantics.
+       * find/fstype.c (get_mounted_filesystems): If extendbuf returns
+       NULL, fail (by returning NULL ourselves).
+       (get_mounted_devices):  Likewise.
+
 2010-04-04  James Youngman  <address@hidden>
 
        Fix Savannah bug #29435: fd_is_cloexec does not work on Fedora
diff --git a/find/fstype.c b/find/fstype.c
index 21c446b..dc96068 100644
--- a/find/fstype.c
+++ b/find/fstype.c
@@ -258,6 +258,7 @@ get_mounted_filesystems (void)
   size_t alloc_size = 0u;
   size_t used = 0u;
   struct mount_entry *entries, *entry;
+  void *p;
 
   entries = must_read_fs_list (false);
   for (entry=entries; entry; entry=entry->me_next)
@@ -271,9 +272,17 @@ get_mounted_filesystems (void)
       set_fstype_devno (entry);
 
       len = strlen (entry->me_mountdir) + 1;
-      result = extendbuf (result, used+len, &alloc_size);
-      strcpy (&result[used], entry->me_mountdir);
-      used += len;             /* len already includes one for the \0 */
+      p = extendbuf (result, used+len, &alloc_size);
+      if (p)
+       {
+         result = p;
+         strcpy (&result[used], entry->me_mountdir);
+         used += len;          /* len already includes one for the \0 */
+       }
+      else
+       {
+         break;
+       }
     }
 
   free_file_system_list (entries);
@@ -299,13 +308,25 @@ get_mounted_devices (size_t *n)
        entry;
        entry = entry->me_next)
     {
-      result = extendbuf (result, sizeof(dev_t)*(used+1), &alloc_size);
-      set_fstype_devno (entry);
-      result[used] = entry->me_dev;
-      ++used;
+      void *p = extendbuf (result, sizeof(dev_t)*(used+1), &alloc_size);
+      if (p)
+       {
+         result = p;
+         set_fstype_devno (entry);
+         result[used] = entry->me_dev;
+         ++used;
+       }
+      else
+       {
+         free (result);
+         result = NULL;
+       }
     }
   free_file_system_list (entries);
-  *n = used;
+  if (result)
+    {
+      *n = used;
+    }
   return result;
 }
 
diff --git a/lib/extendbuf.c b/lib/extendbuf.c
index e5aa074..6cc52d5 100644
--- a/lib/extendbuf.c
+++ b/lib/extendbuf.c
@@ -49,7 +49,7 @@ decide_size (size_t current, size_t wanted)
   while (newsize < wanted)
     {
       if (2 * newsize < newsize)
-       xalloc_die ();
+       return wanted;
       newsize *= 2;
     }
   return newsize;
@@ -76,15 +76,18 @@ extendbuf (void* existing, size_t wanted, size_t *allocated)
       assert (NULL == existing);
 
       (*allocated) = newsize;
-      result = xmalloc (newsize);
+      result = malloc (newsize);
     }
   else
     {
       if (newsize != (*allocated) )
        {
          (*allocated) = newsize;
-         result = xrealloc (existing, newsize);
-
+         result = realloc (existing, newsize);
+         if (NULL == result)
+           {
+             saved_errno = errno;
+           }
        }
       else
        {
@@ -94,10 +97,24 @@ extendbuf (void* existing, size_t wanted, size_t *allocated)
 
   if (result)
     {
-      /* xmalloc () or xrealloc () may have changed errno, but in the
+      /* malloc () or realloc () may have changed errno, but in the
         success case we want to preserve the previous value.
       */
       errno = saved_errno;
     }
   return result;
 }
+
+
+void *
+xextendbuf (void* existing, size_t wanted, size_t *allocated)
+{
+  void *p = extendbuf (existing, wanted, allocated);
+  if (NULL == p)
+    {
+      free (existing);
+      xalloc_die ();
+    }
+  return p;
+}
+
diff --git a/lib/extendbuf.h b/lib/extendbuf.h
index 23a9e33..8d495a6 100644
--- a/lib/extendbuf.h
+++ b/lib/extendbuf.h
@@ -20,6 +20,7 @@
 #define INC_EXTENDBUF_H 1
 
 void *extendbuf(void* existing, size_t wanted, size_t *allocated);
+void *xextendbuf(void* existing, size_t wanted, size_t *allocated);
 
 
 #endif
diff --git a/lib/savedirinfo.c b/lib/savedirinfo.c
index 631c038..62bc36b 100644
--- a/lib/savedirinfo.c
+++ b/lib/savedirinfo.c
@@ -189,11 +189,11 @@ xsavedir (const char *dir, int flags)
        {
          /* Remember the name. */
          size_t entry_size = strlen (entry) + 1;
-         result->buffer = extendbuf (result->buffer, namebuf_used+entry_size, 
&namebuf_allocated);
+         result->buffer = xextendbuf (result->buffer, namebuf_used+entry_size, 
&namebuf_allocated);
          memcpy ((result->buffer) + namebuf_used, entry, entry_size);
 
          /* Remember the other stuff. */
-         internal = extendbuf (internal, (1+result->size)*sizeof (*internal), 
&entrybuf_allocated);
+         internal = xextendbuf (internal, (1+result->size)*sizeof (*internal), 
&entrybuf_allocated);
          internal[result->size].flags = 0;
 
 #if defined HAVE_STRUCT_DIRENT_D_TYPE && defined USE_STRUCT_DIRENT_D_TYPE
@@ -211,7 +211,7 @@ xsavedir (const char *dir, int flags)
        }
     }
 
-  result->buffer = extendbuf (result->buffer, namebuf_used+1, 
&namebuf_allocated);
+  result->buffer = xextendbuf (result->buffer, namebuf_used+1, 
&namebuf_allocated);
   result->buffer[namebuf_used] = '\0';
 
   /* convert the result to its externally-usable form. */
-- 
1.7.0





reply via email to

[Prev in Thread] Current Thread [Next in Thread]