[arch-commits] Commit in glibc/trunk (3 files)

Allan McRae allan at archlinux.org
Wed Aug 29 11:53:36 UTC 2012


    Date: Wednesday, August 29, 2012 @ 07:53:35
  Author: allan
Revision: 165745

upgpkg: glibc 2.16.0-4

fix buffer/integer overflow in strtod and segfault in strncasecmp

Added:
  glibc/trunk/glibc-2.16-strncasecmp-segfault.patch
  glibc/trunk/glibc-2.16-strtod-overflow.patch
Modified:
  glibc/trunk/PKGBUILD

---------------------------------------+
 PKGBUILD                              |   14 +
 glibc-2.16-strncasecmp-segfault.patch |   65 +++++
 glibc-2.16-strtod-overflow.patch      |  389 ++++++++++++++++++++++++++++++++
 3 files changed, 467 insertions(+), 1 deletion(-)

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2012-08-29 11:46:05 UTC (rev 165744)
+++ PKGBUILD	2012-08-29 11:53:35 UTC (rev 165745)
@@ -6,7 +6,7 @@
 
 pkgname=glibc
 pkgver=2.16.0
-pkgrel=3
+pkgrel=4
 pkgdesc="GNU C Library"
 arch=('i686' 'x86_64')
 url="http://www.gnu.org/software/libc"
@@ -23,6 +23,8 @@
         glibc-2.15-fix-res_query-assert.patch
         glibc-2.15-revert-c5a0802a.patch
         glibc-2.16-rpcgen-cpp-path.patch
+        glibc-2.16-strncasecmp-segfault.patch
+        glibc-2.16-strtod-overflow.patch
         nscd.rcd
         nscd.service
         nscd.tmpfiles
@@ -33,6 +35,8 @@
          '31f415b41197d85d3bbee3d1eecd06a3'
          '0a0383d50d63f1c02919fe9943b82014'
          'ea6a43915474e8276e9361eed6a01280'
+         'f042d37cc8ca3459023431809039bc88'
+         '61d322f7681a85d3293ada5c3ccc2c7e'
          '589d79041aa767a5179eaa4e2737dd3f'
          'ad8a9af15ab7eeaa23dc7ee85024af9f'
          'bccbe5619e75cf1d97312ec3681c605c'
@@ -54,6 +58,14 @@
   # http://sourceware.org/git/?p=glibc.git;a=commit;h=bf9b740a
   patch -p1 -i ${srcdir}/glibc-2.16-rpcgen-cpp-path.patch
 
+  # strncasecmp segfault on i686
+  # http://sourceware.org/git/?p=glibc.git;a=commit;h=6db8f737
+  patch -p1 -i ${srcdir}/glibc-2.16-strncasecmp-segfault.patch
+
+  # strtod integer/buffer overflow
+  # http://sourceware.org/git/?p=glibc.git;a=commit;h=da1f4319
+  patch -p1 -i ${srcdir}/glibc-2.16-strtod-overflow.patch
+
   # ldconfig does not need to look in /usr/lib64 or /usr/libx32 on Arch Linux
   sed -i "s#add_system_dir#do_not_add_system_dir#" sysdeps/unix/sysv/linux/x86_64/dl-cache.h
 

Added: glibc-2.16-strncasecmp-segfault.patch
===================================================================
--- glibc-2.16-strncasecmp-segfault.patch	                        (rev 0)
+++ glibc-2.16-strncasecmp-segfault.patch	2012-08-29 11:53:35 UTC (rev 165745)
@@ -0,0 +1,65 @@
+diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c
+index 6c17530..acfe668 100644
+--- a/string/test-strncasecmp.c
++++ b/string/test-strncasecmp.c
+@@ -1,5 +1,5 @@
+ /* Test and measure strncasecmp functions.
+-   Copyright (C) 1999, 2002, 2003, 2005, 2010 Free Software Foundation, Inc.
++   Copyright (C) 1999-2012 Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+    Written by Jakub Jelinek <jakub at redhat.com>, 1999.
+ 
+@@ -251,9 +251,9 @@ do_random_tests (void)
+     }
+ }
+ 
+-
++/* Regression test for BZ #12205 */
+ static void
+-check1 (void)
++bz12205 (void)
+ {
+   static char cp [4096+16] __attribute__ ((aligned(4096)));
+   static char gotrel[4096] __attribute__ ((aligned(4096)));
+@@ -270,6 +270,15 @@ check1 (void)
+     check_result (impl, s1, s2, n, exp_result);
+ }
+ 
++/* Regression test for BZ #14195 */
++static void
++bz14195 (void)
++{
++  const char *empty_string  = "";
++  FOR_EACH_IMPL (impl, 0)
++    check_result (impl, empty_string, "", 5, 0);
++}
++
+ int
+ test_main (void)
+ {
+@@ -277,7 +286,8 @@ test_main (void)
+ 
+   test_init ();
+ 
+-  check1 ();
++  bz12205 ();
++  bz14195 ();
+ 
+   printf ("%23s", "");
+   FOR_EACH_IMPL (impl, 0)
+diff --git a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S b/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
+index 5e6321e..9735ad0 100644
+--- a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
++++ b/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
+@@ -2445,7 +2445,7 @@ L(less16bytes_sncmp):
+ # endif
+ 	jne	L(neq_sncmp)
+ 	test	%cl, %cl
+-	je	L(eq)
++	je	L(eq_sncmp)
+ 
+ 	cmp	$1, REM
+ 	je	L(eq_sncmp)
+-- 
+1.7.3.4
+

Added: glibc-2.16-strtod-overflow.patch
===================================================================
--- glibc-2.16-strtod-overflow.patch	                        (rev 0)
+++ glibc-2.16-strtod-overflow.patch	2012-08-29 11:53:35 UTC (rev 165745)
@@ -0,0 +1,389 @@
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index f7811c5..79c9acb 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -68,7 +68,8 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
+ 		   tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
+ 		   tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2	    \
+ 		   tst-makecontext2 tst-strtod6 tst-unsetenv1		    \
+-		   tst-makecontext3 bug-getcontext bug-fmtmsg1
++		   tst-makecontext3 bug-getcontext bug-fmtmsg1		    \
++		   tst-strtod-overflow
+ 
+ include ../Makeconfig
+ 
+diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
+index 2166a08..a8a7ea8 100644
+--- a/stdlib/strtod_l.c
++++ b/stdlib/strtod_l.c
+@@ -60,6 +60,7 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
+ #include <math.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <stdint.h>
+ 
+ /* The gmp headers need some configuration frobs.  */
+ #define HAVE_ALLOCA 1
+@@ -72,7 +73,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
+ #include "longlong.h"
+ #include "fpioconst.h"
+ 
+-#define NDEBUG 1
+ #include <assert.h>
+ 
+ 
+@@ -174,19 +174,19 @@ extern const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1];
+ /* Return a floating point number of the needed type according to the given
+    multi-precision number after possible rounding.  */
+ static FLOAT
+-round_and_return (mp_limb_t *retval, int exponent, int negative,
++round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
+ 		  mp_limb_t round_limb, mp_size_t round_bit, int more_bits)
+ {
+   if (exponent < MIN_EXP - 1)
+     {
+-      mp_size_t shift = MIN_EXP - 1 - exponent;
+-
+-      if (shift > MANT_DIG)
++      if (exponent < MIN_EXP - 1 - MANT_DIG)
+ 	{
+ 	  __set_errno (ERANGE);
+ 	  return 0.0;
+ 	}
+ 
++      mp_size_t shift = MIN_EXP - 1 - exponent;
++
+       more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0;
+       if (shift == MANT_DIG)
+ 	/* This is a special case to handle the very seldom case where
+@@ -233,6 +233,9 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+       __set_errno (ERANGE);
+     }
+ 
++  if (exponent > MAX_EXP)
++    goto overflow;
++
+   if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0
+       && (more_bits || (retval[0] & 1) != 0
+ 	  || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0))
+@@ -258,6 +261,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+     }
+ 
+   if (exponent > MAX_EXP)
++  overflow:
+     return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+ 
+   return MPN2FLOAT (retval, exponent, negative);
+@@ -271,7 +275,7 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
+    factor for the resulting number (see code) multiply by it.  */
+ static const STRING_TYPE *
+ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+-	    int *exponent
++	    intmax_t *exponent
+ #ifndef USE_WIDE_CHAR
+ 	    , const char *decimal, size_t decimal_len, const char *thousands
+ #endif
+@@ -301,6 +305,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+ 	      cy += __mpn_add_1 (n, n, *nsize, low);
+ 	      if (cy != 0)
+ 		{
++		  assert (*nsize < MPNSIZE);
+ 		  n[*nsize] = cy;
+ 		  ++(*nsize);
+ 		}
+@@ -335,7 +340,7 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+     }
+   while (--digcnt > 0);
+ 
+-  if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB)
++  if (*exponent > 0 && *exponent <= MAX_DIG_PER_LIMB - cnt)
+     {
+       low *= _tens_in_limb[*exponent];
+       start = _tens_in_limb[cnt + *exponent];
+@@ -355,7 +360,10 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
+       cy = __mpn_mul_1 (n, n, *nsize, start);
+       cy += __mpn_add_1 (n, n, *nsize, low);
+       if (cy != 0)
+-	n[(*nsize)++] = cy;
++	{
++	  assert (*nsize < MPNSIZE);
++	  n[(*nsize)++] = cy;
++	}
+     }
+ 
+   return str;
+@@ -413,7 +421,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ {
+   int negative;			/* The sign of the number.  */
+   MPN_VAR (num);		/* MP representation of the number.  */
+-  int exponent;			/* Exponent of the number.  */
++  intmax_t exponent;		/* Exponent of the number.  */
+ 
+   /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
+   int base = 10;
+@@ -435,7 +443,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+   /* Points at the character following the integer and fractional digits.  */
+   const STRING_TYPE *expp;
+   /* Total number of digit and number of digits in integer part.  */
+-  int dig_no, int_no, lead_zero;
++  size_t dig_no, int_no, lead_zero;
+   /* Contains the last character read.  */
+   CHAR_TYPE c;
+ 
+@@ -767,7 +775,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+      are all or any is really a fractional digit will be decided
+      later.  */
+   int_no = dig_no;
+-  lead_zero = int_no == 0 ? -1 : 0;
++  lead_zero = int_no == 0 ? (size_t) -1 : 0;
+ 
+   /* Read the fractional digits.  A special case are the 'american
+      style' numbers like `16.' i.e. with decimal point but without
+@@ -789,12 +797,13 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 	     (base == 16 && ({ CHAR_TYPE lo = TOLOWER (c);
+ 			       lo >= L_('a') && lo <= L_('f'); })))
+ 	{
+-	  if (c != L_('0') && lead_zero == -1)
++	  if (c != L_('0') && lead_zero == (size_t) -1)
+ 	    lead_zero = dig_no - int_no;
+ 	  ++dig_no;
+ 	  c = *++cp;
+ 	}
+     }
++  assert (dig_no <= (uintmax_t) INTMAX_MAX);
+ 
+   /* Remember start of exponent (if any).  */
+   expp = cp;
+@@ -817,24 +826,80 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 
+       if (c >= L_('0') && c <= L_('9'))
+ 	{
+-	  int exp_limit;
++	  intmax_t exp_limit;
+ 
+ 	  /* Get the exponent limit. */
+ 	  if (base == 16)
+-	    exp_limit = (exp_negative ?
+-			 -MIN_EXP + MANT_DIG + 4 * int_no :
+-			 MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
++	    {
++	      if (exp_negative)
++		{
++		  assert (int_no <= (uintmax_t) (INTMAX_MAX
++						 + MIN_EXP - MANT_DIG) / 4);
++		  exp_limit = -MIN_EXP + MANT_DIG + 4 * (intmax_t) int_no;
++		}
++	      else
++		{
++		  if (int_no)
++		    {
++		      assert (lead_zero == 0
++			      && int_no <= (uintmax_t) INTMAX_MAX / 4);
++		      exp_limit = MAX_EXP - 4 * (intmax_t) int_no + 3;
++		    }
++		  else if (lead_zero == (size_t) -1)
++		    {
++		      /* The number is zero and this limit is
++			 arbitrary.  */
++		      exp_limit = MAX_EXP + 3;
++		    }
++		  else
++		    {
++		      assert (lead_zero
++			      <= (uintmax_t) (INTMAX_MAX - MAX_EXP - 3) / 4);
++		      exp_limit = (MAX_EXP
++				   + 4 * (intmax_t) lead_zero
++				   + 3);
++		    }
++		}
++	    }
+ 	  else
+-	    exp_limit = (exp_negative ?
+-			 -MIN_10_EXP + MANT_DIG + int_no :
+-			 MAX_10_EXP - int_no + lead_zero + 1);
++	    {
++	      if (exp_negative)
++		{
++		  assert (int_no
++			  <= (uintmax_t) (INTMAX_MAX + MIN_10_EXP - MANT_DIG));
++		  exp_limit = -MIN_10_EXP + MANT_DIG + (intmax_t) int_no;
++		}
++	      else
++		{
++		  if (int_no)
++		    {
++		      assert (lead_zero == 0
++			      && int_no <= (uintmax_t) INTMAX_MAX);
++		      exp_limit = MAX_10_EXP - (intmax_t) int_no + 1;
++		    }
++		  else if (lead_zero == (size_t) -1)
++		    {
++		      /* The number is zero and this limit is
++			 arbitrary.  */
++		      exp_limit = MAX_10_EXP + 1;
++		    }
++		  else
++		    {
++		      assert (lead_zero
++			      <= (uintmax_t) (INTMAX_MAX - MAX_10_EXP - 1));
++		      exp_limit = MAX_10_EXP + (intmax_t) lead_zero + 1;
++		    }
++		}
++	    }
++
++	  if (exp_limit < 0)
++	    exp_limit = 0;
+ 
+ 	  do
+ 	    {
+-	      exponent *= 10;
+-	      exponent += c - L_('0');
+-
+-	      if (__builtin_expect (exponent > exp_limit, 0))
++	      if (__builtin_expect ((exponent > exp_limit / 10
++				     || (exponent == exp_limit / 10
++					 && c - L_('0') > exp_limit % 10)), 0))
+ 		/* The exponent is too large/small to represent a valid
+ 		   number.  */
+ 		{
+@@ -843,7 +908,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 		  /* We have to take care for special situation: a joker
+ 		     might have written "0.0e100000" which is in fact
+ 		     zero.  */
+-		  if (lead_zero == -1)
++		  if (lead_zero == (size_t) -1)
+ 		    result = negative ? -0.0 : 0.0;
+ 		  else
+ 		    {
+@@ -862,6 +927,9 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 		  /* NOTREACHED */
+ 		}
+ 
++	      exponent *= 10;
++	      exponent += c - L_('0');
++
+ 	      c = *++cp;
+ 	    }
+ 	  while (c >= L_('0') && c <= L_('9'));
+@@ -930,7 +998,14 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 	}
+ #endif
+       startp += lead_zero + decimal_len;
+-      exponent -= base == 16 ? 4 * lead_zero : lead_zero;
++      assert (lead_zero <= (base == 16
++			    ? (uintmax_t) INTMAX_MAX / 4
++			    : (uintmax_t) INTMAX_MAX));
++      assert (lead_zero <= (base == 16
++			    ? ((uintmax_t) exponent
++			       - (uintmax_t) INTMAX_MIN) / 4
++			    : ((uintmax_t) exponent - (uintmax_t) INTMAX_MIN)));
++      exponent -= base == 16 ? 4 * (intmax_t) lead_zero : (intmax_t) lead_zero;
+       dig_no -= lead_zero;
+     }
+ 
+@@ -972,7 +1047,10 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+ 	}
+ 
+       /* Adjust the exponent for the bits we are shifting in.  */
+-      exponent += bits - 1 + (int_no - 1) * 4;
++      assert (int_no <= (uintmax_t) (exponent < 0
++				     ? (INTMAX_MAX - bits + 1) / 4
++				     : (INTMAX_MAX - exponent - bits + 1) / 4));
++      exponent += bits - 1 + ((intmax_t) int_no - 1) * 4;
+ 
+       while (--dig_no > 0 && idx >= 0)
+ 	{
+@@ -1024,13 +1102,15 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+      really integer digits or belong to the fractional part; i.e. we normalize
+      123e-2 to 1.23.  */
+   {
+-    register int incr = (exponent < 0 ? MAX (-int_no, exponent)
+-			 : MIN (dig_no - int_no, exponent));
++    register intmax_t incr = (exponent < 0
++			      ? MAX (-(intmax_t) int_no, exponent)
++			      : MIN ((intmax_t) dig_no - (intmax_t) int_no,
++				     exponent));
+     int_no += incr;
+     exponent -= incr;
+   }
+ 
+-  if (__builtin_expect (int_no + exponent > MAX_10_EXP + 1, 0))
++  if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
+     {
+       __set_errno (ERANGE);
+       return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
+@@ -1215,7 +1295,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+        digits we should have enough bits for the result.  The remaining
+        decimal digits give us the information that more bits are following.
+        This can be used while rounding.  (Two added as a safety margin.)  */
+-    if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 2)
++    if ((intmax_t) dig_no > (intmax_t) int_no + (MANT_DIG - bits + 2) / 3 + 2)
+       {
+ 	dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 2;
+ 	more_bits = 1;
+@@ -1223,7 +1303,7 @@ ____STRTOF_INTERNAL (nptr, endptr, group, loc)
+     else
+       more_bits = 0;
+ 
+-    neg_exp = dig_no - int_no - exponent;
++    neg_exp = (intmax_t) dig_no - (intmax_t) int_no - exponent;
+ 
+     /* Construct the denominator.  */
+     densize = 0;
+diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c
+new file mode 100644
+index 0000000..668d55b
+--- /dev/null
++++ b/stdlib/tst-strtod-overflow.c
+@@ -0,0 +1,48 @@
++/* Test for integer/buffer overflow in strtod.
++   Copyright (C) 2012 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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#define EXPONENT "e-2147483649"
++#define SIZE 214748364
++
++static int
++do_test (void)
++{
++  char *p = malloc (1 + SIZE + sizeof (EXPONENT));
++  if (p == NULL)
++    {
++      puts ("malloc failed, cannot test for overflow");
++      return 0;
++    }
++  p[0] = '1';
++  memset (p + 1, '0', SIZE);
++  memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
++  double d = strtod (p, NULL);
++  if (d != 0)
++    {
++      printf ("strtod returned wrong value: %a\n", d);
++      return 1;
++    }
++  return 0;
++}
++
++#define TEST_FUNCTION do_test ()
++#include "../test-skeleton.c"
+-- 
+1.7.3.4
+




More information about the arch-commits mailing list