bug-gnulib
[Top][All Lists]
Advanced

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

Re: [Bug-gnulib] xalloc patch to check for address arithmetic overflow


From: Paul Eggert
Subject: Re: [Bug-gnulib] xalloc patch to check for address arithmetic overflow
Date: 26 Oct 2003 23:34:42 -0800
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Bruno Haible <address@hidden> writes:

> 'inline' without static is likely to give problems;

Thanks for mentioning this.  Also, Jim Meyering mentioned that we need
a better interface for reallocating an array by doubling its size.  I
installed the following patch to fix both of these problems.


2003-10-26  Paul Eggert  <address@hidden>

        Add two functions x2realloc, x2nrealloc, for programs that grow
        arrays dynamically by doubling their sizes.
        * xalloc.h (x2realloc, x2nrealloc): New decls.
        * xmalloc.c (x2nrealloc_inline, x2nrealloc, x2realloc):
        New functions.

        Port to C99 semantics for 'inline' of external functions.
        Bug reported by Bruno Haible.
        * xmalloc.c (xnmalloc_inline): New static inline function,
        with the old contents of xnmalloc.
        (xnmalloc, xmalloc): Use it.
        (xnrealloc_inline): New static inline function,
        with the old contents of xnrealloc.
        (xnrealloc, xrealloc): Use it.

Index: lib/xalloc.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/xalloc.h,v
retrieving revision 1.17
diff -p -u -r1.17 xalloc.h
--- lib/xalloc.h        13 Oct 2003 06:07:11 -0000      1.17
+++ lib/xalloc.h        27 Oct 2003 07:25:07 -0000
@@ -54,6 +54,8 @@ void *xzalloc (size_t s);
 void *xcalloc (size_t n, size_t s);
 void *xrealloc (void *p, size_t s);
 void *xnrealloc (void *p, size_t n, size_t s);
+void *x2realloc (void *p, size_t *pn);
+void *x2nrealloc (void *p, size_t *pn, size_t s);
 void *xclone (void const *p, size_t s);
 char *xstrdup (const char *str);
 
Index: lib/xmalloc.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/xmalloc.c,v
retrieving revision 1.29
diff -p -u -r1.29 xmalloc.c
--- lib/xmalloc.c       16 Oct 2003 07:06:25 -0000      1.29
+++ lib/xmalloc.c       27 Oct 2003 07:25:07 -0000
@@ -77,8 +77,8 @@ xalloc_die (void)
 /* Allocate an array of N objects, each with S bytes of memory,
    dynamically, with error checking.  S must be nonzero.  */
 
-inline void *
-xnmalloc (size_t n, size_t s)
+static inline void *
+xnmalloc_inline (size_t n, size_t s)
 {
   void *p;
   if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
@@ -86,32 +86,148 @@ xnmalloc (size_t n, size_t s)
   return p;
 }
 
+void *
+xnmalloc (size_t n, size_t s)
+{
+  return xnmalloc_inline (n, s);
+}
+
 /* Allocate N bytes of memory dynamically, with error checking.  */
 
 void *
 xmalloc (size_t n)
 {
-  return xnmalloc (n, 1);
+  return xnmalloc_inline (n, 1);
 }
 
 /* Change the size of an allocated block of memory P to an array of N
    objects each of S bytes, with error checking.  S must be nonzero.  */
 
-inline void *
-xnrealloc (void *p, size_t n, size_t s)
+static inline void *
+xnrealloc_inline (void *p, size_t n, size_t s)
 {
   if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
     xalloc_die ();
   return p;
 }
 
+void *
+xnrealloc (void *p, size_t n, size_t s)
+{
+  return xnrealloc_inline (p, n, s);
+}
+
 /* Change the size of an allocated block of memory P to N bytes,
    with error checking.  */
 
 void *
 xrealloc (void *p, size_t n)
 {
-  return xnrealloc (p, n, 1);
+  return xnrealloc_inline (p, n, 1);
+}
+
+
+/* If P is null, allocate a block of at least *PN such objects;
+   otherwise, reallocate P so that it contains more than *PN objects
+   each of S bytes.  *PN must be nonzero unless P is null, and S must
+   be nonzero.  Set *PN to the new number of objects, and return the
+   pointer to the new block.  *PN is never set to zero, and the
+   returned pointer is never null.
+
+   Repeated reallocations are guaranteed to make progress, either by
+   allocating an initial block with a nonzero size, or by allocating a
+   larger block.
+
+   In the following implementation, nonzero sizes are doubled so that
+   repeated reallocations have O(N log N) overall cost rather than
+   O(N**2) cost, but the specification for this function does not
+   guarantee that sizes are doubled.
+
+   Here is an example of use:
+
+     int *p = NULL;
+     size used = 0;
+     size allocated = 0;
+
+     void
+     append_int (int value)
+       {
+        if (used == allocated)
+          p = x2nrealloc (p, &allocated, sizeof *p);
+        p[used++] = value;
+       }
+
+   This causes x2nrealloc to allocate a block of some nonzero size the
+   first time it is called.
+
+   To have finer-grained control over the initial size, set *PN to a
+   nonzero value before calling this function with P == NULL.  For
+   example:
+
+     int *p = NULL;
+     size used = 0;
+     size allocated = 0;
+     size allocated1 = 1000;
+
+     void
+     append_int (int value)
+       {
+        if (used == allocated)
+          {
+            p = x2nrealloc (p, &allocated1, sizeof *p);
+            allocated = allocated1;
+          }
+        p[used++] = value;
+       }
+
+   */
+
+static inline void *
+x2nrealloc_inline (void *p, size_t *pn, size_t s)
+{
+  size_t n = *pn;
+
+  if (! p)
+    {
+      if (! n)
+       {
+         /* The approximate size to use for initial small allocation
+            requests, when the invoking code specifies an old size of
+            zero.  64 bytes is the largest "small" request for the
+            GNU C library malloc.  */
+         enum { DEFAULT_MXFAST = 64 };
+
+         n = DEFAULT_MXFAST / s;
+         n += !n;
+       }
+    }
+  else
+    {
+      if (SIZE_MAX / 2 / s < n)
+       xalloc_die ();
+      n *= 2;
+    }
+
+  *pn = n;
+  return xrealloc (p, n * s);
+}
+
+void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+  return x2nrealloc_inline (p, pn, s);
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+   reallocate P so that it contains more than *PN bytes.  *PN must be
+   nonzero unless P is null.  Set *PN to the new block's size, and
+   return the pointer to the new block.  *PN is never set to zero, and
+   the returned pointer is never null.  */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+  return x2nrealloc_inline (p, pn, 1);
 }
 
 /* Allocate S bytes of zeroed memory dynamically, with error checking.




reply via email to

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