about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog30
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in10
-rw-r--r--nscd/aicache.c37
-rw-r--r--nscd/mem.c53
-rw-r--r--nscd/nscd.h2
-rw-r--r--resolv/nss_dns/dns-host.c16
-rw-r--r--sysdeps/posix/getaddrinfo.c5
8 files changed, 108 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index abca0a60d2..671ec52f3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2008-05-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* nscd/mem.c (gc): Avoid stack overflow when allocating move list.
+
+	* nscd/mem.c (gc): Correctly determine highest used array element
+	in mark.
+
+	* nscd/mem.c (markrange): Add assert to check entries are all
+	aligned.  Small cleanup in bitmap use.
+
+	* nscd/nscd.h (mem_in_flight): Replace blockaddr field with
+	blockoff of type nscd_ssize_t.
+	* nscd/mem.c (gc): Simplify markrange call for on-flight blocks.
+	(mempoll_alloc): Record block offset and not address.
+
+	* nscd/mem.c (gc): Fix test for stack overuse.
+
+	* nscd/aicache.c (addhstaiX): Fix a few small problems, cleanups,
+	more asserts.
+
+	* sysdeps/posix/getaddrinfo.c (gaih_inet): If nscd reports no
+	entry is available, believe it.
+
+	* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): If there are
+	no answers return NSS_STATUS_NOTFOUND.
+	(gaih_getanswer): Don't call gaih_getanswer_slice if the answer
+	buffer does not have any content.
+
 2008-05-16  Ulrich Drepper  <drepper@redhat.com>
 
 	* string/strcasestr.c (CMP_FUNC): Use __strncasecmp, not strncasecmp.
@@ -174,7 +202,7 @@
 	* nscd/hstcache.c: Likewise.
 	* nscd/initgrcache.c: Likewise.
 	* nscd/pwdcache.c: Likewise.
-	* nscd/servicecache.c: Likewise.
+	* nscd/servicescache.c: Likewise.
 
 2008-05-10  Roland McGrath  <roland@redhat.com>
 
diff --git a/fedora/branch.mk b/fedora/branch.mk
index ba57c390b3..c88650ca1d 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-f8
-fedora-sync-date := 2008-05-16 21:52 UTC
-fedora-sync-tag := fedora-glibc-20080516T2152
+fedora-sync-date := 2008-05-18 10:17 UTC
+fedora-sync-tag := fedora-glibc-20080518T1017
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index b46ffdb70d..648e8eba09 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -19,7 +19,7 @@
 Summary: The GNU libc libraries
 Name: glibc
 Version: @glibcversion@
-Release: 2
+Release: 3
 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
 # Things that are linked directly into dynamically linked programs
 # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
@@ -281,8 +281,8 @@ GCC="gcc -m64"
 GXX="g++ -m64"
 %endif
 
-BuildFlags="$BuildFlags -DNDEBUG=1 -fasynchronous-unwind-tables"
-#BuildFlags="$BuildFlags -fasynchronous-unwind-tables"
+#BuildFlags="$BuildFlags -DNDEBUG=1 -fasynchronous-unwind-tables"
+BuildFlags="$BuildFlags -fasynchronous-unwind-tables"
 EnableKernel="--enable-kernel=%{enablekernel}"
 echo "$GCC" > Gcc
 AddOns=`echo */configure | sed -e 's!/configure!!g;s!\(linuxthreads\|nptl\|rtkaio\|powerpc-cpu\)\( \|$\)!!g;s! \+$!!;s! !,!g;s!^!,!;/^,\*$/d'`
@@ -976,6 +976,10 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Sun May 18 2008 Jakub Jelinek <jakub@redhat.com> 2.8.90-3
+- getaddrinfo and nscd fixes
+- reenable assertion checking in rawhide
+
 * Fri May 16 2008 Jakub Jelinek <jakub@redhat.com> 2.8.90-2
 - fix getaddrinfo (#446801, #446808)
 
diff --git a/nscd/aicache.c b/nscd/aicache.c
index 918efc9f39..7ae5a1645c 100644
--- a/nscd/aicache.c
+++ b/nscd/aicache.c
@@ -114,7 +114,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
   char *tmpbuf6 = alloca (tmpbuf6len);
   size_t tmpbuf4len = 0;
   char *tmpbuf4 = NULL;
-  char *canon = NULL;
   int32_t ttl = INT32_MAX;
   ssize_t total = 0;
   char *key_copy = NULL;
@@ -126,6 +125,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
       int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
       int naddrs = 0;
       size_t addrslen = 0;
+      char *canon = NULL;
       size_t canonlen;
 
       nss_gethostbyname4_r fct4 = __nss_lookup_function (nip,
@@ -136,9 +136,11 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	  while (1)
 	    {
 	      rc6 = 0;
-	      status[0] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len,
+	      herrno = 0;
+	      status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len,
 					      &rc6, &herrno, &ttl));
-	      if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
+	      if (rc6 != ERANGE || (herrno != NETDB_INTERNAL
+				    && herrno != TRY_AGAIN))
 		break;
 	      tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
 	    }
@@ -146,22 +148,21 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	  if (rc6 != 0 && herrno == NETDB_INTERNAL)
 	    goto out;
 
-	  if (status[0] != NSS_STATUS_SUCCESS)
+	  if (status[1] != NSS_STATUS_SUCCESS)
 	    goto next_nip;
 
 	  /* We found the data.  Count the addresses and the size.  */
-	  for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next)
+	  for (const struct gaih_addrtuple *at2 = at; at2 != NULL;
+	       at2 = at2->next)
 	    {
 	      ++naddrs;
-	      /* We handle unknown types here the best we can: assume
-		 the maximum size for the address.  */
+	      /* We do not handle anything other than IPv4 and IPv6
+		 addresses.  The getaddrinfo implementation does not
+		 either so it is not worth trying to do more.  */
 	      if (at2->family == AF_INET)
 		addrslen += INADDRSZ;
-	      else if (at2->family == AF_INET6
-		       && IN6ADDRSZ != sizeof (at2->addr))
+	      else if (at2->family == AF_INET6)
 		addrslen += IN6ADDRSZ;
-	      else
-		addrslen += sizeof (at2->addr);
 	    }
 	  canon = at->name;
 	  canonlen = strlen (canon) + 1;
@@ -191,19 +192,17 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	    }
 
 	  /* Fill in the address and address families.  */
-	  char *addrs = (char *) (&dataset->resp + 1);
+	  char *addrs = dataset->strdata;
 	  uint8_t *family = (uint8_t *) (addrs + addrslen);
 
-	  for (struct gaih_addrtuple *at2 = at; at2 != NULL; at2 = at2->next)
+	  for (const struct gaih_addrtuple *at2 = at; at2 != NULL;
+	       at2 = at2->next)
 	    {
 	      *family++ = at2->family;
 	      if (at2->family == AF_INET)
 		addrs = mempcpy (addrs, at2->addr, INADDRSZ);
-	      else if (at2->family == AF_INET6
-		       && IN6ADDRSZ != sizeof (at2->addr))
+	      else if (at2->family == AF_INET6)
 		addrs = mempcpy (addrs, at2->addr, IN6ADDRSZ);
-	      else
-		addrs = mempcpy (addrs, at2->addr, sizeof (at2->addr));
 	    }
 
 	  cp = family;
@@ -373,7 +372,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 	    }
 
 	  /* Fill in the address and address families.  */
-	  char *addrs = (char *) (&dataset->resp + 1);
+	  char *addrs = dataset->strdata;
 	  uint8_t *family = (uint8_t *) (addrs + addrslen);
 
 	  for (int j = 0; j < 2; ++j)
@@ -411,6 +410,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
 
       key_copy = memcpy (cp, key, req->key_len);
 
+      assert (cp == (char *) dataset + total);
+
       /* Now we can determine whether on refill we have to create a
 	 new record or not.  */
       if (he != NULL)
diff --git a/nscd/mem.c b/nscd/mem.c
index 14928d633c..96ff03f0df 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -24,6 +24,7 @@
 #include <inttypes.h>
 #include <libintl.h>
 #include <limits.h>
+#include <obstack.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -79,6 +80,7 @@ static void
 markrange (BITMAP_T *mark, ref_t start, size_t len)
 {
   /* Adjust parameters for block alignment.  */
+  assert ((start & BLOCK_ALIGN_M1) == 0);
   start /= BLOCK_ALIGN;
   len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN;
 
@@ -93,7 +95,7 @@ markrange (BITMAP_T *mark, ref_t start, size_t len)
 	  return;
 	}
 
-      mark[elem++] |= 0xff << (start % BITS);
+      mark[elem++] |= ALLBITS << (start % BITS);
       len -= BITS - (start % BITS);
     }
 
@@ -130,14 +132,14 @@ gc (struct database_dyn *db)
   size_t stack_used = sizeof (bool) * db->head->module;
   if (__builtin_expect (stack_used > MAX_STACK_USE, 0))
     stack_used = 0;
-  size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1)
-			  / BITS) * sizeof (BITMAP_T);
-  if (memory_needed <= MAX_STACK_USE)
+  size_t nmark = (db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS;
+  size_t memory_needed = nmark * sizeof (BITMAP_T);
+  if (stack_used + memory_needed <= MAX_STACK_USE)
     {
       mark = (BITMAP_T *) alloca (memory_needed);
       mark_use_malloc = false;
       memset (mark, '\0', memory_needed);
-      stack_used = memory_needed;
+      stack_used += memory_needed;
     }
   else
     {
@@ -156,6 +158,7 @@ gc (struct database_dyn *db)
       he = alloca (db->head->nentries * sizeof (struct hashentry *));
       he_data = alloca (db->head->nentries * sizeof (struct hashentry *));
       he_use_malloc = false;
+      stack_used += memory_needed;
     }
   else
     {
@@ -212,11 +215,12 @@ gc (struct database_dyn *db)
       for (enum in_flight idx = IDX_result_data;
 	   idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx)
 	{
-	 assert ((char *) mrunp->block[idx].blockaddr > db->data);
-	 assert ((char *) mrunp->block[idx].blockaddr
-		 + mrunp->block[0].blocklen <= db->data + db->memsize);
-	 markrange (mark, (char *) mrunp->block[idx].blockaddr -  db->data,
-		    mrunp->block[idx].blocklen);
+	  assert (mrunp->block[idx].blockoff >= 0);
+	  assert (mrunp->block[idx].blocklen < db->memsize);
+	  assert (mrunp->block[idx].blockoff
+		  + mrunp->block[0].blocklen <= db->memsize);
+	  markrange (mark, mrunp->block[idx].blockoff,
+		     mrunp->block[idx].blocklen);
 	}
 
       mrunp = mrunp->next;
@@ -232,7 +236,7 @@ gc (struct database_dyn *db)
   qsort (he, cnt, sizeof (struct hashentry *), sort_he);
 
   /* Determine the highest used address.  */
-  size_t high = sizeof (mark);
+  size_t high = nmark;
   while (high > 0 && mark[high - 1] == 0)
     --high;
 
@@ -303,6 +307,10 @@ gc (struct database_dyn *db)
     size_t size;
     struct moveinfo *next;
   } *moves = NULL;
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+  struct obstack ob;
+  obstack_init (&ob);
 
   while (byte < high)
     {
@@ -363,8 +371,14 @@ gc (struct database_dyn *db)
 	 displacement.  */
       ref_t disp = off_alloc - off_free;
 
-      struct moveinfo *new_move
-	= (struct moveinfo *) alloca (sizeof (*new_move));
+      struct moveinfo *new_move;
+      if (stack_used + sizeof (*new_move) <= MAX_STACK_USE)
+	{
+	  new_move = alloca (sizeof (*new_move));
+	  stack_used += sizeof (*new_move);
+	}
+      else
+	new_move = obstack_alloc (&ob, sizeof (*new_move));
       new_move->from = db->data + off_alloc;
       new_move->to = db->data + off_free;
       new_move->size = off_allocend - off_alloc;
@@ -524,6 +538,8 @@ gc (struct database_dyn *db)
     free (he);
   if (mark_use_malloc)
     free (mark);
+
+  obstack_free (&ob, NULL);
 }
 
 
@@ -589,15 +605,16 @@ mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx)
     }
   else
     {
-      db->head->first_free += len;
-
-      db->last_alloc_failed = false;
-
       /* Remember that we have allocated this memory.  */
       assert (idx >= 0 && idx < IDX_last);
       mem_in_flight.block[idx].dbidx = db - dbs;
       mem_in_flight.block[idx].blocklen = len;
-      mem_in_flight.block[idx].blockaddr = res;
+      mem_in_flight.block[idx].blockoff = db->head->first_free;
+
+      db->head->first_free += len;
+
+      db->last_alloc_failed = false;
+
     }
 
   pthread_mutex_unlock (&db->memlock);
diff --git a/nscd/nscd.h b/nscd/nscd.h
index 66813e7480..b024017fd4 100644
--- a/nscd/nscd.h
+++ b/nscd/nscd.h
@@ -197,7 +197,7 @@ extern __thread struct mem_in_flight
   {
     int dbidx;
     nscd_ssize_t blocklen;
-    void *blockaddr;
+    nscd_ssize_t blockoff;
   } block[IDX_last];
 
   struct mem_in_flight *next;
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index c52f9f7f84..d998ebf4f5 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -990,6 +990,9 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
   char *h_name = NULL;
   int h_namelen = 0;
 
+  if (ancount == 0)
+    return NSS_STATUS_NOTFOUND;
+
   while (ancount-- > 0 && cp < end_of_message && had_error == 0)
     {
       n = __ns_name_unpack (answer->buf, end_of_message, cp,
@@ -1164,12 +1167,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
 {
   int first = 1;
 
-  enum nss_status status = gaih_getanswer_slice(answer1, anslen1, qname,
-						&pat, &buffer, &buflen,
-						errnop, h_errnop, ttlp,
-						&first);
+  enum nss_status status = NSS_STATUS_NOTFOUND;
+
+  if (anslen1 > 0)
+    status = gaih_getanswer_slice(answer1, anslen1, qname,
+				  &pat, &buffer, &buflen,
+				  errnop, h_errnop, ttlp,
+				  &first);
   if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
-      && answer2 != NULL)
+      && answer2 != NULL && anslen2 > 0)
     status = gaih_getanswer_slice(answer2, anslen2, qname,
 				  &pat, &buffer, &buflen,
 				  errnop, h_errnop, ttlp, &first);
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 2515d23c26..5c82b5274a 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -660,7 +660,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
 
 		  goto process_list;
 		}
-	      else if (err != 0 && __nss_not_use_nscd_hosts == 0)
+	      else if (err == 0)
+		/* The database contains a negative entry.  */
+		return 0;
+	      else if (__nss_not_use_nscd_hosts == 0)
 		{
 		  if (herrno == NETDB_INTERNAL && errno == ENOMEM)
 		    return -EAI_MEMORY;