about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-11-15 09:47:23 +0000
committerJakub Jelinek <jakub@redhat.com>2004-11-15 09:47:23 +0000
commitb3c20a361d75caf75f670b2fcd64ab8668c16ca5 (patch)
treecac006e13628dcbf5a48cb618417ae708906db89
parent87ffc9aca119436c8530d6605483a49cfb16668e (diff)
downloadglibc-b3c20a361d75caf75f670b2fcd64ab8668c16ca5.tar.gz
glibc-b3c20a361d75caf75f670b2fcd64ab8668c16ca5.tar.xz
glibc-b3c20a361d75caf75f670b2fcd64ab8668c16ca5.zip
Updated to fedora-glibc-20041115T0915
-rw-r--r--ChangeLog51
-rw-r--r--debug/chk_fail.c18
-rw-r--r--debug/test-strcpy_chk.c36
-rw-r--r--debug/tst-chk1.c16
-rw-r--r--elf/elf.h7
-rw-r--r--elf/rtld.c20
-rw-r--r--fedora/branch.mk4
-rw-r--r--fedora/glibc.spec.in7
-rw-r--r--include/stdio.h2
-rw-r--r--malloc/malloc.c354
-rw-r--r--nis/ypclnt.c2
-rw-r--r--posix/Makefile1
-rw-r--r--sysdeps/posix/libc_fatal.c125
-rw-r--r--sysdeps/unix/sysv/linux/libc_fatal.c144
14 files changed, 501 insertions, 286 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ff1338078..5e1b916936 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2004-11-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* malloc/malloc.c (malloc_state): stat_lock_* elements need only
+	be defined if THREAD_STATS is defined.  Remove pad0_ since it does
+	not align with cache line sizes in general anyway.
+
+2004-11-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* elf/rtld.c (print_statistics): Avoid segfaults if not all namespaces
+	are used.  Fix computation of num_relative_relocations on RELA
+	architectures other than IA-64 and Alpha.
+
+2004-11-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* malloc/malloc.c (_int_free): Use munmap_chunk for handling
+	mmaped memory.
+
+2004-11-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* malloc/malloc.c (_int_free): Remove test for NULL parameter.
+	(_int_realloc): Call _int_free only if memory parameter is not NULL.
+
+	* sysdeps/unix/sysv/linux/libc_fatal.c: Add new function __libc_message
+	which performs the printing and simple format string handling.  The
+	string is written to tty, stderr, syslog in this order, stopping after
+	the first successful output.
+	(__libc_fatal): Call __libc_message.
+	* include/stdio.h: Declare __libc_message.
+	* malloc/malloc.c (malloc_printerr): Use __libc_message.
+	* debug/chk_fail.c: Also print message with __libc_message.
+	* debug/test-strcpy_chk.c: Ensure that debug messages are not printed
+	to the terminal or stderr.
+	* debug/tst-chk1.c: Likewise.
+
+	* posix/Makefile: Remove gpl2lgpl variable.
+
+2004-11-12  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+	* elf/elf.h: Add 20 bit relocations R_390_*20.
+
 2004-11-12  Jakub Jelinek  <jakub@redhat.com>
 
 	* sysdeps/unix/sysv/linux/i386/setuid.c: Include linux/posix_types.h.
@@ -7,16 +47,9 @@
 	* sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise.
 	* sysdeps/unix/sysv/linux/i386/setresgid.c: Likewise.
 
-2004-11-11  Jakub Jelinek  <jakub@redhat.com>
+2004-11-12  Andreas Schwab  <schwab@suse.de>
 
-	* debug/chk_fail.c: Include errno.h and string.h.
-	(__chk_fail): Write a short message to stderr.
-	* debug/tst-chk1.c: Include fcntl.h.
-	(do_test): Redirect stderr to /dev/null.
-	* debug/test-strcpy_chk.c: Include fcntl.h.
-	(test_main): Redirect stderr to /dev/null.
-	(do_one_test, do_random_tests): Use printf instead of
-	error.
+	* nis/ypclnt.c (ypprot_err): Fix "minor optimizations".
 
 2004-11-12  Ulrich Drepper  <drepper@redhat.com>
 
diff --git a/debug/chk_fail.c b/debug/chk_fail.c
index 70ffa9e40f..dc1c3d70b6 100644
--- a/debug/chk_fail.c
+++ b/debug/chk_fail.c
@@ -1,3 +1,4 @@
+
 /* Copyright (C) 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,27 +17,14 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <errno.h>
+#include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <abort-instr.h>
 
 
 void
 __attribute__ ((noreturn))
 __chk_fail (void)
 {
-  while (1)
-    {
-      const char *text = "*** buffer overflow detected ***\n";
-      TEMP_FAILURE_RETRY (write (STDERR_FILENO, text, strlen (text)));
-      /* This will leave a nice backtrace.  */
-      abort ();
-#ifdef ABORT_INSTRUCTION
-      ABORT_INSTRUCTION;
-#endif
-      _exit (127);
-    }
+  __libc_fatal ("*** buffer overflow detected ***\n");
 }
 libc_hidden_def (__chk_fail)
diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c
index 8430ca4704..ac9f9448cf 100644
--- a/debug/test-strcpy_chk.c
+++ b/debug/test-strcpy_chk.c
@@ -46,9 +46,10 @@ simple_strcpy_chk (char *dst, const char *src, size_t len)
 }
 #endif
 
+#include <fcntl.h>
+#include <paths.h>
 #include <setjmp.h>
 #include <signal.h>
-#include <fcntl.h>
 
 volatile int chk_fail_ok;
 jmp_buf chk_fail_buf;
@@ -81,8 +82,8 @@ do_one_test (impl_t *impl, char *dst, const char *src,
       if (setjmp (chk_fail_buf) == 0)
 	{
 	  res = CALL (impl, dst, src, dlen);
-	  printf ("*** Function %s (%zd; %zd) did not __chk_fail",
-	          impl->name, len, dlen);
+	  printf ("*** Function %s (%zd; %zd) did not __chk_fail\n",
+		  impl->name, len, dlen);
 	  chk_fail_ok = 0;
 	  ret = 1;
 	}
@@ -93,7 +94,7 @@ do_one_test (impl_t *impl, char *dst, const char *src,
 
   if (res != STRCPY_RESULT (dst, len))
     {
-      printf ("*** Wrong result in function %s %p %p", impl->name,
+      printf ("Wrong result in function %s %p %p\n", impl->name,
 	      res, STRCPY_RESULT (dst, len));
       ret = 1;
       return;
@@ -101,7 +102,7 @@ do_one_test (impl_t *impl, char *dst, const char *src,
 
   if (strcmp (dst, src) != 0)
     {
-      printf ("*** Wrong result in function %s dst \"%s\" src \"%s\"",
+      printf ("Wrong result in function %s dst \"%s\" src \"%s\"\n",
 	      impl->name, dst, src);
       ret = 1;
       return;
@@ -233,7 +234,7 @@ do_random_tests (void)
 		  if (setjmp (chk_fail_buf) == 0)
 		    {
 		      res = CALL (impl, p2 + align2, p1 + align1, dlen);
-		      printf ("*** Iteration %zd - did not __chk_fail", n);
+		      printf ("Iteration %zd - did not __chk_fail\n", n);
 		      chk_fail_ok = 0;
 		      ret = 1;
 		    }
@@ -244,7 +245,8 @@ do_random_tests (void)
 	  res = CALL (impl, p2 + align2, p1 + align1, dlen);
 	  if (res != STRCPY_RESULT (p2 + align2, len))
 	    {
-	      printf ("*** Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p",
+	      printf ("\
+Iteration %zd - wrong result in function %s (%zd, %zd, %zd) %p != %p\n",
 		      n, impl->name, align1, align2, len, res,
 		      STRCPY_RESULT (p2 + align2, len));
 	      ret = 1;
@@ -253,7 +255,8 @@ do_random_tests (void)
 	    {
 	      if (p2[j - 64] != '\1')
 		{
-		  printf ("*** Iteration %zd - garbage before, %s (%zd, %zd, %zd)",
+		  printf ("\
+Iteration %zd - garbage before, %s (%zd, %zd, %zd)\n",
 			  n, impl->name, align1, align2, len);
 		  ret = 1;
 		  break;
@@ -263,7 +266,8 @@ do_random_tests (void)
 	    {
 	      if (p2[j] != '\1')
 		{
-		  printf ("*** Iteration %zd - garbage after, %s (%zd, %zd, %zd)",
+		  printf ("\
+Iteration %zd - garbage after, %s (%zd, %zd, %zd)\n",
 			  n, impl->name, align1, align2, len);
 		  ret = 1;
 		  break;
@@ -271,7 +275,8 @@ do_random_tests (void)
 	    }
 	  if (memcmp (p1 + align1, p2 + align2, len + 1))
 	    {
-	      printf ("*** Iteration %zd - different strings, %s (%zd, %zd, %zd)",
+	      printf ("\
+Iteration %zd - different strings, %s (%zd, %zd, %zd)\n",
 		      n, impl->name, align1, align2, len);
 	      ret = 1;
 	    }
@@ -292,8 +297,15 @@ test_main (void)
   sigaction (SIGABRT, &sa, NULL);
 
   /* Avoid all the buffer overflow messages on stderr.  */
-  close (STDERR_FILENO);
-  open ("/dev/null", O_WRONLY);
+  int fd = open (_PATH_DEVNULL, O_WRONLY);
+  if (fd == -1)
+    close (STDERR_FILENO);
+  else
+    {
+      dup2 (fd, STDERR_FILENO);
+      close (fd);
+    }
+  setenv ("LIBC_FATAL_STDERR_", "1", 1);
 
   test_init ();
 
diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c
index e01284ae53..37320c3514 100644
--- a/debug/tst-chk1.c
+++ b/debug/tst-chk1.c
@@ -18,6 +18,7 @@
    02111-1307 USA.  */
 
 #include <fcntl.h>
+#include <paths.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <stdio.h>
@@ -108,8 +109,15 @@ do_test (void)
   sigaction (SIGABRT, &sa, NULL);
 
   /* Avoid all the buffer overflow messages on stderr.  */
-  close (STDERR_FILENO);
-  open ("/dev/null", O_WRONLY);
+  int fd = open (_PATH_DEVNULL, O_WRONLY);
+  if (fd == -1)
+    close (STDERR_FILENO);
+  else
+    {
+      dup2 (fd, STDERR_FILENO);
+      close (fd);
+    }
+  setenv ("LIBC_FATAL_STDERR_", "1", 1);
 
   struct A { char buf1[9]; char buf2[1]; } a;
 
@@ -205,7 +213,7 @@ do_test (void)
   if (memcmp (a.buf1, "aabcdabcjj", 10))
     FAIL ();
 
-#if __USE_FORTIFY_LEVEL < 2 || !__GNUC_PREREQ (4, 0)
+#if __USE_FORTIFY_LEVEL < 2
   /* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
      and sufficient GCC support, as the string operations overflow
      from a.buf1 into a.buf2.  */
@@ -304,7 +312,7 @@ do_test (void)
   memset (a.buf1 + 9, 'j', l0 + 2);
   CHK_FAIL_END
 
-#if __USE_FORTIFY_LEVEL >= 2 && __GNUC_PREREQ (4, 0)
+#if __USE_FORTIFY_LEVEL >= 2
 # define O 0
 #else
 # define O 1
diff --git a/elf/elf.h b/elf/elf.h
index db95254f74..0daff76a41 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2402,8 +2402,13 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_390_TLS_DTPOFF	55	/* Offset in TLS block.	 */
 #define R_390_TLS_TPOFF		56	/* Negated offset in static TLS
 					   block.  */
+#define R_390_20		57	/* Direct 20 bit.  */
+#define R_390_GOT20		58	/* 20 bit GOT offset.  */
+#define R_390_GOTPLT20		59	/* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20	60	/* 20 bit GOT offset for static TLS
+					   block offset.  */
 /* Keep this the last entry.  */
-#define R_390_NUM		57
+#define R_390_NUM		61
 
 
 /* CRIS relocations.  */
diff --git a/elf/rtld.c b/elf/rtld.c
index e53273c2bb..e442aa257f 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2444,19 +2444,29 @@ print_statistics (hp_timing_t *rtld_total_timep)
   unsigned long int num_relative_relocations = 0;
   for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
     {
+      if (GL(dl_ns)[ns]._ns_loaded == NULL)
+	continue;
+
       struct r_scope_elem *scope = &GL(dl_ns)[ns]._ns_loaded->l_searchlist;
 
       for (unsigned int i = 0; i < scope->r_nlist; i++)
 	{
 	  struct link_map *l = scope->r_list [i];
 
-	  if (!l->l_addr)
-	    continue;
-
-	  if (l->l_info[VERSYMIDX (DT_RELCOUNT)])
+	  if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELCOUNT)])
 	    num_relative_relocations
 	      += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val;
-	  if (l->l_info[VERSYMIDX (DT_RELACOUNT)])
+#ifndef ELF_MACHINE_REL_RELATIVE
+	  /* Relative relocations are processed on these architectures if
+	     library is loaded to different address than p_vaddr or
+	     if not prelinked.  */
+	  if ((l->l_addr != 0 || !l->l_info[VALIDX(DT_GNU_PRELINKED)])
+	      && l->l_info[VERSYMIDX (DT_RELACOUNT)])
+#else
+	  /* On e.g. IA-64 or Alpha, relative relocations are processed
+	     only if library is loaded to different address than p_vaddr.  */
+	  if (l->l_addr != 0 && l->l_info[VERSYMIDX (DT_RELACOUNT)])
+#endif
 	    num_relative_relocations
 	      += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val;
 	}
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 2714ad4822..3add7920d6 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -1,5 +1,5 @@
 # This file is updated automatically by Makefile.
 glibc-branch := fedora
 glibc-base := HEAD
-fedora-sync-date := 2004-11-12 16:40 UTC
-fedora-sync-tag := fedora-glibc-20041112T1640
+fedora-sync-date := 2004-11-15 09:15 UTC
+fedora-sync-tag := fedora-glibc-20041115T0915
diff --git a/fedora/glibc.spec.in b/fedora/glibc.spec.in
index 0d97316b37..1c93fc1e0b 100644
--- a/fedora/glibc.spec.in
+++ b/fedora/glibc.spec.in
@@ -1,4 +1,4 @@
-%define glibcrelease 77
+%define glibcrelease 78
 %define auxarches i586 i686 athlon sparcv9 alphaev6
 %define prelinkarches noarch
 %define nptlarches i386 i686 athlon x86_64 ia64 s390 s390x sparcv9 ppc ppc64
@@ -1256,6 +1256,11 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Mon Nov 15 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-78
+- update from CVS
+  - issue error message before aborting in __chk_fail ()
+  - some more free () checking
+
 * Fri Nov 12 2004 Jakub Jelinek <jakub@redhat.com> 2.3.3-77
 - update from CVS
   - speedup regex on palindromes (BZ #429)
diff --git a/include/stdio.h b/include/stdio.h
index 05a91b4cb3..ad8f157829 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -62,6 +62,8 @@ extern int __gen_tempname (char *__tmpl, int __kind);
 /* Print out MESSAGE on the error output and abort.  */
 extern void __libc_fatal (__const char *__message)
      __attribute__ ((__noreturn__));
+extern void __libc_message (int do_abort, __const char *__fnt, ...)
+     __attribute__ ((__noreturn__));
 
 /* Acquire ownership of STREAM.  */
 extern void __flockfile (FILE *__stream);
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 6d6294c6e6..57074108f1 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -2192,10 +2192,12 @@ typedef struct malloc_chunk* mfastbinptr;
 struct malloc_state {
   /* Serialize access.  */
   mutex_t mutex;
+  // Should we have padding to move the mutex to its own cache line?
 
+#if THREAD_STATS
   /* Statistics for locking.  Only used if THREAD_STATS is defined.  */
   long stat_lock_direct, stat_lock_loop, stat_lock_wait;
-  long pad0_[1]; /* try to give the mutex its own cacheline */
+#endif
 
   /* The maximum chunk size to be eligible for fastbin */
   INTERNAL_SIZE_T  max_fast;   /* low 2 bits used as flags */
@@ -4196,191 +4198,182 @@ _int_free(mstate av, Void_t* mem)
   mchunkptr       fwd;         /* misc temp for linking */
 
 
-  /* free(0) has no effect */
-  if (mem != 0) {
-    const char *errstr = NULL;
+  const char *errstr = NULL;
 
-    p = mem2chunk(mem);
-    size = chunksize(p);
+  p = mem2chunk(mem);
+  size = chunksize(p);
 
-    /* Little security check which won't hurt performance: the
-       allocator never wrapps around at the end of the address space.
-       Therefore we can exclude some size values which might appear
-       here by accident or by "design" from some intruder.  */
-    if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0))
-      {
-	errstr = "free(): invalid pointer";
-      errout:
-	malloc_printerr (check_action, errstr, mem);
-	return;
-      }
+  /* Little security check which won't hurt performance: the
+     allocator never wrapps around at the end of the address space.
+     Therefore we can exclude some size values which might appear
+     here by accident or by "design" from some intruder.  */
+  if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0))
+    {
+      errstr = "free(): invalid pointer";
+    errout:
+      malloc_printerr (check_action, errstr, mem);
+      return;
+    }
 
-    check_inuse_chunk(av, p);
+  check_inuse_chunk(av, p);
 
-    /*
-      If eligible, place chunk on a fastbin so it can be found
-      and used quickly in malloc.
-    */
+  /*
+    If eligible, place chunk on a fastbin so it can be found
+    and used quickly in malloc.
+  */
 
-    if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
+  if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
 
 #if TRIM_FASTBINS
-        /*
-           If TRIM_FASTBINS set, don't place chunks
-           bordering top into fastbins
-        */
-        && (chunk_at_offset(p, size) != av->top)
-#endif
-        ) {
-
-      set_fastchunks(av);
-      fb = &(av->fastbins[fastbin_index(size)]);
-      /* Another simple check: make sure the top of the bin is not the
-	 record we are going to add (i.e., double free).  */
-      if (__builtin_expect (*fb == p, 0))
-	{
-	  errstr = "double free or corruption (fasttop)";
-	  goto errout;
-	}
-      p->fd = *fb;
-      *fb = p;
-    }
-
-    /*
-       Consolidate other non-mmapped chunks as they arrive.
-    */
+      /*
+	If TRIM_FASTBINS set, don't place chunks
+	bordering top into fastbins
+      */
+      && (chunk_at_offset(p, size) != av->top)
+#endif
+      ) {
 
-    else if (!chunk_is_mmapped(p)) {
-      nextchunk = chunk_at_offset(p, size);
+    set_fastchunks(av);
+    fb = &(av->fastbins[fastbin_index(size)]);
+    /* Another simple check: make sure the top of the bin is not the
+       record we are going to add (i.e., double free).  */
+    if (__builtin_expect (*fb == p, 0))
+      {
+	errstr = "double free or corruption (fasttop)";
+	goto errout;
+      }
+    p->fd = *fb;
+    *fb = p;
+  }
 
-      /* Lightweight tests: check whether the block is already the
-	 top block.  */
-      if (__builtin_expect (p == av->top, 0))
-	{
-	  errstr = "double free or corruption (top)";
-	  goto errout;
-	}
-      /* Or whether the next chunk is beyond the boundaries of the arena.  */
-      if (__builtin_expect (contiguous (av)
-			    && (char *) nextchunk
-			       >= ((char *) av->top + chunksize(av->top)), 0))
-	{
-	  errstr = "double free or corruption (out)";
-	  goto errout;
-	}
-      /* Or whether the block is actually not marked used.  */
-      if (__builtin_expect (!prev_inuse(nextchunk), 0))
-	{
-	  errstr = "double free or corruption (!prev)";
-	  goto errout;
-	}
+  /*
+    Consolidate other non-mmapped chunks as they arrive.
+  */
 
-      nextsize = chunksize(nextchunk);
-      assert(nextsize > 0);
+  else if (!chunk_is_mmapped(p)) {
+    nextchunk = chunk_at_offset(p, size);
 
-      /* consolidate backward */
-      if (!prev_inuse(p)) {
-        prevsize = p->prev_size;
-        size += prevsize;
-        p = chunk_at_offset(p, -((long) prevsize));
-        unlink(p, bck, fwd);
+    /* Lightweight tests: check whether the block is already the
+       top block.  */
+    if (__builtin_expect (p == av->top, 0))
+      {
+	errstr = "double free or corruption (top)";
+	goto errout;
+      }
+    /* Or whether the next chunk is beyond the boundaries of the arena.  */
+    if (__builtin_expect (contiguous (av)
+			  && (char *) nextchunk
+			  >= ((char *) av->top + chunksize(av->top)), 0))
+      {
+	errstr = "double free or corruption (out)";
+	goto errout;
+      }
+    /* Or whether the block is actually not marked used.  */
+    if (__builtin_expect (!prev_inuse(nextchunk), 0))
+      {
+	errstr = "double free or corruption (!prev)";
+	goto errout;
       }
 
-      if (nextchunk != av->top) {
-        /* get and clear inuse bit */
-        nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-
-        /* consolidate forward */
-        if (!nextinuse) {
-          unlink(nextchunk, bck, fwd);
-          size += nextsize;
-        } else
-	  clear_inuse_bit_at_offset(nextchunk, 0);
-
-        /*
-          Place the chunk in unsorted chunk list. Chunks are
-          not placed into regular bins until after they have
-          been given one chance to be used in malloc.
-        */
+    nextsize = chunksize(nextchunk);
+    assert(nextsize > 0);
 
-        bck = unsorted_chunks(av);
-        fwd = bck->fd;
-        p->bk = bck;
-        p->fd = fwd;
-        bck->fd = p;
-        fwd->bk = p;
+    /* consolidate backward */
+    if (!prev_inuse(p)) {
+      prevsize = p->prev_size;
+      size += prevsize;
+      p = chunk_at_offset(p, -((long) prevsize));
+      unlink(p, bck, fwd);
+    }
 
-        set_head(p, size | PREV_INUSE);
-        set_foot(p, size);
+    if (nextchunk != av->top) {
+      /* get and clear inuse bit */
+      nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
 
-        check_free_chunk(av, p);
-      }
+      /* consolidate forward */
+      if (!nextinuse) {
+	unlink(nextchunk, bck, fwd);
+	size += nextsize;
+      } else
+	clear_inuse_bit_at_offset(nextchunk, 0);
 
       /*
-         If the chunk borders the current high end of memory,
-         consolidate into top
+	Place the chunk in unsorted chunk list. Chunks are
+	not placed into regular bins until after they have
+	been given one chance to be used in malloc.
       */
 
-      else {
-        size += nextsize;
-        set_head(p, size | PREV_INUSE);
-        av->top = p;
-        check_chunk(av, p);
-      }
+      bck = unsorted_chunks(av);
+      fwd = bck->fd;
+      p->bk = bck;
+      p->fd = fwd;
+      bck->fd = p;
+      fwd->bk = p;
 
-      /*
-        If freeing a large space, consolidate possibly-surrounding
-        chunks. Then, if the total unused topmost memory exceeds trim
-        threshold, ask malloc_trim to reduce top.
-
-        Unless max_fast is 0, we don't know if there are fastbins
-        bordering top, so we cannot tell for sure whether threshold
-        has been reached unless fastbins are consolidated.  But we
-        don't want to consolidate on each free.  As a compromise,
-        consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
-        is reached.
-      */
+      set_head(p, size | PREV_INUSE);
+      set_foot(p, size);
+
+      check_free_chunk(av, p);
+    }
+
+    /*
+      If the chunk borders the current high end of memory,
+      consolidate into top
+    */
 
-      if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
-        if (have_fastchunks(av))
-          malloc_consolidate(av);
+    else {
+      size += nextsize;
+      set_head(p, size | PREV_INUSE);
+      av->top = p;
+      check_chunk(av, p);
+    }
 
-	if (av == &main_arena) {
+    /*
+      If freeing a large space, consolidate possibly-surrounding
+      chunks. Then, if the total unused topmost memory exceeds trim
+      threshold, ask malloc_trim to reduce top.
+
+      Unless max_fast is 0, we don't know if there are fastbins
+      bordering top, so we cannot tell for sure whether threshold
+      has been reached unless fastbins are consolidated.  But we
+      don't want to consolidate on each free.  As a compromise,
+      consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
+      is reached.
+    */
+
+    if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
+      if (have_fastchunks(av))
+	malloc_consolidate(av);
+
+      if (av == &main_arena) {
 #ifndef MORECORE_CANNOT_TRIM
-	  if ((unsigned long)(chunksize(av->top)) >=
-	      (unsigned long)(mp_.trim_threshold))
-	    sYSTRIm(mp_.top_pad, av);
+	if ((unsigned long)(chunksize(av->top)) >=
+	    (unsigned long)(mp_.trim_threshold))
+	  sYSTRIm(mp_.top_pad, av);
 #endif
-	} else {
-	  /* Always try heap_trim(), even if the top chunk is not
-             large, because the corresponding heap might go away.  */
-	  heap_info *heap = heap_for_ptr(top(av));
+      } else {
+	/* Always try heap_trim(), even if the top chunk is not
+	   large, because the corresponding heap might go away.  */
+	heap_info *heap = heap_for_ptr(top(av));
 
-	  assert(heap->ar_ptr == av);
-	  heap_trim(heap, mp_.top_pad);
-	}
+	assert(heap->ar_ptr == av);
+	heap_trim(heap, mp_.top_pad);
       }
-
     }
-    /*
-      If the chunk was allocated via mmap, release via munmap(). Note
-      that if HAVE_MMAP is false but chunk_is_mmapped is true, then
-      user must have overwritten memory. There's nothing we can do to
-      catch this error unless MALLOC_DEBUG is set, in which case
-      check_inuse_chunk (above) will have triggered error.
-    */
 
-    else {
+  }
+  /*
+    If the chunk was allocated via mmap, release via munmap(). Note
+    that if HAVE_MMAP is false but chunk_is_mmapped is true, then
+    user must have overwritten memory. There's nothing we can do to
+    catch this error unless MALLOC_DEBUG is set, in which case
+    check_inuse_chunk (above) will have triggered error.
+  */
+
+  else {
 #if HAVE_MMAP
-      int ret;
-      INTERNAL_SIZE_T offset = p->prev_size;
-      mp_.n_mmaps--;
-      mp_.mmapped_mem -= (size + offset);
-      ret = munmap((char*)p - offset, size + offset);
-      /* munmap returns non-zero on failure */
-      assert(ret == 0);
+    munmap_chunk (p);
 #endif
-    }
   }
 }
 
@@ -4528,7 +4521,8 @@ _int_realloc(mstate av, Void_t* oldmem, size_t bytes)
 
 #if REALLOC_ZERO_BYTES_FREES
   if (bytes == 0) {
-    _int_free(av, oldmem);
+    if (oldmem != 0)
+      _int_free(av, oldmem);
     return 0;
   }
 #endif
@@ -5474,45 +5468,19 @@ malloc_printerr(int action, const char *str, void *ptr)
 {
   if (action & 1)
     {
-      /* output string will be ": ADDR ***\n"  */
-      static const char suffix[] = " ***\n";
-      static const char prefix[] = ": 0x";
-      char buf[sizeof (prefix) - 1 + sizeof (void *) * 2 + sizeof (suffix)];
-      char *cp;
-      if (action & 4)
-	cp = memcpy (&buf[sizeof (buf) - 2], "\n", 2);
-      else
-	{
-	  cp = memcpy (&buf[sizeof (buf) - sizeof (suffix)], suffix,
-		       sizeof (suffix));
-	  cp = _itoa_word ((unsigned long int) ptr, cp, 16, 0);
-	  while (cp > &buf[sizeof (prefix) - 1])
-	    *--cp = '0';
-	  cp = memcpy (buf, prefix, sizeof (prefix) - 1);
-	}
+      char buf[2 * sizeof (uintptr_t) + 1];
 
-      struct iovec iov[3];
-      int n = 0;
-      if ((action & 4) == 0)
-	{
-	  iov[0].iov_base = (char *) "*** glibc detected *** ";
-	  iov[0].iov_len = strlen (iov[0].iov_base);
-	  ++n;
-	}
-      iov[n].iov_base = (char *) str;
-      iov[n].iov_len = strlen (str);
-      ++n;
-      iov[n].iov_base = cp;
-      iov[n].iov_len = &buf[sizeof (buf) - 1] - cp;
-      ++n;
-      if (TEMP_FAILURE_RETRY (__writev (STDERR_FILENO, iov, n)) == -1
-	  && errno == EBADF)
-	/* Standard error is not opened.  Try using syslog.  */
-	syslog (LOG_ERR, "%s%s%s", (char *) iov[0].iov_base,
-		(char *) iov[1].iov_base,
-		n == 3 ? (const char *) iov[2].iov_base : "");
+      buf[sizeof (buf) - 1] = '\0';
+      char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);
+      while (cp > buf)
+	*--cp = '0';
+
+      __libc_message (action & 2,
+		      action & 4
+		      ? "%s\n" : "*** glibc detected *** %s: 0x%s ***\n",
+		      str, cp);
     }
-  if (action & 2)
+  else if (action & 2)
     abort ();
 }
 
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
index 65b9c55467..5ad78eda00 100644
--- a/nis/ypclnt.c
+++ b/nis/ypclnt.c
@@ -846,7 +846,7 @@ ypprot_err (const int code)
 {
   if (code < YP_VERS || code > YP_NOKEY)
     return YPERR_YPERR;
-  return yp_2_yperr[code];
+  return yp_2_yperr[code - YP_VERS];
 }
 libnsl_hidden_def (ypprot_err)
 
diff --git a/posix/Makefile b/posix/Makefile
index 8bc15ad215..744f49f5b3 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -91,7 +91,6 @@ tests           += wordexp-test tst-exec tst-spawn
 endif
 others		:= getconf
 install-bin	:= getconf
-gpl2lgpl := getopt.c getopt1.c getopt.h	regex.c regex.h
 
 before-compile	:= testcases.h ptestcases.h
 
diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
index 7e45174708..fac8cbd051 100644
--- a/sysdeps/posix/libc_fatal.c
+++ b/sysdeps/posix/libc_fatal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995, 1997, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1994,1995,1997,2000,2004 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
@@ -16,44 +16,131 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdarg.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sysdep.h>
 #include <string.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/syslog.h>
+#include <not-cancel.h>
 
 #ifdef FATAL_PREPARE_INCLUDE
 #include FATAL_PREPARE_INCLUDE
 #endif
 
+struct str_list
+{
+  const char *str;
+  size_t len;
+  struct str_list *next;
+};
+
+
 /* Abort with an error message.  */
 void
-__libc_fatal (message)
-     const char *message;
+__libc_message (int do_abort, const char *fmt, ...)
 {
-  size_t len = strlen (message);
+  va_list ap;
+  va_list ap_copy;
+  int fd = -1;
+
+  va_start (ap, fmt);
+  va_copy (ap_copy, ap);
 
 #ifdef FATAL_PREPARE
   FATAL_PREPARE;
 #endif
 
-  while (len > 0)
+  /* Open a descriptor for /dev/tty unless the user explicitly
+     requests errors on standard error.  */
+  const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
+  if (on_2 == NULL || *on_2 == '\0')
+    fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
+
+  if (fd == -1)
+    fd = STDERR_FILENO;
+
+  struct str_list *list = NULL;
+  int nlist = 0;
+
+  const char *cp = fmt;
+  while (*cp != '\0')
     {
-      register int count = __write (STDERR_FILENO, message, len);
-      if (count > 0)
+      /* Find the next "%s" or the end of the string.  */
+      char *next = cp;
+      while (next[0] != '%' || next[1] != 's')
 	{
-	  message += count;
-	  len -= count;
+	  next = __strchrnul (next + 1, '%');
+
+	  if (next[0] == '\0')
+	    break;
 	}
-      else if (count < 0
-#ifdef EINTR
-	       && errno != EINTR
-#endif
-	       )
-	break;
+
+      /* Determine what to print.  */
+      const char *str;
+      size_t len;
+      if (cp[0] == '%' && cp[1] == 's')
+	{
+	  str = va_arg (ap, const char *);
+	  len = strlen (str);
+	  cp += 2;
+	}
+      else
+	{
+	  str = cp;
+	  len = next - cp;
+	  cp = next;
+	}
+
+      struct str_list *newp = alloca (sizeof (struct str_list));
+      newp->str = str;
+      newp->len = len;
+      newp->next = list;
+      list = newp;
+      ++nlist;
+    }
+
+  bool written = false;
+  if (nlist > 0)
+    {
+      struct iovec *iov = alloca (nlist * sizeof (struct iovec));
+      ssize_t total = 0;
+
+      for (int cnt = nlist - 1; cnt >= 0; --cnt)
+	{
+	  iov[cnt].iov_base = list->str;
+	  iov[cnt].iov_len = list->len;
+	  total += list->len;
+	  list = list->next;
+	}
+
+      if (TEMP_FAILURE_RETRY (__writev (fd, iov, nlist)) == total)
+	written = true;
     }
 
-  abort ();
+  va_end (ap);
+
+  /* If we  had no success writing the message, use syslog.  */
+  if (! written)
+    vsyslog (LOG_ERR, fmt, ap_copy);
+
+  va_end (ap_copy);
+
+  if (do_abort()
+      /* Kill the application.  */
+      abort ();
+}
+
+
+void
+__libc_fatal (message)
+     const char *message;
+{
+  __libc_message (1, "%s", message);
 }
 libc_hidden_def (__libc_fatal)
diff --git a/sysdeps/unix/sysv/linux/libc_fatal.c b/sysdeps/unix/sysv/linux/libc_fatal.c
index 46347bb20e..c0482d96f3 100644
--- a/sysdeps/unix/sysv/linux/libc_fatal.c
+++ b/sysdeps/unix/sysv/linux/libc_fatal.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993-1995,1997,2000,2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1993-1995,1997,2000,2002-2004 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
@@ -16,45 +16,143 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sysdep.h>
 #include <string.h>
-#include <abort-instr.h>
+#include <sysdep.h>
+#include <unistd.h>
+#include <sys/syslog.h>
 #ifndef ABORT_INSTRUCTION
 /* No such instruction is available.  */
 # define ABORT_INSTRUCTION
 #endif
 
 /* Abort with an error message.  */
+#include <not-cancel.h>
+
+#ifdef FATAL_PREPARE_INCLUDE
+#include FATAL_PREPARE_INCLUDE
+#endif
+
+struct str_list
+{
+  const char *str;
+  size_t len;
+  struct str_list *next;
+};
+
+
+/* Abort with an error message.  */
 void
-__libc_fatal (message)
-     const char *message;
+__libc_message (int do_abort, const char *fmt, ...)
 {
-  size_t len = strlen (message);
+  va_list ap;
+  va_list ap_copy;
+  int fd = -1;
+
+  va_start (ap, fmt);
+  va_copy (ap_copy, ap);
+
+#ifdef FATAL_PREPARE
+  FATAL_PREPARE;
+#endif
 
-  while (len > 0)
+  /* Open a descriptor for /dev/tty unless the user explicitly
+     requests errors on standard error.  */
+  const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
+  if (on_2 == NULL || *on_2 == '\0')
+    fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
+
+  if (fd == -1)
+    fd = STDERR_FILENO;
+
+  struct str_list *list = NULL;
+  int nlist = 0;
+
+  const char *cp = fmt;
+  while (*cp != '\0')
     {
-      INTERNAL_SYSCALL_DECL (err);
-      ssize_t count = INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO,
-					message, len);
-      if (! INTERNAL_SYSCALL_ERROR_P (count, err))
+      /* Find the next "%s" or the end of the string.  */
+      const char *next = cp;
+      while (next[0] != '%' || next[1] != 's')
 	{
-	  message += count;
-	  len -= count;
+	  next = __strchrnul (next + 1, '%');
+
+	  if (next[0] == '\0')
+	    break;
 	}
-      else if (INTERNAL_SYSCALL_ERRNO (count, err) != EINTR)
-	break;
+
+      /* Determine what to print.  */
+      const char *str;
+      size_t len;
+      if (cp[0] == '%' && cp[1] == 's')
+	{
+	  str = va_arg (ap, const char *);
+	  len = strlen (str);
+	  cp += 2;
+	}
+      else
+	{
+	  str = cp;
+	  len = next - cp;
+	  cp = next;
+	}
+
+      struct str_list *newp = alloca (sizeof (struct str_list));
+      newp->str = str;
+      newp->len = len;
+      newp->next = list;
+      list = newp;
+      ++nlist;
     }
 
-  /* Terminate the process.  */
-  _exit (127);
+  bool written = false;
+  if (nlist > 0)
+    {
+      struct iovec *iov = alloca (nlist * sizeof (struct iovec));
+      ssize_t total = 0;
+
+      for (int cnt = nlist - 1; cnt >= 0; --cnt)
+	{
+	  iov[cnt].iov_base = (void *) list->str;
+	  iov[cnt].iov_len = list->len;
+	  total += list->len;
+	  list = list->next;
+	}
+
+      INTERNAL_SYSCALL_DECL (err);
+      ssize_t cnt;
+      do
+	cnt = INTERNAL_SYSCALL (writev, err, 3, fd, iov, nlist);
+      while (INTERNAL_SYSCALL_ERROR_P (cnt, err)
+	     && INTERNAL_SYSCALL_ERRNO (cnt, err) == EINTR);
 
-  /* The previous call should never have returned.  */
-  while (1)
-    /* Try for ever and ever.  */
-    ABORT_INSTRUCTION;
+      if (cnt == total)
+	written = true;
+    }
+
+  va_end (ap);
+
+  /* If we  had no success writing the message, use syslog.  */
+  if (! written)
+    vsyslog (LOG_ERR, fmt, ap_copy);
+
+  va_end (ap_copy);
+
+  if (do_abort)
+    /* Terminate the process.  */
+    abort ();
+}
+
+
+void
+__libc_fatal (message)
+     const char *message;
+{
+  __libc_message (1, "%s", message);
 }
 libc_hidden_def (__libc_fatal)