bug-gnulib
[Top][All Lists]
Advanced

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

[Bug-gnulib] xreadlink.c patch


From: Mark D. Baushke
Subject: [Bug-gnulib] xreadlink.c patch
Date: Tue, 02 Nov 2004 02:44:33 -0800

Hi,

A patch for GNULIB lib/xreadlink.c

  1) bugfix. readlink() on AIX 4.3 returns a
     negative link_length and sets errno == ERANGE
     when the length of the link is greater than
     buf_size. (I am given to understand via the
     Ffile_symlink_p function in GNU Emacs
     src/fileio.c that the same is true for
     at least some versions of HP-UX.)

  2) enhancement. The size passed to xreadlink
     could be the maximum value and adding one
     could wrap it to zero which would be a bad
     idea.

  3) enhancement. Allow for at least one attempt
     at the maximum allowed buffer size if
     doubling the current buf_size pushes over the
     limit.

Thank you for your consideration of this patch.

        -- Mark
                
ChangeLog:

        * xreadlink.c (xreadlink): Deal with AIX and HP-UX readlink()
          returning ERANGE if the buffer is too small. Validate caller
          input parameter. Make one last attempt at SSIZE_MAX if
          doubling buf_size would have been greater than it. Use times()
          instead of *= to avoid numerical overflow.

Index: xreadlink.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/xreadlink.c,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 xreadlink.c
--- xreadlink.c 7 Aug 2004 00:09:39 -0000       1.15
+++ xreadlink.c 2 Nov 2004 10:46:54 -0000
@@ -56,14 +56,20 @@ xreadlink (char const *filename, size_t 
 {
   /* The initial buffer size for the link value.  A power of 2
      detects arithmetic overflow earlier, but is not required.  */
-  size_t buf_size = size + 1;
+  size_t buf_size = (size < SSIZE_MAX) ? size + 1 : size;
 
   while (1)
     {
       char *buffer = xmalloc (buf_size);
       ssize_t link_length = readlink (filename, buffer, buf_size);
 
-      if (link_length < 0)
+       /* AIX and HP-UX realloc() report ERANGE if the buffer is too
+          small */
+      if (link_length < 0
+#ifdef ERANGE
+         && errno != ERANGE
+#endif
+         )
        {
          int saved_errno = errno;
          free (buffer);
@@ -71,15 +77,20 @@ xreadlink (char const *filename, size_t 
          return NULL;
        }
 
-      if ((size_t) link_length < buf_size)
+      if (link_length >= 0 && (size_t) link_length < buf_size)
        {
          buffer[link_length] = 0;
          return buffer;
        }
 
       free (buffer);
-      buf_size *= 2;
-      if (! (0 < buf_size && buf_size <= SSIZE_MAX))
+      if (buf_size >= SSIZE_MAX)
+       /* Our buffer cannot grow any bigger.  */
        xalloc_die ();
+
+      buf_size = xtimes (buf_size, 2);
+      if (buf_size > SSIZE_MAX)
+       /* readlink()'s maximum buffer size.  */
+       buf_size = SSIZE_MAX;
     }
 }




reply via email to

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