about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--string/strnlen.c44
-rw-r--r--sunrpc/auth_unix.c14
-rw-r--r--sunrpc/svc_tcp.c4
-rw-r--r--sunrpc/svc_udp.c3
-rw-r--r--sunrpc/svc_unix.c4
-rw-r--r--sunrpc/xdr_rec.c12
-rw-r--r--sysdeps/generic/strnlen.c157
-rw-r--r--sysdeps/i386/i486/bits/string.h12
9 files changed, 197 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index 783c73f3ef..6f854b6936 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2001-08-22  Jakub Jelinek  <jakub@redhat.com>
+
+	* sunrpc/xdr_rec.c (xdrrec_create): Fix buf sizes before allocating
+	buf.  Free resources on failure.
+	* sunrpc/svc_unix.c (svcunix_create): Free resources on failure.
+	(makefd_xprt): Likewise.
+	* sunrpc/svc_udp.c (svcudp_bufcreate): Likewise.
+	* sunrpc/svc_tcp.c (svctcp_create, makefd_xprt): Likewise.
+	* sunrpc/auth_unix.c (authunix_create): Likewise.
+
+2001-08-21  Jakub Jelinek  <jakub@redhat.com>
+
+	* string/strnlen.c: Remove.
+	* sysdeps/generic/strnlen.c: New.
+	* sysdeps/i386/i486/bits/string.h (strnlen): Remove.
+
 2001-08-21  Roland McGrath  <roland@frob.com>
 
 	* sysdeps/mach/i386/machine-sp.h (__thread_stack_pointer): Define this
diff --git a/string/strnlen.c b/string/strnlen.c
deleted file mode 100644
index a777b35ca9..0000000000
--- a/string/strnlen.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Find the length of STRING, but scan at most MAXLEN characters.
-   Copyright (C) 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <string.h>
-
-/* Find the length of S, but scan at most MAXLEN characters.  If no
-   '\0' terminator is found in that many characters, return MAXLEN.  */
-
-size_t
-__strnlen (const char *s, size_t maxlen)
-{
-  size_t len = 0;
-
-  while (s[len] != '\0' && maxlen > 0)
-    {
-      if (s[++len] == '\0' || --maxlen == 0)
-	return len;
-      if (s[++len] == '\0' || --maxlen == 0)
-	return len;
-      if (s[++len] == '\0' || --maxlen == 0)
-	return len;
-      ++len;
-      --maxlen;
-    }
-
-  return len;
-}
-weak_alias (__strnlen, strnlen)
diff --git a/sunrpc/auth_unix.c b/sunrpc/auth_unix.c
index 50f955146c..bcfa0c931f 100644
--- a/sunrpc/auth_unix.c
+++ b/sunrpc/auth_unix.c
@@ -108,6 +108,7 @@ authunix_create (char *machname, uid_t uid, gid_t gid, int len,
   au = (struct audata *) mem_alloc (sizeof (*au));
   if (auth == NULL || au == NULL)
     {
+no_memory:
 #ifdef USE_IN_LIBIO
       if (_IO_fwide (stderr, 0) > 0)
 	(void) __fwprintf (stderr, L"%s",
@@ -115,6 +116,8 @@ authunix_create (char *machname, uid_t uid, gid_t gid, int len,
       else
 #endif
 	(void) fputs (_("authunix_create: out of memory\n"), stderr);
+      mem_free (auth, sizeof (*auth));
+      mem_free (au, sizeof (*au));
       return NULL;
     }
   auth->ah_ops = &auth_unix_ops;
@@ -143,16 +146,7 @@ authunix_create (char *machname, uid_t uid, gid_t gid, int len,
   au->au_origcred.oa_flavor = AUTH_UNIX;
   au->au_origcred.oa_base = mem_alloc ((u_int) len);
   if (au->au_origcred.oa_base == NULL)
-    {
-#ifdef USE_IN_LIBIO
-      if (_IO_fwide (stderr, 0) > 0)
-	(void) __fwprintf (stderr, L"%s",
-			   _("authunix_create: out of memory\n"));
-      else
-#endif
-	(void) fputs (_("authunix_create: out of memory\n"), stderr);
-      return NULL;
-    }
+    goto no_memory;
   memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
 
   /*
diff --git a/sunrpc/svc_tcp.c b/sunrpc/svc_tcp.c
index 2fffdf5b5c..cda2484b6f 100644
--- a/sunrpc/svc_tcp.c
+++ b/sunrpc/svc_tcp.c
@@ -183,6 +183,8 @@ svctcp_create (int sock, u_int sendsize, u_int recvsize)
       else
 #endif
 	(void) fputs (_("svctcp_create: out of memory\n"), stderr);
+      mem_free (r, sizeof (*r));
+      mem_free (xprt, sizeof (SVCXPRT));
       return NULL;
     }
   r->sendsize = sendsize;
@@ -225,6 +227,8 @@ makefd_xprt (int fd, u_int sendsize, u_int recvsize)
       else
 #endif
 	(void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (cd, sizeof (struct tcp_conn));
       return NULL;
     }
   cd->strm_stat = XPRT_IDLE;
diff --git a/sunrpc/svc_udp.c b/sunrpc/svc_udp.c
index f8ea76c0b8..17c4977e96 100644
--- a/sunrpc/svc_udp.c
+++ b/sunrpc/svc_udp.c
@@ -156,6 +156,9 @@ svcudp_bufcreate (sock, sendsz, recvsz)
       else
 #endif
 	(void) fputs (_("svcudp_create: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (su, sizeof (*su));
+      mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4);
       return NULL;
     }
   su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4;
diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
index 99e5a2a781..72bc9c2dda 100644
--- a/sunrpc/svc_unix.c
+++ b/sunrpc/svc_unix.c
@@ -179,6 +179,8 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
       else
 #endif
 	fputs (_("svcunix_create: out of memory\n"), stderr);
+      mem_free (r, sizeof (*r));
+      mem_free (xprt, sizeof (SVCXPRT));
       return NULL;
     }
   r->sendsize = sendsize;
@@ -221,6 +223,8 @@ makefd_xprt (int fd, u_int sendsize, u_int recvsize)
       else
 #endif
 	(void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
+      mem_free (xprt, sizeof (SVCXPRT));
+      mem_free (cd, sizeof (struct unix_conn));
       return NULL;
     }
   cd->strm_stat = XPRT_IDLE;
diff --git a/sunrpc/xdr_rec.c b/sunrpc/xdr_rec.c
index 65ffa3799e..941afa35de 100644
--- a/sunrpc/xdr_rec.c
+++ b/sunrpc/xdr_rec.c
@@ -146,7 +146,11 @@ xdrrec_create (XDR *xdrs, u_int sendsize,
 {
   RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM));
   caddr_t tmp;
-  char *buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
+  char *buf;
+
+  sendsize = fix_buf_size (sendsize);
+  recvsize = fix_buf_size (recvsize);
+  buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT);
 
   if (rstrm == NULL || buf == NULL)
     {
@@ -156,6 +160,8 @@ xdrrec_create (XDR *xdrs, u_int sendsize,
       else
 #endif
 	(void) fputs (_("xdrrec_create: out of memory\n"), stderr);
+      mem_free (rstrm, sizeof (RECSTREAM));
+      mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT);
       /*
        *  This is bad.  Should rework xdrrec_create to
        *  return a handle, and in this case return NULL
@@ -165,8 +171,8 @@ xdrrec_create (XDR *xdrs, u_int sendsize,
   /*
    * adjust sizes and allocate buffer quad byte aligned
    */
-  rstrm->sendsize = sendsize = fix_buf_size (sendsize);
-  rstrm->recvsize = recvsize = fix_buf_size (recvsize);
+  rstrm->sendsize = sendsize;
+  rstrm->recvsize = recvsize;
   rstrm->the_buffer = buf;
   tmp = rstrm->the_buffer;
   if ((size_t)tmp % BYTES_PER_XDR_UNIT)
diff --git a/sysdeps/generic/strnlen.c b/sysdeps/generic/strnlen.c
new file mode 100644
index 0000000000..f1b6760247
--- /dev/null
+++ b/sysdeps/generic/strnlen.c
@@ -0,0 +1,157 @@
+/* Find the length of STRING, but scan at most MAXLEN characters.
+   Copyright (C) 1991, 1993, 1997, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Jakub Jelinek <jakub@redhat.com>.
+
+   Based on strlen written by Torbjorn Granlund (tege@sics.se),
+   with help from Dan Sahlin (dan@sics.se);
+   commentary by Jim Blandy (jimb@ai.mit.edu).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <string.h>
+#include <stdlib.h>
+
+/* Find the length of S, but scan at most MAXLEN characters.  If no
+   '\0' terminator is found in that many characters, return MAXLEN.  */
+size_t
+__strnlen (const char *str, size_t maxlen)
+{
+  const char *char_ptr, *end_ptr = str + maxlen;
+  const unsigned long int *longword_ptr;
+  unsigned long int longword, magic_bits, himagic, lomagic;
+
+  if (maxlen == 0)
+    return 0;
+
+  /* Handle the first few characters by reading one character at a time.
+     Do this until CHAR_PTR is aligned on a longword boundary.  */
+  for (char_ptr = str; ((unsigned long int) char_ptr
+			& (sizeof (longword) - 1)) != 0;
+       ++char_ptr)
+    if (*char_ptr == '\0')
+      {
+	if (char_ptr > end_ptr)
+	  char_ptr = end_ptr;
+	return char_ptr - str;
+      }
+
+  /* All these elucidatory comments refer to 4-byte longwords,
+     but the theory applies equally well to 8-byte longwords.  */
+
+  longword_ptr = (unsigned long int *) char_ptr;
+
+  /* Bits 31, 24, 16, and 8 of this number are zero.  Call these bits
+     the "holes."  Note that there is a hole just to the left of
+     each byte, with an extra at the end:
+
+     bits:  01111110 11111110 11111110 11111111
+     bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
+
+     The 1-bits make sure that carries propagate to the next 0-bit.
+     The 0-bits provide holes for carries to fall into.  */
+  magic_bits = 0x7efefeffL;
+  himagic = 0x80808080L;
+  lomagic = 0x01010101L;
+  if (sizeof (longword) > 4)
+    {
+      /* 64-bit version of the magic.  */
+      /* Do the shift in two steps to avoid a warning if long has 32 bits.  */
+      magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
+      himagic = ((himagic << 16) << 16) | himagic;
+      lomagic = ((lomagic << 16) << 16) | lomagic;
+    }
+  if (sizeof (longword) > 8)
+    abort ();
+
+  /* Instead of the traditional loop which tests each character,
+     we will test a longword at a time.  The tricky part is testing
+     if *any of the four* bytes in the longword in question are zero.  */
+  while (longword_ptr < (unsigned long int *) end_ptr)
+    {
+      /* We tentatively exit the loop if adding MAGIC_BITS to
+	 LONGWORD fails to change any of the hole bits of LONGWORD.
+
+	 1) Is this safe?  Will it catch all the zero bytes?
+	 Suppose there is a byte with all zeros.  Any carry bits
+	 propagating from its left will fall into the hole at its
+	 least significant bit and stop.  Since there will be no
+	 carry from its most significant bit, the LSB of the
+	 byte to the left will be unchanged, and the zero will be
+	 detected.
+
+	 2) Is this worthwhile?  Will it ignore everything except
+	 zero bytes?  Suppose every byte of LONGWORD has a bit set
+	 somewhere.  There will be a carry into bit 8.  If bit 8
+	 is set, this will carry into bit 16.  If bit 8 is clear,
+	 one of bits 9-15 must be set, so there will be a carry
+	 into bit 16.  Similarly, there will be a carry into bit
+	 24.  If one of bits 24-30 is set, there will be a carry
+	 into bit 31, so all of the hole bits will be changed.
+
+	 The one misfire occurs when bits 24-30 are clear and bit
+	 31 is set; in this case, the hole at bit 31 is not
+	 changed.  If we had access to the processor carry flag,
+	 we could close this loophole by putting the fourth hole
+	 at bit 32!
+
+	 So it ignores everything except 128's, when they're aligned
+	 properly.  */
+
+      longword = *longword_ptr++;
+
+      if ((longword - lomagic) & himagic)
+	{
+	  /* Which of the bytes was the zero?  If none of them were, it was
+	     a misfire; continue the search.  */
+
+	  const char *cp = (const char *) (longword_ptr - 1);
+
+	  char_ptr = cp;
+	  if (cp[0] == 0)
+	    break;
+	  char_ptr = cp + 1;
+	  if (cp[1] == 0)
+	    break;
+	  char_ptr = cp + 2;
+	  if (cp[2] == 0)
+	    break;
+	  char_ptr = cp + 3;
+	  if (cp[3] == 0)
+	    break;
+	  if (sizeof (longword) > 4)
+	    {
+	      char_ptr = cp + 4;
+	      if (cp[4] == 0)
+		break;
+	      char_ptr = cp + 5;
+	      if (cp[5] == 0)
+		break;
+	      char_ptr = cp + 6;
+	      if (cp[6] == 0)
+		break;
+	      char_ptr = cp + 7;
+	      if (cp[7] == 0)
+		break;
+	    }
+	}
+      char_ptr = end_ptr;
+    }
+
+  if (char_ptr > end_ptr)
+    char_ptr = end_ptr;
+  return char_ptr - str;
+}
+weak_alias (__strnlen, strnlen)
diff --git a/sysdeps/i386/i486/bits/string.h b/sysdeps/i386/i486/bits/string.h
index bbe39adab7..07757ec389 100644
--- a/sysdeps/i386/i486/bits/string.h
+++ b/sysdeps/i386/i486/bits/string.h
@@ -540,18 +540,6 @@ __strlen_g (__const char *__str)
 }
 
 
-
-#if defined __USE_GNU
-#define _HAVE_STRING_ARCH_strnlen	1
-__STRING_INLINE size_t
-strnlen (__const char *__string, size_t __maxlen)
-{
-  __const char *__end = (__const char *) memchr (__string, '\0', __maxlen);
-  return __end ? (size_t) (__end - __string) : __maxlen;
-}
-#endif
-
-
 /* Copy SRC to DEST.  */
 #define _HAVE_STRING_ARCH_strcpy 1
 #define strcpy(dest, src) \