GNU C Library master sources branch master updated. glibc-2.22-579-g8f5e8b0

jsm28@sourceware.org jsm28@sourceware.org
Fri Dec 4 20:37:00 GMT 2015


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, master has been updated
       via  8f5e8b01a1da2a207228f2072c934fa5918554b8 (commit)
      from  79e0d340a9e7fb2c931686462131c92b99611003 (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=8f5e8b01a1da2a207228f2072c934fa5918554b8

commit 8f5e8b01a1da2a207228f2072c934fa5918554b8
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Fri Dec 4 20:36:28 2015 +0000

    Fix nan functions handling of payload strings (bug 16961, bug 16962).
    
    The nan, nanf and nanl functions handle payload strings by doing e.g.:
    
      if (tagp[0] != '\0')
        {
          char buf[6 + strlen (tagp)];
          sprintf (buf, "NAN(%s)", tagp);
          return strtod (buf, NULL);
        }
    
    This is an unbounded stack allocation based on the length of the
    argument.  Furthermore, if the argument starts with an n-char-sequence
    followed by ')', that n-char-sequence is wrongly treated as
    significant for determining the payload of the resulting NaN, when ISO
    C says the call should be equivalent to strtod ("NAN", NULL), without
    being affected by that initial n-char-sequence.  This patch fixes both
    those problems by using the __strtod_nan etc. functions recently
    factored out of strtod etc. for that purpose, with those functions
    being exported from libc at version GLIBC_PRIVATE.
    
    Tested for x86_64, x86, mips64 and powerpc.
    
    	[BZ #16961]
    	[BZ #16962]
    	* math/s_nan.c (__nan): Use __strtod_nan instead of constructing a
    	string on the stack for strtod.
    	* math/s_nanf.c (__nanf): Use __strtof_nan instead of constructing
    	a string on the stack for strtof.
    	* math/s_nanl.c (__nanl): Use __strtold_nan instead of
    	constructing a string on the stack for strtold.
    	* stdlib/Versions (libc): Add __strtof_nan, __strtod_nan and
    	__strtold_nan to GLIBC_PRIVATE.
    	* math/test-nan-overflow.c: New file.
    	* math/test-nan-payload.c: Likewise.
    	* math/Makefile (tests): Add test-nan-overflow and
    	test-nan-payload.

diff --git a/ChangeLog b/ChangeLog
index 266df03..edd7ccf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2015-12-04  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #16961]
+	[BZ #16962]
+	* math/s_nan.c (__nan): Use __strtod_nan instead of constructing a
+	string on the stack for strtod.
+	* math/s_nanf.c (__nanf): Use __strtof_nan instead of constructing
+	a string on the stack for strtof.
+	* math/s_nanl.c (__nanl): Use __strtold_nan instead of
+	constructing a string on the stack for strtold.
+	* stdlib/Versions (libc): Add __strtof_nan, __strtod_nan and
+	__strtold_nan to GLIBC_PRIVATE.
+	* math/test-nan-overflow.c: New file.
+	* math/test-nan-payload.c: Likewise.
+	* math/Makefile (tests): Add test-nan-overflow and
+	test-nan-payload.
+
 2015-12-04  Paul Eggert  <eggert@cs.ucla.edu>
 
 	Consistency about byte vs character in string.texi
diff --git a/NEWS b/NEWS
index cb61a3a..37189f7 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,12 @@ Version 2.23
   C Library is GCC 4.7.  Older GCC versions, and non-GNU compilers, can
   still be used to compile programs using the GNU C Library.
 
+Security related changes:
+
+* The nan, nanf and nanl functions no longer have unbounded stack usage
+  depending on the length of the string passed as an argument to the
+  functions.  Reported by Joseph Myers.
+
 * The following bugs are resolved with this release:
 
   [The release manager will add the list generated by
diff --git a/math/Makefile b/math/Makefile
index 20f90d9..32f5730 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -113,7 +113,8 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
 	test-signgam-finite-c99 test-signgam-finite-c11 \
 	test-nearbyint-except-2 test-signgam-uchar test-signgam-uchar-init \
 	test-signgam-uint test-signgam-uint-init test-signgam-ullong \
-	test-signgam-ullong-init $(tests-static)
+	test-signgam-ullong-init test-nan-overflow test-nan-payload \
+	$(tests-static)
 tests-static = test-fpucw-static test-fpucw-ieee-static \
 	       test-signgam-uchar-static test-signgam-uchar-init-static \
 	       test-signgam-uint-static test-signgam-uint-init-static \
diff --git a/math/s_nan.c b/math/s_nan.c
index f4b30a2..a6f3006 100644
--- a/math/s_nan.c
+++ b/math/s_nan.c
@@ -28,14 +28,7 @@
 double
 __nan (const char *tagp)
 {
-  if (tagp[0] != '\0')
-    {
-      char buf[6 + strlen (tagp)];
-      sprintf (buf, "NAN(%s)", tagp);
-      return strtod (buf, NULL);
-    }
-
-  return NAN;
+  return __strtod_nan (tagp, NULL, 0);
 }
 weak_alias (__nan, nan)
 #ifdef NO_LONG_DOUBLE
diff --git a/math/s_nanf.c b/math/s_nanf.c
index 2d3fcc5..6a98422 100644
--- a/math/s_nanf.c
+++ b/math/s_nanf.c
@@ -28,13 +28,6 @@
 float
 __nanf (const char *tagp)
 {
-  if (tagp[0] != '\0')
-    {
-      char buf[6 + strlen (tagp)];
-      sprintf (buf, "NAN(%s)", tagp);
-      return strtof (buf, NULL);
-    }
-
-  return NAN;
+  return __strtof_nan (tagp, NULL, 0);
 }
 weak_alias (__nanf, nanf)
diff --git a/math/s_nanl.c b/math/s_nanl.c
index 73387a9..4e1fc80 100644
--- a/math/s_nanl.c
+++ b/math/s_nanl.c
@@ -28,13 +28,6 @@
 long double
 __nanl (const char *tagp)
 {
-  if (tagp[0] != '\0')
-    {
-      char buf[6 + strlen (tagp)];
-      sprintf (buf, "NAN(%s)", tagp);
-      return strtold (buf, NULL);
-    }
-
-  return NAN;
+  return __strtold_nan (tagp, NULL, 0);
 }
 weak_alias (__nanl, nanl)
diff --git a/math/test-nan-overflow.c b/math/test-nan-overflow.c
new file mode 100644
index 0000000..f56aaf3
--- /dev/null
+++ b/math/test-nan-overflow.c
@@ -0,0 +1,66 @@
+/* Test nan functions stack overflow (bug 16962).
+   Copyright (C) 2015 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 <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/resource.h>
+
+#define STACK_LIM 1048576
+#define STRING_SIZE (2 * STACK_LIM)
+
+static int
+do_test (void)
+{
+  int result = 0;
+  struct rlimit lim;
+  getrlimit (RLIMIT_STACK, &lim);
+  lim.rlim_cur = STACK_LIM;
+  setrlimit (RLIMIT_STACK, &lim);
+  char *nanstr = malloc (STRING_SIZE);
+  if (nanstr == NULL)
+    {
+      puts ("malloc failed, cannot test");
+      return 77;
+    }
+  memset (nanstr, '0', STRING_SIZE - 1);
+  nanstr[STRING_SIZE - 1] = 0;
+#define NAN_TEST(TYPE, FUNC)			\
+  do						\
+    {						\
+      char *volatile p = nanstr;		\
+      volatile TYPE v = FUNC (p);		\
+      if (isnan (v))				\
+	puts ("PASS: " #FUNC);			\
+      else					\
+	{					\
+	  puts ("FAIL: " #FUNC);		\
+	  result = 1;				\
+	}					\
+    }						\
+  while (0)
+  NAN_TEST (float, nanf);
+  NAN_TEST (double, nan);
+#ifndef NO_LONG_DOUBLE
+  NAN_TEST (long double, nanl);
+#endif
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/math/test-nan-payload.c b/math/test-nan-payload.c
new file mode 100644
index 0000000..358ff71
--- /dev/null
+++ b/math/test-nan-payload.c
@@ -0,0 +1,122 @@
+/* Test nan functions payload handling (bug 16961).
+   Copyright (C) 2015 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 <float.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Avoid built-in functions.  */
+#define WRAP_NAN(FUNC, STR) \
+  ({ const char *volatile wns = (STR); FUNC (wns); })
+#define WRAP_STRTO(FUNC, STR) \
+  ({ const char *volatile wss = (STR); FUNC (wss, NULL); })
+
+#define CHECK_IS_NAN(TYPE, A)			\
+  do						\
+    {						\
+      if (isnan (A))				\
+	puts ("PASS: " #TYPE " " #A);		\
+      else					\
+	{					\
+	  puts ("FAIL: " #TYPE " " #A);		\
+	  result = 1;				\
+	}					\
+    }						\
+  while (0)
+
+#define CHECK_SAME_NAN(TYPE, A, B)			\
+  do							\
+    {							\
+      if (memcmp (&(A), &(B), sizeof (A)) == 0)		\
+	puts ("PASS: " #TYPE " " #A " = " #B);		\
+      else						\
+	{						\
+	  puts ("FAIL: " #TYPE " " #A " = " #B);	\
+	  result = 1;					\
+	}						\
+    }							\
+  while (0)
+
+#define CHECK_DIFF_NAN(TYPE, A, B)			\
+  do							\
+    {							\
+      if (memcmp (&(A), &(B), sizeof (A)) != 0)		\
+	puts ("PASS: " #TYPE " " #A " != " #B);		\
+      else						\
+	{						\
+	  puts ("FAIL: " #TYPE " " #A " != " #B);	\
+	  result = 1;					\
+	}						\
+    }							\
+  while (0)
+
+/* Cannot test payloads by memcmp for formats where NaNs have padding
+   bits.  */
+#define CAN_TEST_EQ(MANT_DIG) ((MANT_DIG) != 64 && (MANT_DIG) != 106)
+
+#define RUN_TESTS(TYPE, SFUNC, FUNC, MANT_DIG)		\
+  do							\
+    {							\
+     TYPE n123 = WRAP_NAN (FUNC, "123");		\
+     CHECK_IS_NAN (TYPE, n123);				\
+     TYPE s123 = WRAP_STRTO (SFUNC, "NAN(123)");	\
+     CHECK_IS_NAN (TYPE, s123);				\
+     TYPE n456 = WRAP_NAN (FUNC, "456");		\
+     CHECK_IS_NAN (TYPE, n456);				\
+     TYPE s456 = WRAP_STRTO (SFUNC, "NAN(456)");	\
+     CHECK_IS_NAN (TYPE, s456);				\
+     TYPE n123x = WRAP_NAN (FUNC, "123)");		\
+     CHECK_IS_NAN (TYPE, n123x);			\
+     TYPE nemp = WRAP_NAN (FUNC, "");			\
+     CHECK_IS_NAN (TYPE, nemp);				\
+     TYPE semp = WRAP_STRTO (SFUNC, "NAN()");		\
+     CHECK_IS_NAN (TYPE, semp);				\
+     TYPE sx = WRAP_STRTO (SFUNC, "NAN");		\
+     CHECK_IS_NAN (TYPE, sx);				\
+     if (CAN_TEST_EQ (MANT_DIG))			\
+       CHECK_SAME_NAN (TYPE, n123, s123);		\
+     if (CAN_TEST_EQ (MANT_DIG))			\
+       CHECK_SAME_NAN (TYPE, n456, s456);		\
+     if (CAN_TEST_EQ (MANT_DIG))			\
+       CHECK_SAME_NAN (TYPE, nemp, semp);		\
+     if (CAN_TEST_EQ (MANT_DIG))			\
+       CHECK_SAME_NAN (TYPE, n123x, sx);		\
+     CHECK_DIFF_NAN (TYPE, n123, n456);			\
+     CHECK_DIFF_NAN (TYPE, n123, nemp);			\
+     CHECK_DIFF_NAN (TYPE, n123, n123x);		\
+     CHECK_DIFF_NAN (TYPE, n456, nemp);			\
+     CHECK_DIFF_NAN (TYPE, n456, n123x);		\
+    }							\
+  while (0)
+
+static int
+do_test (void)
+{
+  int result = 0;
+  RUN_TESTS (float, strtof, nanf, FLT_MANT_DIG);
+  RUN_TESTS (double, strtod, nan, DBL_MANT_DIG);
+#ifndef NO_LONG_DOUBLE
+  RUN_TESTS (long double, strtold, nanl, LDBL_MANT_DIG);
+#endif
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdlib/Versions b/stdlib/Versions
index f1777df..60b628d 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -118,5 +118,6 @@ libc {
     # Used from other libraries
     __libc_secure_getenv;
     __call_tls_dtors;
+    __strtof_nan; __strtod_nan; __strtold_nan;
   }
 }

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

Summary of changes:
 ChangeLog                                 |   17 ++++
 NEWS                                      |    6 ++
 math/Makefile                             |    3 +-
 math/s_nan.c                              |    9 +--
 math/s_nanf.c                             |    9 +--
 math/s_nanl.c                             |    9 +--
 math/{test-powl.c => test-nan-overflow.c} |   59 +++++++++------
 math/test-nan-payload.c                   |  122 +++++++++++++++++++++++++++++
 stdlib/Versions                           |    1 +
 9 files changed, 187 insertions(+), 48 deletions(-)
 copy math/{test-powl.c => test-nan-overflow.c} (51%)
 create mode 100644 math/test-nan-payload.c


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



More information about the Glibc-cvs mailing list