diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | manual/arith.texi | 22 | ||||
-rw-r--r-- | misc/efgcvt.c | 55 | ||||
-rw-r--r-- | misc/efgcvt_r.c | 14 | ||||
-rw-r--r-- | misc/qefgcvt.c | 3 | ||||
-rw-r--r-- | misc/qefgcvt_r.c | 3 | ||||
-rw-r--r-- | misc/tst-efgcvt.c | 6 |
7 files changed, 53 insertions, 63 deletions
@@ -1,3 +1,16 @@ +1999-06-23 Ulrich Drepper <drepper@cygnus.com> + + * manual/arith.texi: Document restriction of ndigit parameter of + ecvt and friends. + * misc/efgcvt.c: Define NDIGIT_MAX. + (gcvt): Limit precision in sprintf call to NDIGIT_MAX. + Do not dynamically allocate the static buffers. They are small enough. + * misc/efgcvt_r.c: Define NDIGIT_MAX. + (fcvt_r): Limit precision in snprintf call to NDIGIT_MAX. + * misc/qefgcvt.c: Define NDIGIT_MAX. + * misc/qefgcvt_r.c: Likewise. + * misc/tst-efgcvt.c (special): Add test for large ndigit parameter. + 1999-06-23 Zack Weinberg <zack@rabi.columbia.edu> * libio/stdio.h: Define stdin, stdout, stderr as macros. diff --git a/manual/arith.texi b/manual/arith.texi index a422677..7879a77 100644 --- a/manual/arith.texi +++ b/manual/arith.texi @@ -2199,6 +2199,9 @@ index in the string of the first digit after the decimal point. @var{neg} is set to a nonzero value if @var{value} is negative, zero otherwise. +If @var{ndigit} decimal digits would exceed the precision of a +@code{double} it is reduced to a system-specific value. + The returned string is statically allocated and overwritten by each call to @code{ecvt}. @@ -2220,6 +2223,9 @@ left of the decimal point. For example, if @var{ndigit} is @code{-1}, negative and larger than the number of digits to the left of the decimal point in @var{value}, @var{value} will be rounded to one significant digit. +If @var{ndigit} decimal digits would exceed the precision of a +@code{double} it is reduced to a system-specific value. + The returned string is statically allocated and overwritten by each call to @code{fcvt}. @end deftypefun @@ -2230,6 +2236,9 @@ to @code{fcvt}. @code{gcvt} is functionally equivalent to @samp{sprintf(buf, "%*g", ndigit, value}. It is provided only for compatibility's sake. It returns @var{buf}. + +If @var{ndigit} decimal digits would exceed the precision of a +@code{double} it is reduced to a system-specific value. @end deftypefun As extensions, the GNU C library provides versions of these three @@ -2238,22 +2247,25 @@ functions that take @code{long double} arguments. @comment stdlib.h @comment GNU @deftypefun {char *} qecvt (long double @var{value}, int @var{ndigit}, int *@var{decpt}, int *@var{neg}) -This function is equivalent to @code{ecvt} except that it -takes a @code{long double} for the first parameter. +This function is equivalent to @code{ecvt} except that it takes a +@code{long double} for the first parameter and that @var{ndigit} is +restricted by the precision of a @code{long double}. @end deftypefun @comment stdlib.h @comment GNU @deftypefun {char *} qfcvt (long double @var{value}, int @var{ndigit}, int @var{decpt}, int *@var{neg}) This function is equivalent to @code{fcvt} except that it -takes a @code{long double} for the first parameter. +takes a @code{long double} for the first parameter and that @var{ndigit} is +restricted by the precision of a @code{long double}. @end deftypefun @comment stdlib.h @comment GNU @deftypefun {char *} qgcvt (long double @var{value}, int @var{ndigit}, char *@var{buf}) -This function is equivalent to @code{gcvt} except that it -takes a @code{long double} for the first parameter. +This function is equivalent to @code{gcvt} except that it takes a +@code{long double} for the first parameter and that @var{ndigit} is +restricted by the precision of a @code{long double}. @end deftypefun diff --git a/misc/efgcvt.c b/misc/efgcvt.c index 8c92766..9348914 100644 --- a/misc/efgcvt.c +++ b/misc/efgcvt.c @@ -1,5 +1,5 @@ /* Compatibility functions for floating point formatting. - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1999 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 @@ -19,6 +19,7 @@ #include <stdio.h> #include <stdlib.h> +#include <sys/param.h> #include <float.h> #include <bits/libc-lock.h> @@ -29,6 +30,7 @@ /* Actually we have to write (DBL_DIG + log10 (DBL_MAX_10_EXP)) but we don't have log10 available in the preprocessor. */ # define MAXDIG (DBL_DIG + 3) +# define NDIGIT_MAX DBL_DIG #endif #define APPEND(a, b) APPEND2 (a, b) @@ -39,30 +41,15 @@ #define ECVT_BUFFER APPEND (FUNC_PREFIX, ecvt_buffer) -static char *FCVT_BUFFER; -static char *ECVT_BUFFER; +static char FCVT_BUFFER[MAXDIG]; +static char ECVT_BUFFER[MAXDIG]; -static void -APPEND (FUNC_PREFIX, fcvt_allocate) (void) -{ - FCVT_BUFFER = (char *) malloc (MAXDIG); -} - char * APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign) FLOAT_TYPE value; int ndigit, *decpt, *sign; { - __libc_once_define (static, once); - __libc_once (once, APPEND (FUNC_PREFIX, fcvt_allocate)); - - if (FCVT_BUFFER == NULL) - /* If no core is available we don't have a chance to run the - program successfully and so returning NULL is an acceptable - result. */ - return NULL; - (void) APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, FCVT_BUFFER, MAXDIG); @@ -70,26 +57,11 @@ APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign) } -static void -APPEND (FUNC_PREFIX, ecvt_allocate) (void) -{ - ECVT_BUFFER = (char *) malloc (MAXDIG); -} - char * APPEND (FUNC_PREFIX, ecvt) (value, ndigit, decpt, sign) FLOAT_TYPE value; int ndigit, *decpt, *sign; { - __libc_once_define (static, once); - __libc_once (once, APPEND (FUNC_PREFIX, ecvt_allocate)); - - if (ECVT_BUFFER == NULL) - /* If no core is available we don't have a chance to run the - program successfully and so returning NULL is an acceptable - result. */ - return NULL; - (void) APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, ECVT_BUFFER, MAXDIG); @@ -102,21 +74,6 @@ APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf) int ndigit; char *buf; { - sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", ndigit, value); + sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value); return buf; } - - -/* Make sure the memory is freed if the programs ends while in - memory-debugging mode and something actually was allocated. */ -static void -__attribute__ ((unused)) -free_mem (void) -{ - if (FCVT_BUFFER != NULL) - free (FCVT_BUFFER); - if (ECVT_BUFFER != NULL) - free (ECVT_BUFFER); -} - -text_set_element (__libc_subfreeres, free_mem); diff --git a/misc/efgcvt_r.c b/misc/efgcvt_r.c index 1c237ee..167bd7a 100644 --- a/misc/efgcvt_r.c +++ b/misc/efgcvt_r.c @@ -1,5 +1,5 @@ /* Compatibility functions for floating point formatting, reentrant versions. - Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 1999 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 @@ -26,10 +26,11 @@ #include <sys/param.h> #ifndef FLOAT_TYPE -#define FLOAT_TYPE double -#define FUNC_PREFIX -#define FLOAT_FMT_FLAG -#define FLOAT_NAME_EXT +# define FLOAT_TYPE double +# define FUNC_PREFIX +# define FLOAT_FMT_FLAG +# define FLOAT_NAME_EXT +# define NDIGIT_MAX DBL_DIG #endif #define APPEND(a, b) APPEND2 (a, b) @@ -87,7 +88,8 @@ APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len) /* Value is Inf or NaN. */ *sign = 0; - n = __snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value); + n = __snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", MIN (ndigit, NDIGIT_MAX), + value); if (n < 0) return -1; diff --git a/misc/qefgcvt.c b/misc/qefgcvt.c index 853252c..af65fc1 100644 --- a/misc/qefgcvt.c +++ b/misc/qefgcvt.c @@ -1,5 +1,5 @@ /* Compatibility functions for floating point formatting, long double version. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999 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 @@ -24,5 +24,6 @@ we don't have log10 available in the preprocessor. Since we cannot assume anything on the used `long double' format be generous. */ #define MAXDIG (LDBL_DIG + 12) +#define NDIGIT_MAX LDBL_DIG #include "efgcvt.c" diff --git a/misc/qefgcvt_r.c b/misc/qefgcvt_r.c index 092a639..012ab54 100644 --- a/misc/qefgcvt_r.c +++ b/misc/qefgcvt_r.c @@ -1,6 +1,6 @@ /* Compatibility functions for floating point formatting, reentrant, long double versions. - Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1999 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 @@ -22,5 +22,6 @@ #define FUNC_PREFIX q #define FLOAT_FMT_FLAG "L" #define FLOAT_NAME_EXT l +# define NDIGIT_MAX LDBL_DIG #include "efgcvt_r.c" diff --git a/misc/tst-efgcvt.c b/misc/tst-efgcvt.c index 780dd9a..cfbaa21 100644 --- a/misc/tst-efgcvt.c +++ b/misc/tst-efgcvt.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999 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 @@ -131,6 +131,10 @@ special (void) if (sign != 0 || strcmp (p, "inf") != 0) output_error ("ecvt", NAN, 10, "inf", 0, 0, p, decpt, sign); + /* Simply make sure these calls with large NDIGITs don't crash. */ + (void) ecvt (123.456, 10000, &decpt, &sign); + (void) fcvt (123.456, 10000, &decpt, &sign); + } |