[Top][All Lists]
[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
- [Findutils-patches] [PATCH 1/3] Support extendbuf buffers larger than SIZE_MAX/2.,
James Youngman <=