This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch ibm/2.18/master updated. glibc-2.18-33-gdc3a1f9


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, ibm/2.18/master has been updated
       via  dc3a1f98dc4c86cb454474f4912ae325573655cb (commit)
       via  e20644b3a6f96eb053ab4c2c900f7bef7f472916 (commit)
       via  c51d675c459aefef8d84d5a0b114010f916ea278 (commit)
       via  6a6a386a3040726053a5fb8582ff26dc85d84741 (commit)
       via  7e0e64ead52591b968df582b0ddc247ba5c4eab4 (commit)
       via  c779e9df75256f19c7be8d12b2d163e2016a63f4 (commit)
       via  c4733da3f8e4c54e30f048c9e8d2b2fe2f53fd24 (commit)
       via  b8053c6138c8835fb27d30c7e034e240e92bce0f (commit)
       via  37d4728976aea69db23a061830828787a2fd05ed (commit)
       via  1034d41c8fe7b31ba8ba304d1fff93cecb183520 (commit)
       via  3874aa022b6f0f9aca9ad1ef703a77be1bc97b36 (commit)
       via  6f95434fd488e9b72117f9b93ec2e2dbf397a4d3 (commit)
       via  4a3abd22ecbda2d7b718b133fae2d2abfdfab614 (commit)
       via  d1aac9a6ff01c226c42bb934c170dd1c00ba8071 (commit)
       via  860ec8e62a01a9c9e5087aa4cfd3b5e03fc7649b (commit)
       via  3f71830d35d7bf4ac11664f0c48c3c68d250618b (commit)
       via  8e395175c4786ad9679851e3ed3c0c54a6f4e1f0 (commit)
       via  b51679672648410c6627a4bd169e076c5b36f47b (commit)
       via  a4faadaff25e19abf295556a23b7b889b4bf6df4 (commit)
       via  b502a3756d6979439130f1e46c2c27b62f493acd (commit)
       via  b3c7503940022f70ec8272c2c0d0a0e4489ae992 (commit)
       via  e53103749c19199b0ec23e8a5b330dd2e288f5ac (commit)
       via  85ce5db8d835281c8beff6e750c02c799dee3f6f (commit)
       via  c3a4bddd656561cfffba2605e148e65d4ff07e21 (commit)
       via  1778fd0a17a74422a58d8eada3fa08b80f0a0c27 (commit)
       via  8df86a8394d0ea121f2066efe618f2b1cc799be3 (commit)
       via  f8a004f1fa412e3aae77faa30b4dfb654d721510 (commit)
       via  f166b9c6e90d631115c59b4357357bc168d8e51a (commit)
      from  760b348db29b446efc760b4bc3627379cc61b0d8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=dc3a1f98dc4c86cb454474f4912ae325573655cb

commit dc3a1f98dc4c86cb454474f4912ae325573655cb
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Sep 25 13:43:04 2013 -0500

    PowerPC: Fix POINTER_CHK_GUARD thread register for PPC64

diff --git a/ChangeLog b/ChangeLog
index e658237..b0048f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-25  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h (POINTER_CHK_GUARD:
+	Fix thread ID register.
+
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
 	[BZ #15857]
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 4620f96..e80a683 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -6,7 +6,7 @@
 #define POINTER_CHK_GUARD \
   ({												\
      uintptr_t x;										\
-     asm ("ld %0,%1(2)"										\
+     asm ("ld %0,%1(13)"										\
 	  : "=r" (x)										\
 	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
          );											\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e20644b3a6f96eb053ab4c2c900f7bef7f472916

commit e20644b3a6f96eb053ab4c2c900f7bef7f472916
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Sep 13 09:26:02 2013 +0100

    Add CVE-2013-4332 to NEWS.

diff --git a/NEWS b/NEWS
index e8f1099..ef92d7c 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,11 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2013-4332 The pvalloc, valloc, memalign, posix_memalign and
+  aligned_alloc functions could allocate too few bytes or corrupt the
+  heap when passed very large allocation size values (Bugzilla #15855,
+  #15856, #15857).
+
 * CVE-2013-4788 The pointer guard used for pointer mangling was not
   initialized for static applications resulting in the security feature
   being disabled. The pointer guard is now correctly initialized to a

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c51d675c459aefef8d84d5a0b114010f916ea278

commit c51d675c459aefef8d84d5a0b114010f916ea278
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 12:54:29 2013 +0100

    malloc: Check for integer overflow in memalign.
    
    A large bytes parameter to memalign could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15857]
    	* malloc/malloc.c (__libc_memalign): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 7edeac3..e658237 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15857]
+	* malloc/malloc.c (__libc_memalign): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15856]
 	* malloc/malloc.c (__libc_valloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 31e2dfa..ebbe86d 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3015,6 +3015,13 @@ __libc_memalign(size_t alignment, size_t bytes)
   /* Otherwise, ensure that it is at least a minimum chunk size */
   if (alignment <  MINSIZE) alignment = MINSIZE;
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - alignment - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   arena_get(ar_ptr, bytes + alignment + MINSIZE);
   if(!ar_ptr)
     return 0;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6a6a386a3040726053a5fb8582ff26dc85d84741

commit 6a6a386a3040726053a5fb8582ff26dc85d84741
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 11:59:37 2013 +0100

    malloc: Check for integer overflow in valloc.
    
    A large bytes parameter to valloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15856]
    	* malloc/malloc.c (__libc_valloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 855cc5f..7edeac3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15856]
+	* malloc/malloc.c (__libc_valloc): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15855]
 	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index bcc08c4..31e2dfa 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3046,6 +3046,13 @@ __libc_valloc(size_t bytes)
 
   size_t pagesz = GLRO(dl_pagesize);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7e0e64ead52591b968df582b0ddc247ba5c4eab4

commit 7e0e64ead52591b968df582b0ddc247ba5c4eab4
Author: Will Newton <will.newton@linaro.org>
Date:   Mon Aug 12 15:08:02 2013 +0100

    malloc: Check for integer overflow in pvalloc.
    
    A large bytes parameter to pvalloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15855]
    	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index ea92d46..855cc5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
+	[BZ #15855]
+	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
+	does not overflow.
+
 2013-09-23  Carlos O'Donell  <carlos@redhat.com>
 
 	[BZ #15754]
diff --git a/malloc/malloc.c b/malloc/malloc.c
index be472b2..bcc08c4 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3082,6 +3082,13 @@ __libc_pvalloc(size_t bytes)
   size_t page_mask = GLRO(dl_pagesize) - 1;
   size_t rounded_bytes = (bytes + page_mask) & ~(page_mask);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - 2*pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c779e9df75256f19c7be8d12b2d163e2016a63f4

commit c779e9df75256f19c7be8d12b2d163e2016a63f4
Author: Carlos O'Donell <carlos@redhat.com>
Date:   Mon Sep 23 00:52:09 2013 -0400

    BZ #15754: CVE-2013-4788
    
    The pointer guard used for pointer mangling was not initialized for
    static applications resulting in the security feature being disabled.
    The pointer guard is now correctly initialized to a random value for
    static applications. Existing static applications need to be
    recompiled to take advantage of the fix.
    
    The test tst-ptrguard1-static and tst-ptrguard1 add regression
    coverage to ensure the pointer guards are sufficiently random
    and initialized to a default value.

diff --git a/ChangeLog b/ChangeLog
index 45f8e4e..ea92d46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-09-23  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* elf/Makefile (tests): Add tst-ptrguard1.
+	(tests-static): Add tst-ptrguard1-static.
+	(tst-ptrguard1-ARGS): Define.
+	(tst-ptrguard1-static-ARGS): Define.
+	* elf/tst-ptrguard1.c: New file.
+	* elf/tst-ptrguard1-static.c: New file.
+	* sysdeps/x86_64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+	* sysdeps/i386/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc32/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-32/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-64/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc32/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc64/stackguard-macros.h: Likewise.
+
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
diff --git a/NEWS b/NEWS
index 37601e6..e8f1099 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,12 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2013-4788 The pointer guard used for pointer mangling was not
+  initialized for static applications resulting in the security feature
+  being disabled. The pointer guard is now correctly initialized to a
+  random value for static applications. Existing static applications need
+  to be recompiled to take advantage of the fix (bug 15754).
+
 * CVE-2012-4412 The strcoll implementation caches indices and rules for
   large collation sequences to optimize multiple passes.  This cache
   computation may overflow for large collation sequences and may cause a
diff --git a/csu/libc-start.c b/csu/libc-start.c
index e5da3ef..c898d06 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -37,6 +37,12 @@ extern void __pthread_initialize_minimal (void);
    in thread local area.  */
 uintptr_t __stack_chk_guard attribute_relro;
 # endif
+# ifndef  THREAD_SET_POINTER_GUARD
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+	attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
 #endif
 
 #ifdef HAVE_PTR_NTHREADS
@@ -195,6 +201,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 # else
   __stack_chk_guard = stack_chk_guard;
 # endif
+
+  /* Set up the pointer guard value.  */
+  uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+							 stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+  THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+  __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
 #endif
 
   /* Register the destructor of the dynamic linker if there is any.  */
diff --git a/elf/Makefile b/elf/Makefile
index 3b58649..98834f4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -121,7 +121,8 @@ endif
 tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
 	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5
 tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
-	       tst-leaks1-static tst-array1-static tst-array5-static
+	       tst-leaks1-static tst-array1-static tst-array5-static \
+	       tst-ptrguard1-static
 ifeq (yes,$(build-shared))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
@@ -145,7 +146,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit1 tst-audit2 tst-audit8 \
 	 tst-stackguard1 tst-addr1 tst-thrlock \
 	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
-	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv
+	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+	 tst-ptrguard1
 #	 reldep9
 test-srcs = tst-pathopt
 selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
@@ -1016,6 +1018,9 @@ LDFLAGS-order2mod2.so = $(no-as-needed)
 tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
 
+tst-ptrguard1-ARGS = --command "$(host-test-program-cmd) --child"
+tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child"
+
 $(objpfx)tst-leaks1: $(libdl)
 $(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
diff --git a/elf/tst-ptrguard1-static.c b/elf/tst-ptrguard1-static.c
new file mode 100644
index 0000000..7aff3b7
--- /dev/null
+++ b/elf/tst-ptrguard1-static.c
@@ -0,0 +1 @@
+#include "tst-ptrguard1.c"
diff --git a/elf/tst-ptrguard1.c b/elf/tst-ptrguard1.c
new file mode 100644
index 0000000..c344a04
--- /dev/null
+++ b/elf/tst-ptrguard1.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+#ifndef POINTER_CHK_GUARD
+extern uintptr_t __pointer_chk_guard;
+# define POINTER_CHK_GUARD __pointer_chk_guard
+#endif
+
+static const char *command;
+static bool child;
+static uintptr_t ptr_chk_guard_copy;
+static bool ptr_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  ptr_chk_guard_copy = POINTER_CHK_GUARD;
+  ptr_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (!ptr_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+    {
+      puts ("POINTER_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      write (2, &ptr_chk_guard_copy, sizeof (ptr_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_ptr_chk_guards[N + 1];
+  child_ptr_chk_guards[N] = ptr_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+	{
+	  printf ("couldn't create pipe: %m\n");
+	  return 1;
+	}
+
+      pid_t pid = fork ();
+      if (pid < 0)
+	{
+	  printf ("fork failed: %m\n");
+	  return 1;
+	}
+
+      if (!pid)
+	{
+	  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+	    {
+	      puts ("POINTER_CHK_GUARD changed after fork");
+	      exit (1);
+	    }
+
+	  close (fds[0]);
+	  close (2);
+	  dup2 (fds[1], 2);
+	  close (fds[1]);
+
+	  system (command);
+	  exit (0);
+	}
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_ptr_chk_guards[i],
+				    sizeof (uintptr_t))) != sizeof (uintptr_t))
+	{
+	  puts ("could not read ptr_chk_guard value from child");
+	  return 1;
+	}
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+	{
+	  printf ("waitpid failed: %m\n");
+	  return 1;
+	}
+      else if (termpid != pid)
+	{
+	  printf ("waitpid returned %ld != %ld\n",
+		  (long int) termpid, (long int) pid);
+	  return 1;
+	}
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+	{
+	  puts ("child hasn't exited with exit status 0");
+	  return 1;
+	}
+    }
+
+  qsort (child_ptr_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  /* The default pointer guard is the same as the default stack guard.
+     They are only set to default if dl_random is NULL.  */
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the pointer guard canaries are either randomized,
+     or equal to the default pointer guard value.
+     Even with randomized pointer guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_ptr_chk_guards[i] != child_ptr_chk_guards[i+1])
+	ndifferences++;
+      else if (child_ptr_chk_guards[i] == default_guard)
+	ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("pointer guard values are not randomized enough");
+      puts ("nor equal to the default value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND	10000
+#define OPT_CHILD	10001
+#define CMDLINE_OPTIONS	\
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+#define CMDLINE_PROCESS	\
+  case OPT_COMMAND:	\
+    command = optarg;	\
+    break;		\
+  case OPT_CHILD:	\
+    child = true;	\
+    break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64
index 92b81cb..f61f37f 100644
--- a/ports/ChangeLog.ia64
+++ b/ports/ChangeLog.ia64
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/ia64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-04  Andreas Jaeger  <aj@suse.de>
 
 	* sysdeps/unix/sysv/linux/ia64/sys/ptrace.h (PTRACE_LISTEN):
diff --git a/ports/ChangeLog.tile b/ports/ChangeLog.tile
index a2ec5e1..972bd81 100644
--- a/ports/ChangeLog.tile
+++ b/ports/ChangeLog.tile
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/tile/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-22  Chris Metcalf  <cmetcalf@tilera.com>
 
 	[BZ #15759]
diff --git a/ports/sysdeps/ia64/stackguard-macros.h b/ports/sysdeps/ia64/stackguard-macros.h
index dc683c2..3907293 100644
--- a/ports/sysdeps/ia64/stackguard-macros.h
+++ b/ports/sysdeps/ia64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("adds %0 = -8, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("adds %0 = -16, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
diff --git a/ports/sysdeps/tile/stackguard-macros.h b/ports/sysdeps/tile/stackguard-macros.h
index 589ea2b..f2e041b 100644
--- a/ports/sysdeps/tile/stackguard-macros.h
+++ b/ports/sysdeps/tile/stackguard-macros.h
@@ -4,11 +4,17 @@
 # if __WORDSIZE == 64
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -16; ld %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -24; ld %0, %0" : "=r" (x)); x; })
 # else
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; ld4s %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; ld4s %0, %0" : "=r" (x)); x; })
 # endif
 #else
 # define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; lw %0, %0" : "=r" (x)); x; })
+# define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; lw %0, %0" : "=r" (x)); x; })
 #endif
diff --git a/sysdeps/generic/stackguard-macros.h b/sysdeps/generic/stackguard-macros.h
index ababf65..4fa3d96 100644
--- a/sysdeps/generic/stackguard-macros.h
+++ b/sysdeps/generic/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 extern uintptr_t __stack_chk_guard;
 #define STACK_CHK_GUARD __stack_chk_guard
+
+extern uintptr_t __pointer_chk_guard_local;
+#define POINTER_CHK_GUARD __pointer_chk_guard_local
diff --git a/sysdeps/i386/stackguard-macros.h b/sysdeps/i386/stackguard-macros.h
index 8c31e19..0397629 100644
--- a/sysdeps/i386/stackguard-macros.h
+++ b/sysdeps/i386/stackguard-macros.h
@@ -2,3 +2,11 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("movl %%gs:%c1, %0" : "=r" (x)		\
+	  : "i" (offsetof (tcbhead_t, pointer_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/powerpc/powerpc32/stackguard-macros.h b/sysdeps/powerpc/powerpc32/stackguard-macros.h
index 839f6a4..b3d0af8 100644
--- a/sysdeps/powerpc/powerpc32/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc32/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("lwz %0,%1(2)"									\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 9da879c..4620f96 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("ld %0,%1(2)"										\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/s390/s390-32/stackguard-macros.h b/sysdeps/s390/s390-32/stackguard-macros.h
index b74c579..449e8d4 100644
--- a/sysdeps/s390/s390-32/stackguard-macros.h
+++ b/sysdeps/s390/s390-32/stackguard-macros.h
@@ -2,3 +2,14 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0; l %0,%1(%0)"			\
+	  : "=a" (x)					\
+	  : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/s390/s390-64/stackguard-macros.h b/sysdeps/s390/s390-64/stackguard-macros.h
index 0cebb5f..c8270fb 100644
--- a/sysdeps/s390/s390-64/stackguard-macros.h
+++ b/sysdeps/s390/s390-64/stackguard-macros.h
@@ -2,3 +2,17 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; sllg %0,%0,32; ear %0,%%a1; lg %0,0x28(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0;"				\
+	  "sllg %0,%0,32;"				\
+	  "ear %0,%%a1;"				\
+	  "lg %0,%1(%0)"				\
+	 : "=a" (x)					\
+	 : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/sparc/sparc32/stackguard-macros.h b/sysdeps/sparc/sparc32/stackguard-macros.h
index c0b02b0..1eef0f1 100644
--- a/sysdeps/sparc/sparc32/stackguard-macros.h
+++ b/sysdeps/sparc/sparc32/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ld [%%g7+0x18], %0" : "=r" (x)); x; })
diff --git a/sysdeps/sparc/sparc64/stackguard-macros.h b/sysdeps/sparc/sparc64/stackguard-macros.h
index 80f0635..cc0c12c 100644
--- a/sysdeps/sparc/sparc64/stackguard-macros.h
+++ b/sysdeps/sparc/sparc64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ldx [%%g7+0x30], %0" : "=r" (x)); x; })
diff --git a/sysdeps/x86_64/stackguard-macros.h b/sysdeps/x86_64/stackguard-macros.h
index d7fedb3..1948800 100644
--- a/sysdeps/x86_64/stackguard-macros.h
+++ b/sysdeps/x86_64/stackguard-macros.h
@@ -4,3 +4,8 @@
   ({ uintptr_t x;						\
      asm ("mov %%fs:%c1, %0" : "=r" (x)				\
 	  : "i" (offsetof (tcbhead_t, stack_guard))); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x;						\
+     asm ("mov %%fs:%c1, %0" : "=r" (x)				\
+	  : "i" (offsetof (tcbhead_t, pointer_guard))); x; })

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c4733da3f8e4c54e30f048c9e8d2b2fe2f53fd24

commit c4733da3f8e4c54e30f048c9e8d2b2fe2f53fd24
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:24:30 2013 +0530

    Check for integer overflow in cache size computation in strcoll
    
    strcoll is implemented using a cache for indices and weights of
    collation sequences in the strings so that subsequent passes do not
    have to search through collation data again.  For very large string
    inputs, the cache size computation could overflow.  In such a case,
    use the fallback function that does not cache indices and weights of
    collation sequences.
    
    Fixes CVE-2012-4412.

diff --git a/ChangeLog b/ChangeLog
index eb05e4f..45f8e4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
+	* string/tst-strcoll-overflow.c: New test case.
+	* string/Makefile (xtests): Add tst-strcoll-overflow.
+	* string/strcoll_l.c (STRCOLL): Skip allocating memory for
+	cache if string sizes may cause integer overflow.
+
+	[BZ #14547]
 	* string/strcoll_l.c (coll_seq): New members rule, idx,
 	save_idx and back_us.
 	(get_next_seq_nocache): New function.
diff --git a/NEWS b/NEWS
index cd49f6e..37601e6 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,12 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2012-4412 The strcoll implementation caches indices and rules for
+  large collation sequences to optimize multiple passes.  This cache
+  computation may overflow for large collation sequences and may cause a
+  stack or buffer overflow.  This is now fixed to use a slower algorithm
+  which does not use a cache if there is an integer overflow.
+
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
   Distributions can re-enable building and using pt_chown via the new configure
diff --git a/string/Makefile b/string/Makefile
index 72d3e29..17f9d68 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -57,6 +57,8 @@ tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 tests-ifunc := $(strop-tests:%=test-%-ifunc)
 tests += $(tests-ifunc)
 
+xtests = tst-strcoll-overflow
+
 include ../Rules
 
 tester-ENV = LANGUAGE=C
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index eb042ff..4ee101a 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -524,7 +524,15 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
+  size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1);
+
+  if (MIN (s1len, s2len) > size_max
+      || MAX (s1len, s2len) > size_max - MIN (s1len, s2len))
+    {
+      /* If the strings are long enough to cause overflow in the size request,
+         then skip the allocation and proceed with the non-cached routines.  */
+    }
+  else if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
 
diff --git a/string/tst-strcoll-overflow.c b/string/tst-strcoll-overflow.c
new file mode 100644
index 0000000..bb665ac
--- /dev/null
+++ b/string/tst-strcoll-overflow.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Verify that strcoll does not crash for large strings for which it cannot
+   cache weight lookup results.  The size is large enough to cause integer
+   overflows on 32-bit as well as buffer overflows on 64-bit.  The test should
+   work reasonably reliably when overcommit is disabled, but it obviously
+   depends on how much memory the system has.  There's a limitation to this
+   test in that it does not run to completion.  Actually collating such a
+   large string can take days and we can't have xcheck running that long.  For
+   that reason, we run the test for about 5 minutes and then assume that
+   everything is fine if there are no crashes.  */
+#define SIZE 0x40000000ul
+
+int
+do_test (void)
+{
+  if (setlocale (LC_COLLATE, "en_GB.UTF-8") == NULL)
+    {
+      puts ("setlocale failed, cannot test for overflow");
+      return 0;
+    }
+
+  char *p = malloc (SIZE);
+
+  if (p == NULL)
+    {
+      puts ("could not allocate memory");
+      return 1;
+    }
+
+  memset (p, 'x', SIZE - 1);
+  p[SIZE - 1] = 0;
+  printf ("%d\n", strcoll (p, p));
+  return 0;
+}
+
+#define TIMEOUT 300
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b8053c6138c8835fb27d30c7e034e240e92bce0f

commit b8053c6138c8835fb27d30c7e034e240e92bce0f
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:20:02 2013 +0530

    Fall back to non-cached sequence traversal and comparison on malloc fail
    
    strcoll currently falls back to alloca if malloc fails, resulting in a
    possible stack overflow.  This patch implements sequence traversal and
    comparison without caching indices and rules.
    
    Fixes CVE-2012-4424.

diff --git a/ChangeLog b/ChangeLog
index 1738c87..eb05e4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
-2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #14547]
+	* string/strcoll_l.c (coll_seq): New members rule, idx,
+	save_idx and back_us.
+	(get_next_seq_nocache): New function.
+	(do_compare_nocache): New function.
+	(STRCOLL): Use get_next_seq_nocache and do_compare_nocache
+	when malloc fails.
 
 	* string/strcoll_l.c (coll_seq): New structure.
 	(get_next_seq_cached): New function.
diff --git a/NEWS b/NEWS
index 2970338..cd49f6e 100644
--- a/NEWS
+++ b/NEWS
@@ -12,18 +12,18 @@ Version 2.18
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
   14142, 14155, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478,
-  14496, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909,
-  14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000,
-  15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055,
-  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
-  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
-  15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
-  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
-  15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
-  15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
-  15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15917, 15988, 16072.
+  14496, 14547, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908,
+  14909, 14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996,
+  15000, 15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054,
+  15055, 15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221,
+  15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327,
+  15330, 15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361,
+  15366, 15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418,
+  15419, 15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442,
+  15448, 15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506,
+  15522, 15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631,
+  15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
+  15893, 15895, 15917, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -45,6 +45,12 @@ Version 2.18
 * CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
   for AF_INET6 has been fixed (Bugzilla #16072).
 
+* CVE-2012-4424 The strcoll implementation uses malloc to cache indices and
+  rules for large collation sequences to optimize multiple passes and falls
+  back to alloca if malloc fails, resulting in a possible stack overflow.
+  The implementation now falls back to an uncached collation sequence lookup
+  if malloc fails.
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index 50ed84d..eb042ff 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -45,7 +45,7 @@
 typedef struct
 {
   int len;			/* Length of the current sequence.  */
-  int val;			/* Position of the sequence relative to the
+  size_t val;			/* Position of the sequence relative to the
 				   previous non-ignored sequence.  */
   size_t idxnow;		/* Current index in sequences.  */
   size_t idxmax;		/* Maximum index in sequences.  */
@@ -55,6 +55,12 @@ typedef struct
   const USTRING_TYPE *us;	/* The string.  */
   int32_t *idxarr;		/* Array to cache weight indices.  */
   unsigned char *rulearr;	/* Array to cache rules.  */
+  unsigned char rule;		/* Saved rule for the first sequence.  */
+  int32_t idx;			/* Index to weight of the current sequence.  */
+  int32_t save_idx;		/* Save looked up index of a forward
+				   sequence after the last backward
+				   sequence.  */
+  const USTRING_TYPE *back_us;	/* Beginning of the backward sequence.  */
 } coll_seq;
 
 /* Get next sequence.  The weight indices are cached, so we don't need to
@@ -64,7 +70,7 @@ get_next_seq_cached (coll_seq *seq, int nrules, int pass,
 		     const unsigned char *rulesets,
 		     const USTRING_TYPE *weights)
 {
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -146,7 +152,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
 	      const USTRING_TYPE *extra, const int32_t *indirect)
 {
 #include WEIGHT_H
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -162,7 +168,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
       ++val;
       if (backw_stop != ~0ul)
 	{
-	  /* The is something pushed.  */
+	  /* There is something pushed.  */
 	  if (backw == backw_stop)
 	    {
 	      /* The last pushed character was handled.  Continue
@@ -227,15 +233,199 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
   seq->us = us;
 }
 
-/* Compare two sequences.  */
+/* Get next sequence.  Traverse the string as required.  This function does not
+   set or use any index or rule cache.  */
+static void
+get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
+		      const USTRING_TYPE *weights, const int32_t *table,
+		      const USTRING_TYPE *extra, const int32_t *indirect,
+		      int pass)
+{
+#include WEIGHT_H
+  size_t val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  int32_t idx = seq->idx;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idx = seq->save_idx;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing anymore.  The backward sequence ended with
+		     the last sequence in the string.  Note that len is
+		     still zero.  */
+		  idx = 0;
+		  break;
+	        }
+	    }
+	  else
+	    {
+	      /* XXX Traverse BACKW sequences from the beginning of
+		 BACKW_STOP to get the next sequence.  Is ther a quicker way
+	         to do this?  */
+	      size_t i = backw_stop;
+	      us = seq->back_us;
+	      while (i < backw)
+		{
+		  int32_t tmp = findidx (&us, -1);
+		  idx = tmp & 0xffffff;
+		  i++;
+		}
+	      --backw;
+	      us = seq->us;
+	    }
+	}
+      else
+	{
+	  backw_stop = idxmax;
+	  int32_t prev_idx = idx;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      unsigned char rule = tmp >> 24;
+	      prev_idx = idx;
+	      idx = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      /* Save the rule for the first sequence.  */
+	      if (__glibc_unlikely (idxcnt == 0))
+	        seq->rule = rule;
+
+	      if ((rulesets[rule * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that len is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	    }
+	  else
+	    {
+	      /* We pushed backward sequences.  If the stream ended with the
+		 backward sequence, then we process the last sequence we
+		 found.  Otherwise we process the sequence before the last
+		 one since the last one was a forward sequence.  */
+	      seq->back_us = seq->us;
+	      seq->us = us;
+	      backw = idxcnt;
+	      if (idxmax > idxcnt)
+		{
+		  backw--;
+		  seq->save_idx = idx;
+		  idx = prev_idx;
+		}
+	      if (backw > backw_stop)
+		backw--;
+	    }
+	}
+
+      len = weights[idx++];
+      /* Skip over indices of previous levels.  */
+      for (int i = 0; i < pass; i++)
+	{
+	  idx += len;
+	  len = weights[idx];
+	  idx++;
+	}
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->us = us;
+  seq->idx = idx;
+}
+
+/* Compare two sequences.  This version does not use the index and rules
+   cache.  */
+static int
+do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position,
+		    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
+  int idx1 = seq1->idx;
+  int idx2 = seq2->idx;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 > val2 ? 1 : -1;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1] != weights[idx2])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1] - weights[idx2];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1;
+      ++idx2;
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  seq1->idx = idx1;
+  seq2->idx = idx2;
+  return result;
+}
+
+/* Compare two sequences using the index cache.  */
 static int
 do_compare (coll_seq *seq1, coll_seq *seq2, int position,
 	    const USTRING_TYPE *weights)
 {
   int seq1len = seq1->len;
   int seq2len = seq2->len;
-  int val1 = seq1->val;
-  int val2 = seq2->val;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
   int32_t *idx1arr = seq1->idxarr;
   int32_t *idx2arr = seq2->idxarr;
   int idx1now = seq1->idxnow;
@@ -245,7 +435,7 @@ do_compare (coll_seq *seq1, coll_seq *seq2, int position,
   /* Test for position if necessary.  */
   if (position && val1 != val2)
     {
-      result = val1 - val2;
+      result = val1 > val2 ? 1 : -1;
       goto out;
     }
 
@@ -334,57 +524,62 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indices.  */
-  seq1.us = (const USTRING_TYPE *) s1;
-  seq2.us = (const USTRING_TYPE *) s2;
-
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      seq2.idxarr = &seq1.idxarr[s1len];
-      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
-      seq2.rulearr = &seq1.rulearr[s1len];
-
-      if (seq1.idxarr == NULL)
-	/* No memory.  Well, go with the stack then.
-
-	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indices we will
-	   do this in time.  This means, though, that this happens for
-	   every pass again.  */
-	goto try_stack;
-      use_malloc = true;
+
+      /* If we failed to allocate memory, we leave everything as NULL so that
+	 we use the nocache version of traversal and comparison functions.  */
+      if (seq1.idxarr != NULL)
+	{
+	  seq2.idxarr = &seq1.idxarr[s1len];
+	  seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+	  seq2.rulearr = &seq1.rulearr[s1len];
+	  use_malloc = true;
+	}
     }
   else
     {
-    try_stack:
       seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
       seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
       seq1.rulearr = (unsigned char *) alloca (s1len);
       seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  seq1.rulearr[0] = 0;
+  int rule = 0;
 
   /* Cache values in the first pass and if needed, use them in subsequent
      passes.  */
   for (int pass = 0; pass < nrules; ++pass)
     {
       seq1.idxcnt = 0;
+      seq1.idx = 0;
+      seq2.idx = 0;
       seq1.backw_stop = ~0ul;
       seq1.backw = ~0ul;
       seq2.idxcnt = 0;
       seq2.backw_stop = ~0ul;
       seq2.backw = ~0ul;
 
+      /* We need the elements of the strings as unsigned values since they
+	 are used as indices.  */
+      seq1.us = (const USTRING_TYPE *) s1;
+      seq2.us = (const USTRING_TYPE *) s2;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
+      int position = rulesets[rule * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  if (pass == 0)
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    {
+	      get_next_seq_nocache (&seq1, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	      get_next_seq_nocache (&seq2, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	    }
+	  else if (pass == 0)
 	    {
 	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
 			    indirect);
@@ -411,10 +606,18 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 	      goto free_and_return;
 	    }
 
-	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    result = do_compare_nocache (&seq1, &seq2, position, weights);
+	  else
+	    result = do_compare (&seq1, &seq2, position, weights);
 	  if (result != 0)
 	    goto free_and_return;
 	}
+
+      if (__glibc_likely (seq1.rulearr != NULL))
+	rule = seq1.rulearr[0];
+      else
+	rule = seq1.rule;
     }
 
   /* Free the memory if needed.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=37d4728976aea69db23a061830828787a2fd05ed

commit 37d4728976aea69db23a061830828787a2fd05ed
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Tue Aug 20 08:40:05 2013 +0530

    Simplify strcoll implementation
    
    Break up strcoll into simpler functions so that the logic is easier to
    follow and maintain.

diff --git a/ChangeLog b/ChangeLog
index c83db92..1738c87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	* string/strcoll_l.c (coll_seq): New structure.
+	(get_next_seq_cached): New function.
+	(get_next_seq): New function.
+	(do_compare): New function.
+	(STRCOLL): Use GNU style definition.  Simplify implementation
+	by using get_next_seq, get_next_seq_cached and do_compare.
+
 2013-10-31  Andreas Schwab  <schwab@suse.de>
 
 	[BZ# 15917]
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index ecda08f..50ed84d 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -41,11 +41,244 @@
 
 #include "../locale/localeinfo.h"
 
+/* Track status while looking for sequences in a string.  */
+typedef struct
+{
+  int len;			/* Length of the current sequence.  */
+  int val;			/* Position of the sequence relative to the
+				   previous non-ignored sequence.  */
+  size_t idxnow;		/* Current index in sequences.  */
+  size_t idxmax;		/* Maximum index in sequences.  */
+  size_t idxcnt;		/* Current count of indices.  */
+  size_t backw;			/* Current Backward sequence index.  */
+  size_t backw_stop;		/* Index where the backward sequences stop.  */
+  const USTRING_TYPE *us;	/* The string.  */
+  int32_t *idxarr;		/* Array to cache weight indices.  */
+  unsigned char *rulearr;	/* Array to cache rules.  */
+} coll_seq;
+
+/* Get next sequence.  The weight indices are cached, so we don't need to
+   traverse the string.  */
+static void
+get_next_seq_cached (coll_seq *seq, int nrules, int pass,
+		     const unsigned char *rulesets,
+		     const USTRING_TYPE *weights)
+{
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing any more.  The backward sequence
+		     ended with the last sequence in the string.  */
+		  idxnow = ~0ul;
+		  break;
+		}
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxcnt;
+
+	  while (idxcnt < idxmax)
+	    {
+	      if ((rulesets[rulearr[idxcnt] * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop == idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt++;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxnow = idxnow;
+}
+
+/* Get next sequence.  Traverse the string as required.  */
+static void
+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
+	      const USTRING_TYPE *weights, const int32_t *table,
+	      const USTRING_TYPE *extra, const int32_t *indirect)
+{
+#include WEIGHT_H
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* The is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		/* Nothing any more.  The backward sequence ended with
+		   the last sequence in the string.  Note that LEN
+		   is still zero.  */
+		break;
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxmax;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      rulearr[idxmax] = tmp >> 24;
+	      idxarr[idxmax] = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      if ((rulesets[rulearr[idxcnt] * nrules]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->idxnow = idxnow;
+  seq->us = us;
+}
+
+/* Compare two sequences.  */
+static int
+do_compare (coll_seq *seq1, coll_seq *seq2, int position,
+	    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  int val1 = seq1->val;
+  int val2 = seq2->val;
+  int32_t *idx1arr = seq1->idxarr;
+  int32_t *idx2arr = seq2->idxarr;
+  int idx1now = seq1->idxnow;
+  int idx2now = seq2->idxnow;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 - val2;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1arr[idx1now];
+      ++idx2arr[idx2now];
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  return result;
+}
+
 int
-STRCOLL (s1, s2, l)
-     const STRING_TYPE *s1;
-     const STRING_TYPE *s2;
-     __locale_t l;
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 {
   struct __locale_data *current = l->__locales[LC_COLLATE];
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
@@ -56,34 +289,6 @@ STRCOLL (s1, s2, l)
   const USTRING_TYPE *weights;
   const USTRING_TYPE *extra;
   const int32_t *indirect;
-  uint_fast32_t pass;
-  int result = 0;
-  const USTRING_TYPE *us1;
-  const USTRING_TYPE *us2;
-  size_t s1len;
-  size_t s2len;
-  int32_t *idx1arr;
-  int32_t *idx2arr;
-  unsigned char *rule1arr;
-  unsigned char *rule2arr;
-  size_t idx1max;
-  size_t idx2max;
-  size_t idx1cnt;
-  size_t idx2cnt;
-  size_t idx1now;
-  size_t idx2now;
-  size_t backw1_stop;
-  size_t backw2_stop;
-  size_t backw1;
-  size_t backw2;
-  int val1;
-  int val2;
-  int position;
-  int seq1len;
-  int seq2len;
-  int use_malloc;
-
-#include WEIGHT_H
 
   if (nrules == 0)
     return STRCMP (s1, s2);
@@ -98,7 +303,6 @@ STRCOLL (s1, s2, l)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
   indirect = (const int32_t *)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
-  use_malloc = 0;
 
   assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
   assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
@@ -106,18 +310,13 @@ STRCOLL (s1, s2, l)
   assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
 
   /* We need this a few times.  */
-  s1len = STRLEN (s1);
-  s2len = STRLEN (s2);
+  size_t s1len = STRLEN (s1);
+  size_t s2len = STRLEN (s2);
 
   /* Catch empty strings.  */
-  if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
+  if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0))
     return (s1len != 0) - (s2len != 0);
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indeces.  */
-  us1 = (const USTRING_TYPE *) s1;
-  us2 = (const USTRING_TYPE *) s2;
-
   /* Perform the first pass over the string and while doing this find
      and store the weights for each character.  Since we want this to
      be as fast as possible we are using `alloca' to store the temporary
@@ -127,411 +326,101 @@ STRCOLL (s1, s2, l)
 
      Please note that the localedef programs makes sure that `position'
      is not used at the first level.  */
+
+  coll_seq seq1, seq2;
+  bool use_malloc = false;
+  int result = 0;
+
+  memset (&seq1, 0, sizeof (seq1));
+  seq2 = seq1;
+
+  /* We need the elements of the strings as unsigned values since they
+     are used as indices.  */
+  seq1.us = (const USTRING_TYPE *) s1;
+  seq2.us = (const USTRING_TYPE *) s2;
+
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
-      idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      idx2arr = &idx1arr[s1len];
-      rule1arr = (unsigned char *) &idx2arr[s2len];
-      rule2arr = &rule1arr[s1len];
+      seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
+      seq2.idxarr = &seq1.idxarr[s1len];
+      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+      seq2.rulearr = &seq1.rulearr[s1len];
 
-      if (idx1arr == NULL)
+      if (seq1.idxarr == NULL)
 	/* No memory.  Well, go with the stack then.
 
 	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indeces we will
+	   differently.  Instead of precomputing the indices we will
 	   do this in time.  This means, though, that this happens for
 	   every pass again.  */
 	goto try_stack;
-      use_malloc = 1;
+      use_malloc = true;
     }
   else
     {
     try_stack:
-      idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
-      idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
-      rule1arr = (unsigned char *) alloca (s1len);
-      rule2arr = (unsigned char *) alloca (s2len);
+      seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
+      seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
+      seq1.rulearr = (unsigned char *) alloca (s1len);
+      seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  idx1cnt = 0;
-  idx2cnt = 0;
-  idx1max = 0;
-  idx2max = 0;
-  idx1now = 0;
-  idx2now = 0;
-  backw1_stop = ~0ul;
-  backw2_stop = ~0ul;
-  backw1 = ~0ul;
-  backw2 = ~0ul;
-  seq1len = 0;
-  seq2len = 0;
-  position = rulesets[0] & sort_position;
-  while (1)
-    {
-      val1 = 0;
-      val2 = 0;
-
-      /* Get the next non-IGNOREd element for string `s1'.  */
-      if (seq1len == 0)
-	do
-	  {
-	    ++val1;
-
-	    if (backw1_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw1 == backw1_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx1cnt < idx1max)
-		      {
-			idx1now = idx1cnt;
-			backw1_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq1len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx1now = --backw1;
-	      }
-	    else
-	      {
-		backw1_stop = idx1max;
-
-		while (*us1 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us1, -1);
-		    rule1arr[idx1max] = tmp >> 24;
-		    idx1arr[idx1max] = tmp & 0xffffff;
-		    idx1cnt = idx1max++;
-
-		    if ((rulesets[rule1arr[idx1cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx1cnt;
-		  }
-
-		if (backw1_stop >= idx1cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx1cnt == idx1max || backw1_stop > idx1cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw1_stop = ~0ul;
-		    idx1now = idx1cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx1now = backw1 = idx1cnt - 1;
-	      }
-	  }
-	while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-      /* And the same for string `s2'.  */
-      if (seq2len == 0)
-	do
-	  {
-	    ++val2;
-
-	    if (backw2_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw2 == backw2_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx2cnt < idx2max)
-		      {
-			idx2now = idx2cnt;
-			backw2_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq2len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx2now = --backw2;
-	      }
-	    else
-	      {
-		backw2_stop = idx2max;
-
-		while (*us2 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us2, -1);
-		    rule2arr[idx2max] = tmp >> 24;
-		    idx2arr[idx2max] = tmp & 0xffffff;
-		    idx2cnt = idx2max++;
-
-		    if ((rulesets[rule2arr[idx2cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx2cnt;
-		  }
-
-		if (backw2_stop >= idx2cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx2cnt == idx2max || backw2_stop > idx2cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw2_stop = ~0ul;
-		    idx2now = idx2cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx2now = backw2 = idx2cnt - 1;
-	      }
-	  }
-	while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
-
-      /* See whether any or both strings are empty.  */
-      if (seq1len == 0 || seq2len == 0)
-	{
-	  if (seq1len == seq2len)
-	    /* Both ended.  So far so good, both strings are equal at the
-	       first level.  */
-	    break;
-
-	  /* This means one string is shorter than the other.  Find out
-	     which one and return an appropriate value.  */
-	  result = seq1len == 0 ? -1 : 1;
-	  goto free_and_return;
-	}
-
-      /* Test for position if necessary.  */
-      if (position && val1 != val2)
-	{
-	  result = val1 - val2;
-	  goto free_and_return;
-	}
-
-      /* Compare the two sequences.  */
-      do
-	{
-	  if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-	    {
-	      /* The sequences differ.  */
-	      result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
-	      goto free_and_return;
-	    }
-
-	  /* Increment the offsets.  */
-	  ++idx1arr[idx1now];
-	  ++idx2arr[idx2now];
+  seq1.rulearr[0] = 0;
 
-	  --seq1len;
-	  --seq2len;
-	}
-      while (seq1len > 0 && seq2len > 0);
-
-      if (position && seq1len != seq2len)
-	{
-	  result = seq1len - seq2len;
-	  goto free_and_return;
-	}
-    }
-
-  /* Now the remaining passes over the weights.  We now use the
-     indeces we found before.  */
-  for (pass = 1; pass < nrules; ++pass)
+  /* Cache values in the first pass and if needed, use them in subsequent
+     passes.  */
+  for (int pass = 0; pass < nrules; ++pass)
     {
+      seq1.idxcnt = 0;
+      seq1.backw_stop = ~0ul;
+      seq1.backw = ~0ul;
+      seq2.idxcnt = 0;
+      seq2.backw_stop = ~0ul;
+      seq2.backw = ~0ul;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      idx1cnt = 0;
-      idx2cnt = 0;
-      backw1_stop = ~0ul;
-      backw2_stop = ~0ul;
-      backw1 = ~0ul;
-      backw2 = ~0ul;
-      position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
+      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  val1 = 0;
-	  val2 = 0;
-
-	  /* Get the next non-IGNOREd element for string `s1'.  */
-	  if (seq1len == 0)
-	    do
-	      {
-		++val1;
-
-		if (backw1_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw1 == backw1_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx1cnt < idx1max)
-			  {
-			    idx1now = idx1cnt;
-			    backw1_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx1now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx1now = --backw1;
-		  }
-		else
-		  {
-		    backw1_stop = idx1cnt;
-
-		    while (idx1cnt < idx1max)
-		      {
-			if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx1cnt;
-		      }
-
-		    if (backw1_stop == idx1cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx1cnt == idx1max)
-			  /* Note that seq1len is still zero.  */
-			  break;
-
-			backw1_stop = ~0ul;
-			idx1now = idx1cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx1now = backw1 = idx1cnt - 1;
-		  }
-	      }
-	    while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-	  /* And the same for string `s2'.  */
-	  if (seq2len == 0)
-	    do
-	      {
-		++val2;
-
-		if (backw2_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw2 == backw2_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx2cnt < idx2max)
-			  {
-			    idx2now = idx2cnt;
-			    backw2_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx2now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx2now = --backw2;
-		  }
-		else
-		  {
-		    backw2_stop = idx2cnt;
-
-		    while (idx2cnt < idx2max)
-		      {
-			if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx2cnt;
-		      }
-
-		    if (backw2_stop == idx2cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx2cnt == idx2max)
-			  /* Note that seq2len is still zero.  */
-			  break;
-
-			backw2_stop = ~0ul;
-			idx2now = idx2cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx2now = backw2 = idx2cnt - 1;
-		  }
-	      }
-	    while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
+	  if (pass == 0)
+	    {
+	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
+			    indirect);
+	      get_next_seq (&seq2, nrules, rulesets, weights, table, extra,
+			    indirect);
+	    }
+	  else
+	    {
+	      get_next_seq_cached (&seq1, nrules, pass, rulesets, weights);
+	      get_next_seq_cached (&seq2, nrules, pass, rulesets, weights);
+	    }
 
 	  /* See whether any or both strings are empty.  */
-	  if (seq1len == 0 || seq2len == 0)
+	  if (seq1.len == 0 || seq2.len == 0)
 	    {
-	      if (seq1len == seq2len)
+	      if (seq1.len == seq2.len)
 		/* Both ended.  So far so good, both strings are equal
 		   at this level.  */
 		break;
 
 	      /* This means one string is shorter than the other.  Find out
 		 which one and return an appropriate value.  */
-	      result = seq1len == 0 ? -1 : 1;
+	      result = seq1.len == 0 ? -1 : 1;
 	      goto free_and_return;
 	    }
 
-	  /* Test for position if necessary.  */
-	  if (position && val1 != val2)
-	    {
-	      result = val1 - val2;
-	      goto free_and_return;
-	    }
-
-	  /* Compare the two sequences.  */
-	  do
-	    {
-	      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-		{
-		  /* The sequences differ.  */
-		  result = (weights[idx1arr[idx1now]]
-			    - weights[idx2arr[idx2now]]);
-		  goto free_and_return;
-		}
-
-	      /* Increment the offsets.  */
-	      ++idx1arr[idx1now];
-	      ++idx2arr[idx2now];
-
-	      --seq1len;
-	      --seq2len;
-	    }
-	  while (seq1len > 0 && seq2len > 0);
-
-	  if (position && seq1len != seq2len)
-	    {
-	      result = seq1len - seq2len;
-	      goto free_and_return;
-	    }
+	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (result != 0)
+	    goto free_and_return;
 	}
     }
 
   /* Free the memory if needed.  */
  free_and_return:
   if (use_malloc)
-    free (idx1arr);
+    free (seq1.idxarr);
 
   return result;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1034d41c8fe7b31ba8ba304d1fff93cecb183520

commit 1034d41c8fe7b31ba8ba304d1fff93cecb183520
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu Oct 31 12:51:03 2013 +0100

    Fix parsing of 0e+0 as float

diff --git a/ChangeLog b/ChangeLog
index b0cab3f..c83db92 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-31  Andreas Schwab  <schwab@suse.de>
+
+	[BZ# 15917]
+	* stdio-common/vfscanf.c (_IO_vfwscanf): Handle leading '0' not
+	followed by 'x' as part of digit sequence.
+	* stdio-common/tst-sscanf.c (double_tests2): New tests.
+
 2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
diff --git a/NEWS b/NEWS
index f0a9346..2970338 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15988, 16072.
+  15895, 15917, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index 1edb227..3c34f58 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -109,6 +109,19 @@ struct test double_tests[] =
   { L("-inf"), L("%g"), 1 }
 };
 
+struct test2
+{
+  const CHAR *str;
+  const CHAR *fmt;
+  int retval;
+  char residual;
+} double_tests2[] =
+{
+  { L("0e+0"), L("%g%c"), 1, 0 },
+  { L("0xe+0"), L("%g%c"), 2, '+' },
+  { L("0x.e+0"), L("%g%c"), 2, '+' },
+};
+
 int
 main (void)
 {
@@ -196,5 +209,26 @@ main (void)
 	}
     }
 
+  for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i)
+    {
+      double dummy;
+      int ret;
+      char c = 0;
+
+      if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
+			 &dummy, &c)) != double_tests2[i].retval)
+	{
+	  printf ("double_tests2[%d] returned %d != %d\n",
+		  i, ret, double_tests2[i].retval);
+	  result = 1;
+	}
+      else if (ret == 2 && c != double_tests2[i].residual)
+	{
+	  printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
+		  i, c, double_tests2[i].residual);
+	  result = 1;
+	}
+    }
+
   return result;
 }
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 3430567..093c8b0 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1966,6 +1966,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
 		  if (width > 0)
 		    --width;
 		}
+	      else
+		got_digit = 1;
 	    }
 
 	  while (1)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3874aa022b6f0f9aca9ad1ef703a77be1bc97b36

commit 3874aa022b6f0f9aca9ad1ef703a77be1bc97b36
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 26 09:29:19 2013 -0500

    PowerPC: strcpy/stpcpy optimization for PPC64/POWER7
    
    This patch intends to unify both strcpy and stpcpy implementationsi
    for PPC64 and PPC64/POWER7. The idead default powerpc64 implementation
    is to provide both doubleword and word aligned memory access.
    
    For PPC64/POWER7 is also provide doubleword and word memory access,
    remove the branch hints, use the cmpb instruction for compare
    doubleword/words, and add an optimization for inputs of same alignment.

diff --git a/ChangeLog b/ChangeLog
index ed41494..b0cab3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
+	to provide a boost for large inputs with word alignment.
+	* sysdeps/powerpc/powerpc64/stpcpy.S (__stpcpy): Rewrite
+	implementation based on optimized PPC64 strcpy.
+	* sysdeps/powerpc/powerpc64/power7/strcpy.S: New file: optimized
+	strcpy for PPC64/POWER7 based on both doubleword and word load/store.
+	* sysdeps/powerpc/powerpc64/power7/stpcpy.S: New file: optimized
+	stpcpy for PPC64/POWER7 based on PPC64/POWER7 strcpy.
+
 2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #16072]
diff --git a/sysdeps/powerpc/powerpc64/power7/stpcpy.S b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
new file mode 100644
index 0000000..727dd06
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
@@ -0,0 +1,24 @@
+/* Optimized stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/power7/strcpy.S>
+
+weak_alias (__stpcpy, stpcpy)
+libc_hidden_def (__stpcpy)
+libc_hidden_builtin_def (stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/power7/strcpy.S b/sysdeps/powerpc/powerpc64/power7/strcpy.S
new file mode 100644
index 0000000..5c341a1
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/strcpy.S
@@ -0,0 +1,274 @@
+/* Optimized strcpy/stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+/* Implements the function
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   or
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   if USE_AS_STPCPY is defined. It tries to use aligned memory accesses
+   when possible using the following algorithm:
+
+   if (((((uintptr_t)dst & 0x7UL) == 0) && ((uintptr_t)src & 0x7UL) == 0))
+     goto aligned_doubleword_copy;
+   if (((((uintptr_t)dst & 0x3UL) == 0) && ((uintptr_t)src & 0x3UL) == 0))
+     goto aligned_word_copy;
+   if (((uintptr_t)dst & 0x7UL) == ((uintptr_t)src & 0x7UL))
+     goto same_alignment;
+   goto unaligned;
+
+   The aligned comparison are made using cmpb instructions.  */
+
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+	.machine  power7
+EALIGN (FUNC_NAME, 4, 0)
+	CALL_MCOUNT 2
+
+#define rTMP	r0
+#ifdef USE_AS_STPCPY
+#define rRTN	r3	/* pointer to previous word/doubleword in dest */
+#else
+#define rRTN	r12	/* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
+#define rMASK	r5	/* mask 0xffffffff | 0xffffffffffffffff */
+#define rWORD	r6	/* current word from src */
+#define rALT	r7	/* alternate word from src */
+#define rRTNAL	r8	/* alignment of return pointer */
+#define rSRCAL	r9	/* alignment of source pointer */
+#define rALCNT	r10	/* bytes to read to reach 8 bytes alignment */
+#define rSUBAL	r11	/* doubleword minus unaligned displacement */
+
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr	rRTN, r3
+#endif
+	or	rTMP, rSRC, rRTN
+	clrldi.	rTMP, rTMP, 61
+	bne	L(check_word_alignment)
+	b	L(aligned_doubleword_copy)
+
+L(same_alignment):
+/* Src and dst with same alignment: align both to doubleword.  */
+	mr	rALCNT, rRTN
+	lbz	rWORD, 0(rSRC)
+	subfic	rSUBAL, rRTNAL, 8
+	addi	rRTN, rRTN, 1
+	addi	rSRC, rSRC, 1
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, 0(rALCNT)
+	beq	cr7, L(s2)
+
+	add	rALCNT, rALCNT, rSUBAL
+	subf	rALCNT, rRTN, rALCNT
+	addi	rALCNT, rALCNT, 1
+	mtctr	rALCNT
+	b	L(s1)
+
+	.align 4
+L(s0):
+	addi	rSRC, rSRC, 1
+	lbz	rWORD, -1(rSRC)
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, -1(rALCNT)
+	beqlr	cr7
+	mr	rRTN, rALCNT
+L(s1):
+	addi	rALCNT, rRTN,1
+	bdnz	L(s0)
+	b L(aligned_doubleword_copy)
+	.align 4
+L(s2):
+	mr	rRTN, rALCNT
+	blr
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	.align 4
+L(aligned_doubleword_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -8
+	ld	rWORD, 0(rSRC)
+	b	L(g2)
+
+	.align 4
+L(g0):	ldu	rALT, 8(rSRC)
+	stdu	rWORD, 8(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpdi	rTMP, 0
+	bne	L(g1)
+	ldu	rWORD, 8(rSRC)
+	stdu	rALT, 8(rRTN)
+L(g2):	cmpb	rTMP, rWORD, rMASK
+	cmpdi	rTMP, 0		/* If rTMP is 0, no null's have been found.  */
+	beq	L(g0)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stbu	rALT, 8(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stbu	rTMP, 1(rRTN)
+#else
+	extrdi.	rTMP, rALT, 8, 0
+	stbu	rTMP, 8(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	stbu	rALT, 1(rRTN)
+#endif
+	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	beq	L(aligned_word_copy)
+	rldicl	rRTNAL, rRTN, 0, 61
+	rldicl	rSRCAL, rSRC, 0, 61
+	cmpld	cr7, rSRCAL, rRTNAL
+	beq	cr7, L(same_alignment)
+	b	L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	.align	4
+L(aligned_word_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -4
+	lwz	rWORD, 0(rSRC)
+	b	L(g5)
+
+	.align	4
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpwi	rTMP, 0
+	bne	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	cmpb	rTMP, rWORD, rMASK
+	cmpwi	rTMP, 0		/* If rTMP is 0, no null in word.  */
+	beq	L(g3)
+
+	mr      rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm. rTMP, rALT, 8, 24, 31
+	stbu    rTMP, 4(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 16, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 24, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	stbu    rALT, 1(rRTN)
+#endif
+	blr
+
+/* Oh well.  In this case, we just do a byte-by-byte copy.  */
+	.align	4
+L(unaligned):
+	lbz	rWORD, 0(rSRC)
+	addi	rRTN, rRTN, -1
+	cmpdi	rWORD, 0
+	beq	L(u2)
+
+	.align 	5
+L(u0):	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	beq	L(u2)
+	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	bne	L(u0)
+L(u2):	stbu	rWORD, 1(rRTN)
+	blr
+L(u1):	stbu	rALT, 1(rRTN)
+	blr
+END (FUNC_NAME)
+
+#ifndef USE_AS_STPCPY
+libc_hidden_builtin_def (strcpy)
+#endif
diff --git a/sysdeps/powerpc/powerpc64/stpcpy.S b/sysdeps/powerpc/powerpc64/stpcpy.S
index 070cd46..09aa3be 100644
--- a/sysdeps/powerpc/powerpc64/stpcpy.S
+++ b/sysdeps/powerpc/powerpc64/stpcpy.S
@@ -16,87 +16,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-
-/* See strlen.s for comments on how the end-of-string testing works.  */
-
-/* char * [r3] stpcpy (char *dest [r3], const char *src [r4])  */
-
-EALIGN (__stpcpy, 4, 0)
-	CALL_MCOUNT 2
-
-#define rTMP	r0
-#define rRTN	r3
-#define rDEST	r3		/* pointer to previous word in dest */
-#define rSRC	r4		/* pointer to previous word in src */
-#define rWORD	r6		/* current word from src */
-#define rFEFE	r7		/* 0xfefefeff */
-#define r7F7F	r8		/* 0x7f7f7f7f */
-#define rNEG	r9		/* ~(word in src | 0x7f7f7f7f) */
-#define rALT	r10		/* alternate word from src */
-
-	or	rTMP, rSRC, rDEST
-	clrldi.	rTMP, rTMP, 62
-	addi	rDEST, rDEST, -4
-	bne	L(unaligned)
-
-	lis	rFEFE, -0x101
-	lis	r7F7F, 0x7f7f
-	lwz	rWORD, 0(rSRC)
-	addi	rFEFE, rFEFE, -0x101
-	addi	r7F7F, r7F7F, 0x7f7f
-	b	L(g2)
-
-L(g0):	lwzu	rALT, 4(rSRC)
-	stwu	rWORD, 4(rDEST)
-	add	rTMP, rFEFE, rALT
-	nor	rNEG, r7F7F, rALT
-	and.	rTMP, rTMP, rNEG
-	bne-	L(g1)
-	lwzu	rWORD, 4(rSRC)
-	stwu	rALT, 4(rDEST)
-L(g2):	add	rTMP, rFEFE, rWORD
-	nor	rNEG, r7F7F, rWORD
-	and.	rTMP, rTMP, rNEG
-	beq+	L(g0)
-
-	mr	rALT, rWORD
-/* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
-	stbu	rTMP, 4(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 16, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 24, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	stbu	rALT, 1(rDEST)
-	blr
-
-/* Oh well.  In this case, we just do a byte-by-byte copy.  */
-	.align 4
-	nop
-L(unaligned):
-	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rDEST, 3
-	cmpwi	rWORD, 0
-	beq-	L(u2)
-
-L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
-	cmpwi	rALT, 0
-	beq-	L(u1)
-	nop		/* Let 601 load start of loop.  */
-	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
-	cmpwi	rWORD, 0
-	bne+	L(u0)
-L(u2):	stbu	rWORD, 1(rDEST)
-	blr
-L(u1):	stbu	rALT, 1(rDEST)
-	blr
-END (__stpcpy)
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/strcpy.S>
 
 weak_alias (__stpcpy, stpcpy)
 libc_hidden_def (__stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/strcpy.S b/sysdeps/powerpc/powerpc64/strcpy.S
index 4c6fd3f..793325d 100644
--- a/sysdeps/powerpc/powerpc64/strcpy.S
+++ b/sysdeps/powerpc/powerpc64/strcpy.S
@@ -22,25 +22,38 @@
 
 /* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
 
-EALIGN (strcpy, 4, 0)
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+EALIGN (FUNC_NAME, 4, 0)
 	CALL_MCOUNT 2
 
 #define rTMP	r0
-#define rRTN	r3	/* incoming DEST arg preserved as result */
-#define rSRC	r4	/* pointer to previous word in src */
-#define rDEST	r5	/* pointer to previous word in dest */
+#ifdef USE_AS_STPCPY
+#define rRTN    r3      /* pointer to previous word/doubleword in dest */
+#else
+#define rRTN    r12     /* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
 #define rWORD	r6	/* current word from src */
-#define rFEFE	r7	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+#define rFEFE	r7	/* constant 0xfefefeff | 0xfefefefefefefeff */
+#define r7F7F	r8	/* constant 0x7f7f7f7f | 0x7f7f7f7f7f7f7f7f */
+#define rNEG	r9	/* ~(word in s1 | r7F7F) */
 #define rALT	r10	/* alternate word from src */
 
-	dcbt	0,rSRC
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr      rRTN, r3
+#endif
 	or	rTMP, rSRC, rRTN
 	clrldi.	rTMP, rTMP, 61
-	addi	rDEST, rRTN, -8
-	dcbtst	0,rRTN
-	bne	L(unaligned)
+	bne	L(check_word_alignment)
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	addi	rRTN, rRTN, -8
 
 	lis	rFEFE, -0x101
 	lis	r7F7F, 0x7f7f
@@ -53,13 +66,13 @@ EALIGN (strcpy, 4, 0)
 	b	L(g2)
 
 L(g0):	ldu	rALT, 8(rSRC)
-	stdu	rWORD, 8(rDEST)
+	stdu	rWORD, 8(rRTN)
 	add	rTMP, rFEFE, rALT
 	nor	rNEG, r7F7F, rALT
 	and.	rTMP, rTMP, rNEG
 	bne-	L(g1)
 	ldu	rWORD, 8(rSRC)
-	stdu	rALT, 8(rDEST)
+	stdu	rALT, 8(rRTN)
 L(g2):	add	rTMP, rFEFE, rWORD
 	nor	rNEG, r7F7F, rWORD
 	and.	rTMP, rTMP, rNEG
@@ -68,28 +81,110 @@ L(g2):	add	rTMP, rFEFE, rWORD
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
 L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stbu	rALT, 8(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stbu	rTMP, 1(rRTN)
+#else
 	extrdi.	rTMP, rALT, 8, 0
-	stb	rTMP, 8(rDEST)
+	stbu	rTMP, 8(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 8
-	stb	rTMP, 9(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 16
-	stb	rTMP, 10(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 24
-	stb	rTMP, 11(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 32
-	stb	rTMP, 12(rDEST)
-	beqlr-
+	stbu	rTMP, 1(rRTN)
+	beqlr
 	extrdi.	rTMP, rALT, 8, 40
-	stb	rTMP, 13(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 48
-	stb	rTMP, 14(rDEST)
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	stbu	rALT, 1(rRTN)
+#endif
+	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	bne     L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	addi	rRTN, rRTN, -4
+
+	lis	rFEFE, -0x101
+	lis	r7F7F, 0x7f7f
+	lwz	rWORD, 0(rSRC)
+	addi	rFEFE, rFEFE, -0x101
+	addi	r7F7F, r7F7F, 0x7f7f
+	b	L(g5)
+
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	add	rTMP, rFEFE, rALT
+	nor	rNEG, r7F7F, rALT
+	and.	rTMP, rTMP, rNEG
+	bne-	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	add	rTMP, rFEFE, rWORD
+	nor	rNEG, r7F7F, rWORD
+	and.	rTMP, rTMP, rNEG
+	beq+	L(g3)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
 	beqlr-
-	stb	rALT, 15(rDEST)
+	stbu	rALT, 1(rRTN)
+#endif
 	blr
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
@@ -97,23 +192,25 @@ L(g1):
 	nop
 L(unaligned):
 	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rRTN, -1
+	addi	rRTN, rRTN, -1
 	cmpwi	rWORD, 0
 	beq-	L(u2)
 
 L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
+	stbu	rWORD, 1(rRTN)
 	cmpwi	rALT, 0
 	beq-	L(u1)
 	nop		/* Let 601 load start of loop.  */
 	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
+	stbu	rALT, 1(rRTN)
 	cmpwi	rWORD, 0
 	bne+	L(u0)
-L(u2):	stb	rWORD, 1(rDEST)
+L(u2):	stbu	rWORD, 1(rRTN)
 	blr
-L(u1):	stb	rALT, 1(rDEST)
+L(u1):	stbu	rALT, 1(rRTN)
 	blr
+END (FUNC_NAME)
 
-END (strcpy)
+#ifndef USE_AS_STPCPY
 libc_hidden_builtin_def (strcpy)
+#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6f95434fd488e9b72117f9b93ec2e2dbf397a4d3

commit 6f95434fd488e9b72117f9b93ec2e2dbf397a4d3
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Fri Oct 25 10:22:12 2013 +0530

    Fix stack overflow due to large AF_INET6 requests
    
    Resolves #16072 (CVE-2013-4458).
    
    This patch fixes another stack overflow in getaddrinfo when it is
    called with AF_INET6.  The AF_UNSPEC case was fixed as CVE-2013-1914,
    but the AF_INET6 case went undetected back then.

diff --git a/ChangeLog b/ChangeLog
index 3805278..ed41494 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,76 +1,9 @@
-2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
-	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
-	for NaNs before doing comparisons on argument.
-	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
-	Likewise.
-
-2013-10-04  Anton Blanchard <anton@au1.ibm.com>
-	    Alistair Popple <alistair@ozlabs.au.ibm.com>
-	    Alan Modra <amodra@gmail.com>
-
-	[BZ #15723]
-	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
-	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
-	_dl_hwcap access for little-endian.
-	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
-	destroy vmx regs when saving unaligned.
-	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
-	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
-	destroy vmx regs when saving unaligned.
-
-2013-09-09  Allan McRae  <allan@archlinux.org>
-
-	[BZ #15893]
-	* stdlib/isomac.c (get_null_defines): Fix memory leak.
-
-	[BZ #15892]
-	* libio/memstream.c (open_memstream): Fix memory leak.
-	* libio/wmemstream.c (open_wmemstream): Likewise.
-
-	[BZ #15895]
-	* nscd/netgroupcache.c: Fix nesting of ifdefs.
-
-2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
-
-	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
-	memory access for final bytes in some large inputs.
-	* sysdeps/powerpc/powerpc64/power7/memrchr.S (__memrchr): Likewise.
-
-2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
-
-	* string/test-memrchr.c: New file.
-	* string/test-memrchr-ifunc.c: New file.
-	* string/Makefile: Add new memrchr testcase.
-
-2013-09-03  Joseph Myers  <joseph@codesourcery.com>
-
-	[BZ #15427]
-	* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r): Use
-	2**-30 instead of 2**-70 as threshold for returning -log(|x|).
-	* math/libm-test.inc (lgamma_test_data): Add more tests.
-	* sysdeps/i386/fpu/libm-test-ulps: Update.
-	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
-
-2013-09-03   OndÅ?ej Bílka  <neleai@seznam.cz>
-
-	* sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: New file.
-	* sysdeps/x86_64/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
-	Add ifunc.
-	* sysdeps/x86_64/multiarch/Makefile (sysdep_routines):
-	Add strcmp-sse2-unaligned
-	* sysdeps/x86_64/multiarch/strcmp.S (strcmp): Add ifunc.
-
-2013-09-02  Mike Frysinger  <vapier@gentoo.org>
-
-	* Versions.def (libc): Add GLIBC_2.19.
-
-2013-09-02  Mike Frysinger  <vapier@gentoo.org>
-
-	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
-	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+	[BZ #16072]
+	* sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
+	heap for large requests.
 
->>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index 8689dd0..f0a9346 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15988.
+  15895, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -42,6 +42,9 @@ Version 2.18
   to the d_name member of struct dirent, or omit the terminating NUL
   character.  (Bugzilla #14699).
 
+* CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
+  for AF_INET6 has been fixed (Bugzilla #16072).
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 7bb3ded..2e97255 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 				&rc, &herrno, NULL, &localcanon));	      \
     if (rc != ERANGE || herrno != NETDB_INTERNAL)			      \
       break;								      \
-    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);		      \
+    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
+      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,	      \
+				      alloca_used);			      \
+    else								      \
+      {									      \
+	char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,		      \
+			      2 * tmpbuflen);				      \
+	if (newp == NULL)						      \
+	  {								      \
+	    result = -EAI_MEMORY;					      \
+	    goto free_and_return;					      \
+	  }								      \
+	tmpbuf = newp;							      \
+	malloc_tmpbuf = true;						      \
+	tmpbuflen = 2 * tmpbuflen;					      \
+      }									      \
   }									      \
   if (status == NSS_STATUS_SUCCESS && rc == 0)				      \
     h = &th;								      \
@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 	{								      \
 	  __set_h_errno (herrno);					      \
 	  _res.options |= old_res_options & RES_USE_INET6;		      \
-	  return -EAI_SYSTEM;						      \
+	  result = -EAI_SYSTEM;						      \
+	  goto free_and_return;						      \
 	}								      \
       if (herrno == TRY_AGAIN)						      \
 	no_data = EAI_AGAIN;						      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4a3abd22ecbda2d7b718b133fae2d2abfdfab614

commit 4a3abd22ecbda2d7b718b133fae2d2abfdfab614
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Thu Oct 10 19:11:30 2013 +0000

    Avoid ordered comparisons of NaNs in ldbl-128ibm acosl and asinl.

diff --git a/ChangeLog b/ChangeLog
index 28960dc..3805278 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+
+	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
+	for NaNs before doing comparisons on argument.
+	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
+	Likewise.
+
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 	    Alistair Popple <alistair@ozlabs.au.ibm.com>
 	    Alan Modra <amodra@gmail.com>
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
index 5d2af30..4b61281 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
@@ -151,11 +151,13 @@ static const long double
 long double
 __ieee754_acosl (long double x)
 {
-  long double z, r, w, p, q, s, t, f2;
+  long double a, z, r, w, p, q, s, t, f2;
   ieee854_long_double_shape_type u;
 
-  u.value = __builtin_fabsl (x);
-  if (u.value == 1.0L)
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
+  a = __builtin_fabsl (x);
+  if (a == 1.0L)
     {
       if (x > 0.0L)
 	return 0.0;		/* acos(1) = 0  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
index b395439..bb69402 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
@@ -135,6 +135,8 @@ __ieee754_asinl (long double x)
   int flag;
   ieee854_long_double_shape_type u;
 
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
   flag = 0;
   u.value = __builtin_fabsl (x);
   if (u.value == 1.0L)	/* |x|>= 1 */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d1aac9a6ff01c226c42bb934c170dd1c00ba8071

commit d1aac9a6ff01c226c42bb934c170dd1c00ba8071
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:34:40 2013 +0930

    PowerPC LE setjmp/longjmp
    
    http://sourceware.org/ml/libc-alpha/2013-08/msg00089.html
    
    Little-endian fixes for setjmp/longjmp.  When writing these I noticed
    the setjmp code corrupts the non volatile VMX registers when using an
    unaligned buffer.  Anton fixed this, and also simplified it quite a
    bit.
    
    The current code uses boilerplate for the case where we want to store
    16 bytes to an unaligned address.  For that we have to do a
    read/modify/write of two aligned 16 byte quantities.  In our case we
    are storing a bunch of back to back data (consective VMX registers),
    and only the start and end of the region need the read/modify/write.
    
    	[BZ #15723]
    	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
    	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
    	_dl_hwcap access for little-endian.
    	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
    	destroy vmx regs when saving unaligned.
    	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
    	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
    	destroy vmx regs when saving unaligned.

diff --git a/ChangeLog b/ChangeLog
index b9239a5..28960dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+	    Alistair Popple <alistair@ozlabs.au.ibm.com>
+	    Alan Modra <amodra@gmail.com>
+
+	[BZ #15723]
+	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
+	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
+	_dl_hwcap access for little-endian.
+	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
+	destroy vmx regs when saving unaligned.
+	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
+	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
+	destroy vmx regs when saving unaligned.
+
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
 	[BZ #15893]
diff --git a/sysdeps/powerpc/jmpbuf-offsets.h b/sysdeps/powerpc/jmpbuf-offsets.h
index 64c658a..f2116bd 100644
--- a/sysdeps/powerpc/jmpbuf-offsets.h
+++ b/sysdeps/powerpc/jmpbuf-offsets.h
@@ -21,12 +21,10 @@
 #define JB_LR     2  /* The address we will return to */
 #if __WORDSIZE == 64
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18*2 words total.  */
-# define JB_CR     21 /* Condition code registers with the VRSAVE at */
-                       /* offset 172 (low half of the double word.  */
+# define JB_CR     21 /* Shared dword with VRSAVE.  CR word at offset 172.  */
 # define JB_FPRS   22 /* FPRs 14 through 31 are saved, 18*2 words total.  */
 # define JB_SIZE   (64 * 8) /* As per PPC64-VMX ABI.  */
-# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */
-                       /* 168 (high half of the double word).  */
+# define JB_VRSAVE 21 /* Shared dword with CR.  VRSAVE word at offset 168.  */
 # define JB_VRS    40 /* VRs 20 through 31 are saved, 12*4 words total.  */
 #else
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18 in total.  */
diff --git a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
index 46ea2b0..17bd0ca 100644
--- a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
@@ -111,44 +111,43 @@ ENTRY (__sigsetjmp)
 	stw	r0,((JB_VRSAVE)*4)(3)
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-#define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):
diff --git a/sysdeps/powerpc/powerpc64/__longjmp-common.S b/sysdeps/powerpc/powerpc64/__longjmp-common.S
index 70c3704..4f1e3c8 100644
--- a/sysdeps/powerpc/powerpc64/__longjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/__longjmp-common.S
@@ -57,7 +57,7 @@ ENTRY (__longjmp)
 	beq	L(no_vmx)
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
-	lwz	r0,((JB_VRSAVE)*8)(3)
+	lwz	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	mtspr	VRSAVE,r0
 	beq+	L(aligned_restore_vmx)
 	addi    r6,r5,16
@@ -153,7 +153,7 @@ L(no_vmx):
 	lfd fp21,((JB_FPRS+7)*8)(r3)
 	ld r22,((JB_GPRS+8)*8)(r3)
 	lfd fp22,((JB_FPRS+8)*8)(r3)
-	ld r0,(JB_CR*8)(r3)
+	lwz r0,((JB_CR*8)+4)(r3)	/* 32-bit CR.  */
 	ld r23,((JB_GPRS+9)*8)(r3)
 	lfd fp23,((JB_FPRS+9)*8)(r3)
 	ld r24,((JB_GPRS+10)*8)(r3)
diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S
index 58ec610..1829b9a 100644
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
@@ -95,7 +95,7 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	mfcr r0
 	std  r16,((JB_GPRS+2)*8)(3)
 	stfd fp16,((JB_FPRS+2)*8)(3)
-	std  r0,(JB_CR*8)(3)
+	stw  r0,((JB_CR*8)+4)(3)	/* 32-bit CR.  */
 	std  r17,((JB_GPRS+3)*8)(3)
 	stfd fp17,((JB_FPRS+3)*8)(3)
 	std  r18,((JB_GPRS+4)*8)(3)
@@ -139,50 +139,46 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
 	mfspr	r0,VRSAVE
-	stw	r0,((JB_VRSAVE)*8)(3)
+	stw	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes
-				 on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area
-	   below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-# define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area
-	   above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=860ec8e62a01a9c9e5087aa4cfd3b5e03fc7649b

commit 860ec8e62a01a9c9e5087aa4cfd3b5e03fc7649b
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Tue Oct 1 20:35:28 2013 +0530

    Fix PI mutex check in pthread_cond_broadcast and pthread_cond_signal
    
    Fixes BZ #15988.
    
    The check had a typo - it checked for PTHREAD_MUTEX_ROBUST_NP instead
    of PTHREAD_MUTEX_ROBUST_NORMAL_NP.  It has now been replaced by the
    already existing convenience macro USE_REQUEUE_PI.

diff --git a/NEWS b/NEWS
index 9d7ca62..8689dd0 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895.
+  15895, 15988.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index eae5079..26ee387 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,12 @@
+2013-10-01  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #15988]
+	* pthread_cond_broadcast.c (__pthread_cond_broadcast)
+	[lll_futex_cmp_requeue_pi && __ASSUME_REQUEUE_PI]: Use
+	USE_REQUEUE_PI.
+	* pthread_cond_signal.c (__pthread_cond_signal)
+	[lll_futex_cmd_requeue_pi && __ASSUME_REQUEUE_PI]: Likewise.
+
 2013-07-23  David S. Miller  <davem@davemloft.net>
 
 	* tst-cancel4.c (WRITE_BUFFER_SIZE): Adjust comment.
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
index 0702ec0..7ba9efa 100644
--- a/nptl/pthread_cond_broadcast.c
+++ b/nptl/pthread_cond_broadcast.c
@@ -63,10 +63,7 @@ __pthread_cond_broadcast (cond)
 
 #if (defined lll_futex_cmp_requeue_pi \
      && defined __ASSUME_REQUEUE_PI)
-      int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
-      pi_flag &= mut->__data.__kind;
-
-      if (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP)
+      if (USE_REQUEUE_PI (mut))
 	{
 	  if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
 					&mut->__data.__lock, futex_val,
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
index 102d0b3..ffc35dc 100644
--- a/nptl/pthread_cond_signal.c
+++ b/nptl/pthread_cond_signal.c
@@ -49,14 +49,9 @@ __pthread_cond_signal (cond)
 
 #if (defined lll_futex_cmp_requeue_pi \
      && defined __ASSUME_REQUEUE_PI)
-      int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
       pthread_mutex_t *mut = cond->__data.__mutex;
 
-      /* Do not use requeue for pshared condvars.  */
-      if (mut != (void *) ~0l)
-	pi_flag &= mut->__data.__kind;
-
-      if (__builtin_expect (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP, 0)
+      if (USE_REQUEUE_PI (mut)
 	/* This can only really fail with a ENOSYS, since nobody can modify
 	   futex while we have the cond_lock.  */
 	  && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3f71830d35d7bf4ac11664f0c48c3c68d250618b

commit 3f71830d35d7bf4ac11664f0c48c3c68d250618b
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:52:58 2013 +1000

    Fix memory leak in stdlib/isomac.c

diff --git a/ChangeLog b/ChangeLog
index 68909c8..b9239a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
+	[BZ #15893]
+	* stdlib/isomac.c (get_null_defines): Fix memory leak.
+
 	[BZ #15892]
 	* libio/memstream.c (open_memstream): Fix memory leak.
 	* libio/wmemstream.c (open_wmemstream): Likewise.
diff --git a/NEWS b/NEWS
index 90ff993..9d7ca62 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,8 @@ Version 2.18
   15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
+  15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdlib/isomac.c b/stdlib/isomac.c
index 2c9009b..621b515 100644
--- a/stdlib/isomac.c
+++ b/stdlib/isomac.c
@@ -263,6 +263,7 @@ get_null_defines (void)
   if (system (command))
     {
       puts ("system() returned nonzero");
+      free (command);
       return NULL;
     }
   free (command);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8e395175c4786ad9679851e3ed3c0c54a6f4e1f0

commit 8e395175c4786ad9679851e3ed3c0c54a6f4e1f0
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:50:41 2013 +1000

    Fix memory leaks in libio on allocation failure

diff --git a/ChangeLog b/ChangeLog
index 2f9dea5..68909c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-09-09  Allan McRae  <allan@archlinux.org>
+
+	[BZ #15892]
+	* libio/memstream.c (open_memstream): Fix memory leak.
+	* libio/wmemstream.c (open_wmemstream): Likewise.
+
+	[BZ #15895]
+	* nscd/netgroupcache.c: Fix nesting of ifdefs.
+
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
diff --git a/NEWS b/NEWS
index 6a62ddf..90ff993 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,7 @@ Version 2.18
   15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797.
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/libio/memstream.c b/libio/memstream.c
index 34534e2..3cb1bd7 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -84,7 +84,10 @@ open_memstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_init (&new_f->fp._sf._sbf._f, 0);
   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps;
   _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
diff --git a/libio/wmemstream.c b/libio/wmemstream.c
index 65738d4..fd7fe44 100644
--- a/libio/wmemstream.c
+++ b/libio/wmemstream.c
@@ -85,8 +85,10 @@ open_wmemstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
-
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps);
   _IO_fwide (&new_f->fp._sf._sbf._f, 1);
   _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b51679672648410c6627a4bd169e076c5b36f47b

commit b51679672648410c6627a4bd169e076c5b36f47b
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 5 09:32:56 2013 -0500

    PowerPC: fix POWER7 memrchr for some large inputs

diff --git a/ChangeLog b/ChangeLog
index f4bbcf1..2f9dea5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
+	memory access for final bytes in some large inputs.
+	* sysdeps/powerpc/powerpc64/power7/memrchr.S (__memrchr): Likewise.
+
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	* string/test-memrchr.c: New file.
 	* string/test-memrchr-ifunc.c: New file.
 	* string/Makefile: Add new memrchr testcase.
diff --git a/sysdeps/powerpc/powerpc32/power7/memrchr.S b/sysdeps/powerpc/powerpc32/power7/memrchr.S
index d1e3fda..defd832 100644
--- a/sysdeps/powerpc/powerpc32/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memrchr.S
@@ -101,8 +101,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
+	addi	r8,r8,4
+	cmplw	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 
diff --git a/sysdeps/powerpc/powerpc64/power7/memrchr.S b/sysdeps/powerpc/powerpc64/power7/memrchr.S
index d24fbbb..c499952 100644
--- a/sysdeps/powerpc/powerpc64/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memrchr.S
@@ -102,8 +102,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
+	addi	r8,r8,8
+	cmpld	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a4faadaff25e19abf295556a23b7b889b4bf6df4

commit a4faadaff25e19abf295556a23b7b889b4bf6df4
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Aug 29 15:28:00 2013 -0300

    Add memrchr testcase

diff --git a/ChangeLog b/ChangeLog
index ff223e7..f4bbcf1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
-<<<<<<< HEAD
-=======
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* string/test-memrchr.c: New file.
+	* string/test-memrchr-ifunc.c: New file.
+	* string/Makefile: Add new memrchr testcase.
+
 2013-09-03  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15427]
diff --git a/string/Makefile b/string/Makefile
index 0237edd..72d3e29 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -45,7 +45,7 @@ strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
 		   strlen strncmp strncpy strpbrk strrchr strspn memmem	\
 		   strstr strcasestr strnlen strcasecmp strncasecmp	\
-		   strncat rawmemchr strchrnul bcopy bzero
+		   strncat rawmemchr strchrnul bcopy bzero memrchr
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
diff --git a/string/test-memrchr-ifunc.c b/string/test-memrchr-ifunc.c
new file mode 100644
index 0000000..100dedb
--- /dev/null
+++ b/string/test-memrchr-ifunc.c
@@ -0,0 +1,20 @@
+/* Test and measure IFUNC implementations of memrchr function.
+   Copyright (C) 2013 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define TEST_IFUNC 1
+#include "test-memrchr.c"
diff --git a/string/test-memrchr.c b/string/test-memrchr.c
new file mode 100644
index 0000000..a4fe811
--- /dev/null
+++ b/string/test-memrchr.c
@@ -0,0 +1,169 @@
+/* Test and measure memrchr functions.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define TEST_MAIN
+#define TEST_NAME "memrchr"
+#include "test-string.h"
+
+typedef char *(*proto_t) (const char *, int, size_t);
+char *simple_memrchr (const char *, int, size_t);
+
+IMPL (simple_memrchr, 0)
+IMPL (memrchr, 1)
+
+char *
+simple_memrchr (const char *s, int c, size_t n)
+{
+  s = s + n;
+  while (n--)
+    if (*--s == (char) c)
+      return (char *) s;
+  return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res)
+{
+  char *res = CALL (impl, s, c, n);
+  if (res != exp_res)
+    {
+      error (0, 0, "Wrong result in function %s %p %p", impl->name,
+	     res, exp_res);
+      ret = 1;
+      return;
+    }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char)
+{
+  size_t i;
+  char *result;
+
+  align &= 7;
+  if (align + len >= page_size)
+    return;
+
+  for (i = 0; i < len; ++i)
+    {
+      buf1[align + i] = 1 + 23 * i % 127;
+      if (buf1[align + i] == seek_char)
+        buf1[align + i] = seek_char + 1;
+    }
+  buf1[align + len] = 0;
+
+  if (pos < len)
+    {
+      buf1[align + pos] = seek_char;
+      buf1[align + len] = -seek_char;
+      result = (char *) (buf1 + align + pos);
+    }
+  else
+    {
+      result = NULL;
+      buf1[align + len] = seek_char;
+    }
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, (char *) (buf1 + align), seek_char, len, result);
+}
+
+static void
+do_random_tests (void)
+{
+  size_t i, j, n, align, pos, len;
+  int seek_char;
+  char *result;
+  unsigned char *p = buf1 + page_size - 512;
+
+  for (n = 0; n < ITERATIONS; n++)
+    {
+      align = random () & 15;
+      pos = random () & 511;
+      if (pos + align >= 512)
+	pos = 511 - align - (random () & 7);
+      len = random () & 511;
+      if (pos >= len)
+	len = pos + (random () & 7);
+      if (len + align >= 512)
+        len = 512 - align - (random () & 7);
+      seek_char = random () & 255;
+      j = len + align + 64;
+      if (j > 512)
+        j = 512;
+
+      for (i = 0; i < j; i++)
+	{
+	  if (i == pos + align)
+	    p[i] = seek_char;
+	  else
+	    {
+	      p[i] = random () & 255;
+	      if (p[i] == seek_char)
+		p[i] = seek_char + 13;
+	    }
+	}
+
+      if (pos < len)
+	result = (char *) (p + pos + align);
+      else
+	result = NULL;
+
+      FOR_EACH_IMPL (impl, 1)
+	if (CALL (impl, (char *) (p + align), seek_char, len) != result)
+	  {
+	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+		   n, impl->name, align, seek_char, len, pos,
+		   CALL (impl, (char *) (p + align), seek_char, len),
+		   result, p);
+	    ret = 1;
+	  }
+    }
+}
+
+int
+test_main (void)
+{
+  size_t i;
+
+  test_init ();
+
+  printf ("%20s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 16 << i, 2048, 23);
+      do_test (i, 64, 256, 23);
+      do_test (0, 16 << i, 2048, 0);
+      do_test (i, 64, 256, 0);
+    }
+  for (i = 1; i < 32; ++i)
+    {
+      do_test (0, i, i + 1, 23);
+      do_test (0, i, i + 1, 0);
+    }
+
+  do_random_tests ();
+  return ret;
+}
+
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b502a3756d6979439130f1e46c2c27b62f493acd

commit b502a3756d6979439130f1e46c2c27b62f493acd
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Sep 3 15:32:54 2013 +0000

    Fix lgammaf spurious underflow (bug 15427).

diff --git a/ChangeLog b/ChangeLog
index a2e0a9f..ff223e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+<<<<<<< HEAD
+=======
+2013-09-03  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15427]
+	* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r): Use
+	2**-30 instead of 2**-70 as threshold for returning -log(|x|).
+	* math/libm-test.inc (lgamma_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
+2013-09-03   OndÅ?ej Bílka  <neleai@seznam.cz>
+
+	* sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: New file.
+	* sysdeps/x86_64/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
+	Add ifunc.
+	* sysdeps/x86_64/multiarch/Makefile (sysdep_routines):
+	Add strcmp-sse2-unaligned
+	* sysdeps/x86_64/multiarch/strcmp.S (strcmp): Add ifunc.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* Versions.def (libc): Add GLIBC_2.19.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
+	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+
+>>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index 751b9aa..6a62ddf 100644
--- a/NEWS
+++ b/NEWS
@@ -4,21 +4,6 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
-<<<<<<< HEAD
-=======
-
-Version 2.19
-
-* The following bugs are resolved with this release:
-
-<<<<<<< HEAD
-  14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
-  15905.
->>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
-=======
-  14155, 14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890,
-  15897, 15905, 15909.
->>>>>>> b7835e3... Fix spurious jnf underflows (bug 14155).
 
 Version 2.18
 
@@ -34,10 +19,10 @@ Version 2.18
   15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
   15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
   15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
-  15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465,
-  15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529,
-  15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655,
-  15666, 15667, 15674, 15711, 15755, 15759, 15797.
+  15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
+  15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
+  15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 9d49255..7a11c90 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9973,6 +9973,61 @@ static const struct test_f_f1_data lgamma_test_data[] =
     TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1),
     TEST_f_f1 (lgamma, 0.7L, 0.260867246531666514385732417016759578L, 1),
     TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197028392998854470e-1L, 1),
+
+    TEST_f_f1 (lgamma, 0x1p-5L, 3.4484891277979584796832693452686366085801e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5L, 3.4845895751341394376217526729956836492792e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10L, 6.9309089024194618895406190646600805357273e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10L, 6.9320362775113082175565786721095494761582e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-15L, 1.0397190093941001762077888432721419773538e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-15L, 1.0397225324389321751118257981741350715545e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-20L, 1.3862943060723899573457963336920089012399e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-20L, 1.3862944161675408862049886226750366625112e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-25L, 1.7328679496796266133304874243201700664713e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-25L, 1.7328679531201000798551671833865469674673e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-30L, 2.0794415416260785304085859198055798098863e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-30L, 2.0794415417335933262374820960532606449975e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-40L, 2.7725887222397287402100277256545578941303e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-40L, 2.7725887222398337351278293820766115529596e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-50L, 3.4657359027997264958191108994508978906983e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-50L, 3.4657359027997265983532103151309975524744e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-60L, 4.1588830833596718564533272505187468598519e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-60L, 4.1588830833596718565534582069793719571779e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-64L, 4.4361419555836499802671564849429355013920e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-64L, 4.4361419555836499802734146697217245699749e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-70L, 4.8520302639196171659205759581386516869302e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-70L, 4.8520302639196171659206737422758202661268e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-100L, 6.9314718055994530941723212145817201464678e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-100L, 6.9314718055994530941723212145818112150422e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-126L, 8.7336544750553108986571247303730247577506e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-126L, 8.7336544750553108986571247303730247577520e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, -1),
+#ifndef TEST_FLOAT
+    TEST_f_f1 (lgamma, 0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, -1),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381
+    TEST_f_f1 (lgamma, 0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, -1),
+# if LDBL_MANT_DIG >= 113
+    TEST_f_f1 (lgamma, 0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, -1),
+# endif
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 8244863..4759aa9 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5470,9 +5470,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 float: 1
 ifloat: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -5723,9 +5749,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 float: 1
 ifloat: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2
diff --git a/sysdeps/ieee754/flt-32/e_lgammaf_r.c b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
index 2e92269..0dba9af 100644
--- a/sysdeps/ieee754/flt-32/e_lgammaf_r.c
+++ b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
@@ -150,8 +150,8 @@ __ieee754_lgammaf_r(float x, int *signgamp)
 	      *signgamp = -1;
 	    return one/fabsf(x);
 	  }
-	if(__builtin_expect(ix<0x1c800000, 0)) {
-	    /* |x|<2**-70, return -log(|x|) */
+	if(__builtin_expect(ix<0x30800000, 0)) {
+	    /* |x|<2**-30, return -log(|x|) */
 	    if(hx<0) {
 		*signgamp = -1;
 		return -__ieee754_logf(-x);
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 477eedc..6fbfa64 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6222,11 +6222,39 @@ idouble: 1
 Test "gamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "gamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "gamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -6491,11 +6519,39 @@ ldouble: 2
 Test "lgamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "lgamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "lgamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b3c7503940022f70ec8272c2c0d0a0e4489ae992

commit b3c7503940022f70ec8272c2c0d0a0e4489ae992
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Sep 2 14:51:24 2013 +0000

    Fix spurious jnf underflows (bug 14155).

diff --git a/ChangeLog b/ChangeLog
index 13486b0..a2e0a9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-02  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #14155]
+	* sysdeps/ieee754/flt-32/e_jnf.c (__ieee754_jnf): Use double for
+	intermediate calculations in recurrence.
+	(__ieee754_ynf): Likewise.
+	* math/libm-test.inc (jn_test_data): Do not allow spurious
+	underflow exception.  Add more tests.
+	(yn_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
 2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
 
 	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
diff --git a/NEWS b/NEWS
index 18cf053..751b9aa 100644
--- a/NEWS
+++ b/NEWS
@@ -11,9 +11,14 @@ Version 2.19
 
 * The following bugs are resolved with this release:
 
+<<<<<<< HEAD
   14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
   15905.
 >>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
+=======
+  14155, 14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890,
+  15897, 15905, 15909.
+>>>>>>> b7835e3... Fix spurious jnf underflows (bug 14155).
 
 Version 2.18
 
@@ -21,18 +26,18 @@ Version 2.18
 
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
-  14142, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496,
-  14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909, 14920,
-  14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
-  15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
-  15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
-  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15331,
-  15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
-  15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
-  15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529, 15532,
-  15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666,
-  15667, 15674, 15711, 15755, 15759, 15797.
+  14142, 14155, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478,
+  14496, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909,
+  14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000,
+  15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055,
+  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
+  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
+  15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
+  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
+  15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465,
+  15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529,
+  15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655,
+  15666, 15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 7408c6b..9d49255 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9908,8 +9908,14 @@ static const struct test_if_f_data jn_test_data[] =
     TEST_if_f (jn, 8, 2.4048255576957729L, 0.92165786705344923232879022467054148E-4L),
     TEST_if_f (jn, 9, 2.4048255576957729L, 0.12517270977961513005428966643852564E-4L),
 
-    /* Bug 14155: spurious exception may occur.  */
-    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L, UNDERFLOW_EXCEPTION_OK),
+    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L),
+    TEST_if_f (jn, 2, 0x1p127L, -6.0784021821505059176832624052765568656702e-20L),
+#ifndef TEST_FLOAT
+    TEST_if_f (jn, 2, 0x1p1023L, 1.5665258060609012834424478437196679802783e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (jn, 2, 0x1p16383L, -9.5859502826270374691362975419147645151233e-2467L),
+#endif
   };
 
 static void
@@ -14526,6 +14532,15 @@ static const struct test_if_f_data yn_test_data[] =
     /* Check whether yn returns correct value for LDBL_MIN, DBL_MIN,
        and FLT_MIN.  See Bug 14173.  */
     TEST_if_f (yn, 10, min_value, minus_infty, OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_if_f (yn, 2, 0x1.ffff62p+99L, -5.5244413477397111790415387179517953221757e-16L),
+    TEST_if_f (yn, 2, 0x1p127L, 6.8569250690166637098111268958532649249771e-21L),
+#ifndef TEST_FLOAT
+    TEST_if_f (yn, 2, 0x1p1023L, -8.2687542933709649327986678723012001545638e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (yn, 2, 0x1p16383L, 3.8895531955766020648617743624167352352217e-2467L),
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 530dbd7..8244863 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5635,9 +5635,9 @@ ildouble: 1
 ldouble: 1
 Test "jn (10, 10.0)":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 ildouble: 2
 ldouble: 2
 Test "jn (10, 2.0)":
@@ -5648,6 +5648,14 @@ float: 1
 ifloat: 1
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p1023)":
+double: 1
+idouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 1
 float: 1
@@ -6844,6 +6852,14 @@ ifloat: 1
 Test "yn (10, 2.0)":
 float: 3
 ifloat: 3
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+float: 2
+ifloat: 2
 Test "yn (3, 0.125)":
 ildouble: 1
 ldouble: 1
diff --git a/sysdeps/ieee754/flt-32/e_jnf.c b/sysdeps/ieee754/flt-32/e_jnf.c
index ad26d7e..5984d94 100644
--- a/sysdeps/ieee754/flt-32/e_jnf.c
+++ b/sysdeps/ieee754/flt-32/e_jnf.c
@@ -54,7 +54,7 @@ __ieee754_jnf(int n, float x)
 	    b = __ieee754_j1f(x);
 	    for(i=1;i<n;i++){
 		temp = b;
-		b = b*((float)(i+i)/x) - a; /* avoid underflow */
+		b = b*((double)(i+i)/x) - a; /* avoid underflow */
 		a = temp;
 	    }
 	} else {
@@ -196,7 +196,7 @@ __ieee754_ynf(int n, float x)
 	GET_FLOAT_WORD(ib,b);
 	for(i=1;i<n&&ib!=0xff800000;i++){
 	    temp = b;
-	    b = ((float)(i+i)/x)*b - a;
+	    b = ((double)(i+i)/x)*b - a;
 	    GET_FLOAT_WORD(ib,b);
 	    a = temp;
 	}
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index d02618a..477eedc 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6403,6 +6403,11 @@ idouble: 2
 ifloat: 2
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 2
 float: 1
@@ -7728,6 +7733,16 @@ double: 3
 float: 1
 idouble: 3
 ifloat: 1
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
 Test "yn (3, 0.125)":
 double: 1
 idouble: 1
@@ -8428,9 +8443,9 @@ ldouble: 2
 
 Function: "yn":
 double: 3
-float: 2
+float: 3
 idouble: 3
-ifloat: 2
+ifloat: 3
 ildouble: 4
 ldouble: 4
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e53103749c19199b0ec23e8a5b330dd2e288f5ac

commit e53103749c19199b0ec23e8a5b330dd2e288f5ac
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Thu May 23 18:00:10 2013 +0200

    [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases

diff --git a/ChangeLog b/ChangeLog
index 1ffcad4..13486b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
+
+	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
+
+	* stdlib/strtof_l.c (SET_MANTISSA): Rewrite.
+	* stdlib/strtod_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-64-128/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-96/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
+	(ibm_extended_long_double): Add ieee_nan member.
+	* stdlib/tst-strtod6.c (test): New function, renamed from do_test.
+	(do_test): New function.
+
+	* math/basic-test.c (TEST_CONVERT): New macro, renamed from
+	TEST_TRUNC.
+	(convert_dfsf_test, convert_tfsf_test, convert_tfdf_test): New
+	functions, renamed from truncdfsf_test, trunctfsf_test,
+	trunctfdf_test.
+	(convert_sfdf_test, convert_sftf_test, convert_dftf_test): New
+	functions.
+	(do_test): Run all these.
+
 2013-08-23  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15532]
diff --git a/NEWS b/NEWS
index c83a14e..18cf053 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,16 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
+<<<<<<< HEAD
+=======
+
+Version 2.19
+
+* The following bugs are resolved with this release:
+
+  14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
+  15905.
+>>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
 
 Version 2.18
 
@@ -20,9 +30,9 @@ Version 2.18
   15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
   15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15532, 15536,
-  15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667,
-  15674, 15711, 15755, 15759, 15797.
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529, 15532,
+  15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666,
+  15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 5b41e2b..8f60653 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -42,11 +42,10 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # define SET_MANTISSA(flt, mant) \
   do { union ieee754_double u;						      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 #endif
 /* End of configuration part.  */
diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c
index 6fb44bd..c4c1c1f 100644
--- a/stdlib/strtof_l.c
+++ b/stdlib/strtof_l.c
@@ -37,10 +37,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 #define SET_MANTISSA(flt, mant) \
   do { union ieee754_float u;						      \
        u.f = (flt);							      \
-       if ((mant & 0x7fffff) == 0)					      \
-	 mant = 0x400000;						      \
-       u.ieee.mantissa = (mant) & 0x7fffff;				      \
-       (flt) = u.f;							      \
+       u.ieee_nan.mantissa = (mant);					      \
+       if (u.ieee.mantissa != 0)					      \
+	 (flt) = u.f;							      \
   } while (0)
 
 #include "strtod_l.c"
diff --git a/stdlib/tst-strtod6.c b/stdlib/tst-strtod6.c
index 1d87266..15e79fd 100644
--- a/stdlib/tst-strtod6.c
+++ b/stdlib/tst-strtod6.c
@@ -4,12 +4,13 @@
 #include <string.h>
 
 static int
-do_test (void)
+test (const char str[])
 {
-  static const char str[] = "NaN(blabla)something";
   char *endp;
   int result = 0;
 
+  puts (str);
+
   double d = strtod (str, &endp);
   if (!isnan (d))
     {
@@ -64,5 +65,24 @@ do_test (void)
   return result;
 }
 
+static int
+do_test (void)
+{
+  int result = 0;
+
+  result |= test ("NaN(blabla)something");
+  result |= test ("NaN(1234)something");
+  /* UINT32_MAX.  */
+  result |= test ("NaN(4294967295)something");
+  /* UINT64_MAX.  */
+  result |= test ("NaN(18446744073709551615)something");
+  /* The case of zero is special in that "something" has to be done to make the
+     mantissa different from zero, which would mean infinity instead of
+     NaN.  */
+  result |= test ("NaN(0)something");
+
+  return result;
+}
+
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c
index 8e0bc03..d3a1d1e 100644
--- a/sysdeps/ieee754/ldbl-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128/strtold_l.c
@@ -34,11 +34,13 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
index e5644f5..9e94f53 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h
+++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
@@ -199,6 +199,25 @@ union ibm_extended_long_double
 	unsigned int mantissa2:20;
 	unsigned int mantissa3:32;
       } ieee;
+
+    /* This format makes it easier to see if a NaN is a signalling NaN.  */
+    struct
+      { /* Big endian.  There is no other.  */
+
+	unsigned int negative:1;
+	unsigned int exponent:11;
+	unsigned int quiet_nan:1;
+	/* Together Mantissa0-3 comprise the mantissa.  */
+	unsigned int mantissa0:19;
+	unsigned int mantissa1:32;
+
+	unsigned int negative2:1;
+	unsigned int exponent2:11;
+	/* There is an implied 1 here?  */
+	/* Together these comprise the mantissa.  */
+	unsigned int mantissa2:20;
+	unsigned int mantissa3:32;
+      } ieee_nan;
    };
 
 #define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
index 93415f0..04e3288 100644
--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
@@ -44,11 +44,10 @@ libc_hidden_proto (STRTOF)
 # define SET_MANTISSA(flt, mant) \
   do { union ibm_extended_long_double u;				      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
index 8182b2b..e9b33f2 100644
--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
@@ -44,11 +44,13 @@ libc_hidden_proto (STRTOF)
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c
index ded84f3..dccf98c 100644
--- a/sysdeps/ieee754/ldbl-96/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-96/strtold_l.c
@@ -34,11 +34,10 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       if ((mant & 0x7fffffffffffffffULL) == 0)				      \
-	 mant = 0x4000000000000000ULL;					      \
-       u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000;	      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <stdlib/strtod_l.c>

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=85ce5db8d835281c8beff6e750c02c799dee3f6f

commit 85ce5db8d835281c8beff6e750c02c799dee3f6f
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Fri Aug 23 19:45:38 2013 +0000

    Fix cexp (NaN + i0) (bug 15532).

diff --git a/ChangeLog b/ChangeLog
index 7b4d6e9..1ffcad4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-23  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15532]
+	* math/s_cexp.c (__cexp): Return NaN + i0 for NaN + i0 argument.
+	* math/s_cexpf.c (__cexpf): Likewise.
+	* math/s_cexpl.c (__cexpl): Likewise.
+	* math/libm-test.inc (cexp_test_data): Correct expected return
+	value for NaN + i0.  Add another test.
+
 2013-08-21  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15797]
diff --git a/NEWS b/NEWS
index 0d0a315..c83a14e 100644
--- a/NEWS
+++ b/NEWS
@@ -20,9 +20,9 @@ Version 2.18
   15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
   15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
-  15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
-  15711, 15755, 15759, 15797.
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15532, 15536,
+  15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667,
+  15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 8c1dcac..7408c6b 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -6193,7 +6193,8 @@ static const struct test_c_c_data cexp_test_data[] =
 
     TEST_c_c (cexp, plus_infty, qnan_value, plus_infty, qnan_value),
 
-    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
+    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, 0.0),
+    TEST_c_c (cexp, qnan_value, minus_zero, qnan_value, minus_zero),
     TEST_c_c (cexp, qnan_value, 1.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
 
     TEST_c_c (cexp, qnan_value, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
diff --git a/math/s_cexp.c b/math/s_cexp.c
index 655e4e8..40e0e51 100644
--- a/math/s_cexp.c
+++ b/math/s_cexp.c
@@ -145,12 +145,18 @@ __cexp (__complex__ double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nan ("");
-      __imag__ retval = __nan ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nan ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpf.c b/math/s_cexpf.c
index fa942d3..7c42205 100644
--- a/math/s_cexpf.c
+++ b/math/s_cexpf.c
@@ -145,12 +145,18 @@ __cexpf (__complex__ float x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanf ("");
-      __imag__ retval = __nanf ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanf ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpl.c b/math/s_cexpl.c
index d827bc3..0c35603 100644
--- a/math/s_cexpl.c
+++ b/math/s_cexpl.c
@@ -145,12 +145,18 @@ __cexpl (__complex__ long double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanl ("");
-      __imag__ retval = __nanl ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanl ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c3a4bddd656561cfffba2605e148e65d4ff07e21

commit c3a4bddd656561cfffba2605e148e65d4ff07e21
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Aug 21 19:56:48 2013 +0000

    Fix fdim handling of infinities (bug 15797).

diff --git a/ChangeLog b/ChangeLog
index 16e258c..7b4d6e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-08-21  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15797]
+	* math/s_fdim.c (__fdim): Check for infinite arguments if result
+	is infinite, not alongside NaN test.
+	* math/s_fdimf.c (__fdimf): Likewise.
+	* math/s_fdiml.c (__fdiml): Likewise.
+	* math/libm-test.inc (fdim_test_data): Add more tests.  Test that
+	errno is unchanged.
+
 2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	[BZ #15867]
diff --git a/NEWS b/NEWS
index ab3f353..0d0a315 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,7 @@ Version 2.18
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
   15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
   15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
-  15711, 15755, 15759.
+  15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3b382af..8c1dcac 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -8139,33 +8139,37 @@ fabs_test (void)
 
 static const struct test_ff_f_data fdim_test_data[] =
   {
-    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
diff --git a/math/s_fdim.c b/math/s_fdim.c
index 2f97948..f8fd804 100644
--- a/math/s_fdim.c
+++ b/math/s_fdim.c
@@ -26,16 +26,16 @@ __fdim (double x, double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0;
 
   double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdimf.c b/math/s_fdimf.c
index 03810b5..86efe6e 100644
--- a/math/s_fdimf.c
+++ b/math/s_fdimf.c
@@ -26,16 +26,16 @@ __fdimf (float x, float y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   float r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdiml.c b/math/s_fdiml.c
index 5604532..030fcc2 100644
--- a/math/s_fdiml.c
+++ b/math/s_fdiml.c
@@ -26,16 +26,16 @@ __fdiml (long double x, long double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   long double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1778fd0a17a74422a58d8eada3fa08b80f0a0c27

commit 1778fd0a17a74422a58d8eada3fa08b80f0a0c27
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Aug 20 15:01:59 2013 -0500

    PowerPC: fix backtrace to handle signal trampolines
    
    This patch fixes backtrace for PPC32 and PPC64 to correctly handle
    signal trampolines. The 'debug/tst-backtrace6.c' also check for
    SA_SIGINFO handling, where is triggers another vDSO symbols for PPC32.

diff --git a/ChangeLog b/ChangeLog
index bf25bd6..16e258c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #15867]
+	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
+	trampoline stack frame information.
+	* sysdeps/powerpc/powerpc64/backtrace.c (__backtrace): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+	(__vdso_sigtramp_rt64): New variable: PPC64 signal trampoline.
+	(__vdso_sigtramp32): New variable: PPC32 signal trampoline.
+	(__vdso_sigtramp_rt32): New variable: PPC32 signal trampoline.
+	* sysdeps/unix/sysv/linux/powerpc/init-first.c
+	(_libc_vdso_platform_setup): Initialize the signal trampolines.
+	* debug/tst-backtrace5.c (fn): Add an option set modify sigaction
+	sa_flags value.
+	* debug/tst-backtrace6.c: New file: check backtrace for signal frames,
+	interrupting a syscall and set with option SA_SIGINFO.
+
 2013-08-20  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15531]

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8df86a8394d0ea121f2066efe618f2b1cc799be3

commit 8df86a8394d0ea121f2066efe618f2b1cc799be3
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Aug 20 19:41:15 2013 +0000

    Fix cproj handling of (finite, NaN) arguments (bug 15531).
    
    backport of c980f2f4fe0f5d301f706017a1f7e4e942193ec0

diff --git a/ChangeLog b/ChangeLog
index 9ad0719..bf25bd6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-08-20  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15531]
+	* math/s_cproj.c (__cproj): Only return an infinity if one part of
+	argument is infinite.
+	* math/s_cprojf.c (__cprojf): Likewise.
+	* math/s_cprojl.c (__cprojl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_cprojl.c (__cprojl): Likewise.
+	* math/libm-test.inc (cproj_test_data): Add more tests.
+
+	* sysdeps/unix/sysv/linux/mmap64.c: Include <string.h>.
+
+	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64)
+	[MMAP2_PAGE_SHIFT == -1]: Use __getpagesize to determine page
+	size.  Use __ffs to determine corresponding shift.
+
 2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
 	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
diff --git a/NEWS b/NEWS
index 4d168c5..ab3f353 100644
--- a/NEWS
+++ b/NEWS
@@ -16,13 +16,13 @@ Version 2.18
   14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
   15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
   15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
-  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335,
-  15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381,
-  15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424,
-  15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485,
-  15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577,
-  15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711,
-  15755, 15759.
+  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15331,
+  15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
+  15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
+  15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
+  15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
+  15711, 15755, 15759.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 2324d4f..3b382af 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -7061,11 +7061,51 @@ static const struct test_c_c_data cproj_test_data[] =
 
     TEST_c_c (cproj, qnan_value, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_zero, qnan_value, plus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, plus_zero, qnan_value, plus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_zero, qnan_value, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, qnan_value, 1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, qnan_value, -1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, 1.0, qnan_value, 1.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, -1.0, qnan_value, -1.0, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, 1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, 2.0, 3.0, 2.0, 3.0, NO_INEXACT_EXCEPTION),
   };
diff --git a/math/s_cproj.c b/math/s_cproj.c
index c0be461..98f1a4c 100644
--- a/math/s_cproj.c
+++ b/math/s_cproj.c
@@ -24,9 +24,7 @@
 __complex__ double
 __cproj (__complex__ double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_ns (__real__ x) || __isinf_ns (__imag__ x))
     {
       __complex__ double res;
 
diff --git a/math/s_cprojf.c b/math/s_cprojf.c
index 188bbe3..e4dbc18 100644
--- a/math/s_cprojf.c
+++ b/math/s_cprojf.c
@@ -24,9 +24,7 @@
 __complex__ float
 __cprojf (__complex__ float x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsf (__real__ x) || __isinf_nsf (__imag__ x))
     {
       __complex__ float res;
 
diff --git a/math/s_cprojl.c b/math/s_cprojl.c
index fbdf279..b564a83 100644
--- a/math/s_cprojl.c
+++ b/math/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
index 3b4af54..a344e92 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f8a004f1fa412e3aae77faa30b4dfb654d721510

commit f8a004f1fa412e3aae77faa30b4dfb654d721510
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
Date:   Thu Oct 31 09:57:33 2013 -0500

    * elf/setup-vdso.h (setup_vdso): Fix missing string termination.
    
    backport of f315524e034cfc644157cb4af5ecc99f645dd067

diff --git a/ChangeLog b/ChangeLog
index 3a6ce47..9ad0719 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
+
 2013-08-16  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #14699]
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index a98dfec..056d885 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -89,7 +89,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
 	     addresses in the vsyscall DSO pages in writev() calls.  */
 	  const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
 				 + l->l_info[DT_SONAME]->d_un.d_val);
-	  size_t len = strlen (dsoname);
+	  size_t len = strlen (dsoname) + 1;
 	  char *copy = malloc (len);
 	  if (copy == NULL)
 	    _dl_fatal_printf ("out of memory\n");

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f166b9c6e90d631115c59b4357357bc168d8e51a

commit f166b9c6e90d631115c59b4357357bc168d8e51a
Author: Florian Weimer <fweimer@redhat.com>
Date:   Thu Oct 31 09:55:52 2013 -0500

    CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
    
    * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
    member.
    * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
    member.
    * sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
    * sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
    Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
    conditional.
    * sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
    GETDENTS_64BIT_ALIGNED.
    * sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
    * manual/filesys.texi (Reading/Closing Directory): Document
    ENAMETOOLONG return value of readdir_r.  Recommend readdir more
    strongly.
    * manual/conf.texi (Limits for Files): Add portability note to
    NAME_MAX, PATH_MAX.
    (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
    
    backport of 91ce40854d0b7f865cf5024ef95a8026b76096f3

diff --git a/ChangeLog b/ChangeLog
index 3ef8981..3a6ce47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2013-08-16  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #14699]
+	CVE-2013-4237
+	* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
+	member.
+	* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
+	member.
+	* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
+	* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
+	Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
+	conditional.
+	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
+	GETDENTS_64BIT_ALIGNED.
+	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
+	* manual/filesys.texi (Reading/Closing Directory): Document
+	ENAMETOOLONG return value of readdir_r.  Recommend readdir more
+	strongly.
+	* manual/conf.texi (Limits for Files): Add portability note to
+	NAME_MAX, PATH_MAX.
+	(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
+
 2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
diff --git a/NEWS b/NEWS
index b023c30..4d168c5 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,7 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
-
+
 Version 2.18
 
 * The following bugs are resolved with this release:
@@ -12,17 +12,17 @@ Version 2.18
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
   14142, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496,
-  14582, 14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952,
-  14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006,
-  15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062, 15078,
-  15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283,
-  15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336,
-  15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394,
-  15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426,
-  15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488,
-  15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583,
-  15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711, 15755,
-  15759.
+  14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909, 14920,
+  14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
+  15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
+  15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
+  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335,
+  15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381,
+  15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424,
+  15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485,
+  15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577,
+  15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711,
+  15755, 15759.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -37,6 +37,10 @@ Version 2.18
 * CVE-2013-1914 Stack overflow in getaddrinfo with many results has been
   fixed (Bugzilla #15330).
 
+* CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
+  to the d_name member of struct dirent, or omit the terminating NUL
+  character.  (Bugzilla #14699).
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/manual/conf.texi b/manual/conf.texi
index 7eb8b36..c720063 100644
--- a/manual/conf.texi
+++ b/manual/conf.texi
@@ -1149,6 +1149,9 @@ typed ahead as input.  @xref{I/O Queues}.
 @deftypevr Macro int NAME_MAX
 The uniform system limit (if any) for the length of a file name component, not
 including the terminating null character.
+
+@strong{Portability Note:} On some systems, @theglibc{} defines
+@code{NAME_MAX}, but does not actually enforce this limit.
 @end deftypevr
 
 @comment limits.h
@@ -1157,6 +1160,9 @@ including the terminating null character.
 The uniform system limit (if any) for the length of an entire file name (that
 is, the argument given to system calls such as @code{open}), including the
 terminating null character.
+
+@strong{Portability Note:} @Theglibc{} does not enforce this limit
+even if @code{PATH_MAX} is defined.
 @end deftypevr
 
 @cindex limits, pipe buffer size
@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
 @end table
 
+@strong{Portability Note:} On some systems, @theglibc{} does not
+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
+
 @node Utility Limits
 @section Utility Program Capacity Limits
 
diff --git a/manual/filesys.texi b/manual/filesys.texi
index 1df9cf2..814c210 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
 @comment POSIX.1
 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
 This function reads the next entry from the directory.  It normally
-returns a pointer to a structure containing information about the file.
-This structure is statically allocated and can be rewritten by a
-subsequent call.
+returns a pointer to a structure containing information about the
+file.  This structure is associated with the @var{dirstream} handle
+and can be rewritten by a subsequent call.
 
 @strong{Portability Note:} On some systems @code{readdir} may not
 return entries for @file{.} and @file{..}, even though these are always
@@ -461,19 +461,61 @@ conditions are defined for this function:
 The @var{dirstream} argument is not valid.
 @end table
 
-@code{readdir} is not thread safe.  Multiple threads using
-@code{readdir} on the same @var{dirstream} may overwrite the return
-value.  Use @code{readdir_r} when this is critical.
+To distinguish between an end-of-directory condition or an error, you
+must set @code{errno} to zero before calling @code{readdir}.  To avoid
+entering an infinite loop, you should stop reading from the directory
+after the first error.
+
+In POSIX.1-2008, @code{readdir} is not thread-safe.  In @theglibc{}
+implementation, it is safe to call @code{readdir} concurrently on
+different @var{dirstream}s, but multiple threads accessing the same
+@var{dirstream} result in undefined behavior.  @code{readdir_r} is a
+fully thread-safe alternative, but suffers from poor portability (see
+below).  It is recommended that you use @code{readdir}, with external
+locking if multiple threads access the same @var{dirstream}.
 @end deftypefun
 
 @comment dirent.h
 @comment GNU
 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
-This function is the reentrant version of @code{readdir}.  Like
-@code{readdir} it returns the next entry from the directory.  But to
-prevent conflicts between simultaneously running threads the result is
-not stored in statically allocated memory.  Instead the argument
-@var{entry} points to a place to store the result.
+This function is a version of @code{readdir} which performs internal
+locking.  Like @code{readdir} it returns the next entry from the
+directory.  To prevent conflicts between simultaneously running
+threads the result is stored inside the @var{entry} object.
+
+@strong{Portability Note:} It is recommended to use @code{readdir}
+instead of @code{readdir_r} for the following reasons:
+
+@itemize @bullet
+@item
+On systems which do not define @code{NAME_MAX}, it may not be possible
+to use @code{readdir_r} safely because the caller does not specify the
+length of the buffer for the directory entry.
+
+@item
+On some systems, @code{readdir_r} cannot read directory entries with
+very long names.  If such a name is encountered, @theglibc{}
+implementation of @code{readdir_r} returns with an error code of
+@code{ENAMETOOLONG} after the final directory entry has been read.  On
+other systems, @code{readdir_r} may return successfully, but the
+@code{d_name} member may not be NUL-terminated or may be truncated.
+
+@item
+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
+even when access to the same @var{dirstream} is serialized.  But in
+current implementations (including @theglibc{}), it is safe to call
+@code{readdir} concurrently on different @var{dirstream}s, so there is
+no need to use @code{readdir_r} in most multi-threaded programs.  In
+the rare case that multiple threads need to read from the same
+@var{dirstream}, it is still better to use @code{readdir} and external
+synchronization.
+
+@item
+It is expected that future versions of POSIX will obsolete
+@code{readdir_r} and mandate the level of thread safety for
+@code{readdir} which is provided by @theglibc{} and other
+implementations today.
+@end itemize
 
 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
 to @var{entry}.  If there are no more entries in the directory or an
@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
 null pointer and returns a nonzero error code, also stored in
 @code{errno}, as described for @code{readdir}.
 
-@strong{Portability Note:} On some systems @code{readdir_r} may not
-return a NUL terminated string for the file name, even when there is no
-@code{d_reclen} field in @code{struct dirent} and the file
-name is the maximum allowed size.  Modern systems all have the
-@code{d_reclen} field, and on old systems multi-threading is not
-critical.  In any case there is no such problem with the @code{readdir}
-function, so that even on systems without the @code{d_reclen} member one
-could use multiple threads by using external locking.
-
 It is also important to look at the definition of the @code{struct
 dirent} type.  Simply passing a pointer to an object of this type for
 the second parameter of @code{readdir_r} might not be enough.  Some
diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h
index a7a074d..8e8570d 100644
--- a/sysdeps/posix/dirstream.h
+++ b/sysdeps/posix/dirstream.h
@@ -39,6 +39,8 @@ struct __dirstream
 
     off_t filepos;		/* Position of next entry to read.  */
 
+    int errcode;		/* Delayed error code.  */
+
     /* Directory block.  */
     char data[0] __attribute__ ((aligned (__alignof__ (void*))));
   };
diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index ddfc3a7..fc05b0f 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
   dirp->size = 0;
   dirp->offset = 0;
   dirp->filepos = 0;
+  dirp->errcode = 0;
 
   return dirp;
 }
diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
index b5a8e2e..8ed5c3f 100644
--- a/sysdeps/posix/readdir_r.c
+++ b/sysdeps/posix/readdir_r.c
@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
   DIRENT_TYPE *dp;
   size_t reclen;
   const int saved_errno = errno;
+  int ret;
 
   __libc_lock_lock (dirp->lock);
 
@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
 		  bytes = 0;
 		  __set_errno (saved_errno);
 		}
+	      if (bytes < 0)
+		dirp->errcode = errno;
 
 	      dp = NULL;
-	      /* Reclen != 0 signals that an error occurred.  */
-	      reclen = bytes != 0;
 	      break;
 	    }
 	  dirp->size = (size_t) bytes;
@@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
       dirp->filepos += reclen;
 #endif
 
-      /* Skip deleted files.  */
+#ifdef NAME_MAX
+      if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
+	{
+	  /* The record is very long.  It could still fit into the
+	     caller-supplied buffer if we can skip padding at the
+	     end.  */
+	  size_t namelen = _D_EXACT_NAMLEN (dp);
+	  if (namelen <= NAME_MAX)
+	    reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
+	  else
+	    {
+	      /* The name is too long.  Ignore this file.  */
+	      dirp->errcode = ENAMETOOLONG;
+	      dp->d_ino = 0;
+	      continue;
+	    }
+	}
+#endif
+
+      /* Skip deleted and ignored files.  */
     }
   while (dp->d_ino == 0);
 
   if (dp != NULL)
     {
-#ifdef GETDENTS_64BIT_ALIGNED
-      /* The d_reclen value might include padding which is not part of
-	 the DIRENT_TYPE data structure.  */
-      reclen = MIN (reclen,
-		    offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name));
-#endif
       *result = memcpy (entry, dp, reclen);
-#ifdef GETDENTS_64BIT_ALIGNED
+#ifdef _DIRENT_HAVE_D_RECLEN
       entry->d_reclen = reclen;
 #endif
+      ret = 0;
     }
   else
-    *result = NULL;
+    {
+      *result = NULL;
+      ret = dirp->errcode;
+    }
 
   __libc_lock_unlock (dirp->lock);
 
-  return dp != NULL ? 0 : reclen ? errno : 0;
+  return ret;
 }
 
 #ifdef __READDIR_R_ALIAS
diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c
index 2935a8e..d4991ad 100644
--- a/sysdeps/posix/rewinddir.c
+++ b/sysdeps/posix/rewinddir.c
@@ -33,6 +33,7 @@ rewinddir (dirp)
   dirp->filepos = 0;
   dirp->offset = 0;
   dirp->size = 0;
+  dirp->errcode = 0;
 #ifndef NOT_IN_libc
   __libc_lock_unlock (dirp->lock);
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
index 8ebbcfd..a7d114e 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
@@ -18,7 +18,6 @@
 #define __READDIR_R __readdir64_r
 #define __GETDENTS __getdents64
 #define DIRENT_TYPE struct dirent64
-#define GETDENTS_64BIT_ALIGNED 1
 
 #include <sysdeps/posix/readdir_r.c>
 
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
index 5ed8e95..290f2c8 100644
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
+++ b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
@@ -1,5 +1,4 @@
 #define readdir64_r __no_readdir64_r_decl
-#define GETDENTS_64BIT_ALIGNED 1
 #include <sysdeps/posix/readdir_r.c>
 #undef readdir64_r
 weak_alias (__readdir_r, readdir64_r)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                       |  204 +++++
 NEWS                                            |   57 ++-
 csu/libc-start.c                                |   16 +
 elf/Makefile                                    |    9 +-
 elf/setup-vdso.h                                |    2 +-
 elf/tst-ptrguard1-static.c                      |    1 +
 elf/tst-ptrguard1.c                             |  202 +++++
 libio/memstream.c                               |    5 +-
 libio/wmemstream.c                              |    6 +-
 malloc/malloc.c                                 |   21 +
 manual/conf.texi                                |    9 +
 manual/filesys.texi                             |   73 ++-
 math/libm-test.inc                              |  175 ++++-
 math/s_cexp.c                                   |   14 +-
 math/s_cexpf.c                                  |   14 +-
 math/s_cexpl.c                                  |   14 +-
 math/s_cproj.c                                  |    4 +-
 math/s_cprojf.c                                 |    4 +-
 math/s_cprojl.c                                 |    4 +-
 math/s_fdim.c                                   |    8 +-
 math/s_fdimf.c                                  |    8 +-
 math/s_fdiml.c                                  |    8 +-
 nptl/ChangeLog                                  |    9 +
 nptl/pthread_cond_broadcast.c                   |    5 +-
 nptl/pthread_cond_signal.c                      |    7 +-
 ports/ChangeLog.ia64                            |    5 +
 ports/ChangeLog.tile                            |    5 +
 ports/sysdeps/ia64/stackguard-macros.h          |    3 +
 ports/sysdeps/tile/stackguard-macros.h          |    6 +
 stdio-common/tst-sscanf.c                       |   34 +
 stdio-common/vfscanf.c                          |    2 +
 stdlib/isomac.c                                 |    1 +
 stdlib/strtod_l.c                               |    9 +-
 stdlib/strtof_l.c                               |    7 +-
 stdlib/tst-strtod6.c                            |   24 +-
 string/Makefile                                 |    4 +-
 string/strcoll_l.c                              |  926 +++++++++++++----------
 string/test-memrchr-ifunc.c                     |   20 +
 string/test-memrchr.c                           |  169 ++++
 string/tst-strcoll-overflow.c                   |   61 ++
 sysdeps/generic/stackguard-macros.h             |    3 +
 sysdeps/i386/fpu/libm-test-ulps                 |   72 ++-
 sysdeps/i386/stackguard-macros.h                |    8 +
 sysdeps/ieee754/flt-32/e_jnf.c                  |    4 +-
 sysdeps/ieee754/flt-32/e_lgammaf_r.c            |    4 +-
 sysdeps/ieee754/ldbl-128/strtold_l.c            |   12 +-
 sysdeps/ieee754/ldbl-128ibm/e_acosl.c           |    8 +-
 sysdeps/ieee754/ldbl-128ibm/e_asinl.c           |    2 +
 sysdeps/ieee754/ldbl-128ibm/ieee754.h           |   19 +
 sysdeps/ieee754/ldbl-128ibm/s_cprojl.c          |    4 +-
 sysdeps/ieee754/ldbl-128ibm/strtold_l.c         |    9 +-
 sysdeps/ieee754/ldbl-64-128/strtold_l.c         |   12 +-
 sysdeps/ieee754/ldbl-96/strtold_l.c             |    9 +-
 sysdeps/posix/dirstream.h                       |    2 +
 sysdeps/posix/getaddrinfo.c                     |   20 +-
 sysdeps/posix/opendir.c                         |    1 +
 sysdeps/posix/readdir_r.c                       |   42 +-
 sysdeps/posix/rewinddir.c                       |    1 +
 sysdeps/powerpc/jmpbuf-offsets.h                |    6 +-
 sysdeps/powerpc/powerpc32/fpu/setjmp-common.S   |   65 +-
 sysdeps/powerpc/powerpc32/power7/memrchr.S      |    4 +-
 sysdeps/powerpc/powerpc32/stackguard-macros.h   |   10 +
 sysdeps/powerpc/powerpc64/__longjmp-common.S    |    4 +-
 sysdeps/powerpc/powerpc64/power7/memrchr.S      |    4 +-
 sysdeps/powerpc/powerpc64/power7/stpcpy.S       |   24 +
 sysdeps/powerpc/powerpc64/power7/strcpy.S       |  274 +++++++
 sysdeps/powerpc/powerpc64/setjmp-common.S       |   72 +-
 sysdeps/powerpc/powerpc64/stackguard-macros.h   |   10 +
 sysdeps/powerpc/powerpc64/stpcpy.S              |   83 +--
 sysdeps/powerpc/powerpc64/strcpy.S              |  153 +++-
 sysdeps/s390/s390-32/stackguard-macros.h        |   11 +
 sysdeps/s390/s390-64/stackguard-macros.h        |   14 +
 sysdeps/sparc/sparc32/stackguard-macros.h       |    3 +
 sysdeps/sparc/sparc64/stackguard-macros.h       |    3 +
 sysdeps/unix/sysv/linux/i386/readdir64_r.c      |    1 -
 sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c |    1 -
 sysdeps/x86_64/fpu/libm-test-ulps               |   75 ++-
 sysdeps/x86_64/stackguard-macros.h              |    5 +
 78 files changed, 2432 insertions(+), 777 deletions(-)
 create mode 100644 elf/tst-ptrguard1-static.c
 create mode 100644 elf/tst-ptrguard1.c
 create mode 100644 string/test-memrchr-ifunc.c
 create mode 100644 string/test-memrchr.c
 create mode 100644 string/tst-strcoll-overflow.c
 create mode 100644 sysdeps/powerpc/powerpc64/power7/stpcpy.S
 create mode 100644 sysdeps/powerpc/powerpc64/power7/strcpy.S


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]