public inbox for newlib-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] ldtoa: don't restrict outbuf size to ndigits
@ 2021-11-22 12:59 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2021-11-22 12:59 UTC (permalink / raw)
  To: cygwin-cvs, newlib-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=68faeef4be712df60443c6bb5764b1e9ddad20e2

commit 68faeef4be712df60443c6bb5764b1e9ddad20e2
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Mon Nov 22 13:57:16 2021 +0100

    ldtoa: don't restrict outbuf size to ndigits
    
    https://cygwin.com/pipermail/cygwin/2021-November/249930.html
    reported a regression introduce by using a dynamically sized local
    char array in favor of a statically sized array.
    
    Fix this by reverting to a statically sized array, using a small
    buffer on the stack for a reasonable number of requested digits, a
    big mallocated buffer otherwise.  This should work for small targets
    as well, given that malloc is used in printf anyway right now.
    
    This is *still* hopefully just a temporary measure, unless somebody
    actually provides a new ldtoa.
    
    Fixes: 4d90e53359145 ("ldtoa: fix dropping too many digits from output")
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 newlib/libc/stdlib/ldtoa.c  | 35 +++++++++++++++++++++++++----------
 winsup/cygwin/release/3.3.3 |  3 +++
 2 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/newlib/libc/stdlib/ldtoa.c b/newlib/libc/stdlib/ldtoa.c
index 7da61457b..1b32e801c 100644
--- a/newlib/libc/stdlib/ldtoa.c
+++ b/newlib/libc/stdlib/ldtoa.c
@@ -33,10 +33,10 @@ void _IO_ldtostr (long double *, char *, int, int, char);
  /* Number of bits of precision */
 #define NBITS ((NI-4)*16)
 
- /* Maximum number of decimal digits in ASCII conversion
-  * Take full possible size of output into account
-  */
+ /* Maximum number of decimal digits in ASCII conversion */
 #define NDEC 1023
+ /* Use static stack buffer for up to 44 digits */
+#define NDEC_SML 44
 
  /* The exponent of 1.0 */
 #define EXONE (0x3fff)
@@ -2794,6 +2794,8 @@ _ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits,
   LDPARMS rnd;
   LDPARMS *ldp = &rnd;
   char *outstr;
+  char outbuf_sml[NDEC_SML + MAX_EXP_DIGITS + 10];
+  char *outbuf = outbuf_sml;
   union uconv du;
   du.d = d;
 
@@ -2836,11 +2838,22 @@ _ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits,
     ndigits = 20;
 
 /* This sanity limit must agree with the corresponding one in etoasc, to
-   keep straight the returned value of outexpon.  */
+   keep straight the returned value of outexpon.  Note that we use a dynamic
+   limit now, either NDEC or NDEC_SML, depending on ndigits.  See the usage
+   of "my_NDEC" in etoasc. */
   if (ndigits > NDEC)
     ndigits = NDEC;
 
-  char outbuf[ndigits + MAX_EXP_DIGITS + 10];
+  /* Allocate buffer if more than NDEC_SML digits are requested. */
+  if (ndigits > NDEC_SML)
+    {
+      outbuf = (char *) _malloc_r (ptr, NDEC + MAX_EXP_DIGITS + 10);
+      if (!outbuf)
+	{
+	  ndigits = NDEC_SML;
+	  outbuf = outbuf_sml;
+	}
+    }
 
   etoasc (e, outbuf, ndigits, mode, ldp);
   s = outbuf;
@@ -2933,6 +2946,9 @@ stripspaces:
   if (rve)
     *rve = outstr + (s - outbuf);
 
+  if (outbuf != outbuf_sml)
+    _free_r (ptr, outbuf);
+
   return outstr;
 }
 
@@ -2987,6 +3003,7 @@ etoasc (short unsigned int *x, char *string, int ndigits, int outformat,
   char *s, *ss;
   unsigned short m;
   unsigned short *equot = ldp->equot;
+  int my_NDEC = (ndigits > NDEC_SML) ? NDEC : NDEC_SML;
 
   ndigs = ndigits;
   rndsav = ldp->rndprc;
@@ -3112,9 +3129,7 @@ tnzro:
       else
 	{
 	  emovi (y, w);
-	  /* Note that this loop does not access the incoming string array,
-	   * which may be shorter than NDEC + 1 bytes! */
-	  for (i = 0; i < NDEC + 1; i++)
+	  for (i = 0; i < my_NDEC + 1; i++)
 	    {
 	      if ((w[NI - 1] & 0x7) != 0)
 		break;
@@ -3190,8 +3205,8 @@ isone:
 else if( ndigs < 0 )
         ndigs = 0;
 */
-  if (ndigs > NDEC)
-    ndigs = NDEC;
+  if (ndigs > my_NDEC)
+    ndigs = my_NDEC;
   if (digit == 10)
     {
       *s++ = '1';
diff --git a/winsup/cygwin/release/3.3.3 b/winsup/cygwin/release/3.3.3
index a35c88b97..908ebe402 100644
--- a/winsup/cygwin/release/3.3.3
+++ b/winsup/cygwin/release/3.3.3
@@ -34,3 +34,6 @@ Bug Fixes
 
 - Fix two bugs in raise(2).
   Addresses: https://cygwin.com/pipermail/cygwin/2021-November/249973.html
+
+- Fix regression in printf introduced with Cygwin 3.3.2.
+  Addresses: https://cygwin.com/pipermail/cygwin/2021-November/249930.html


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-11-22 12:59 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-22 12:59 [newlib-cygwin] ldtoa: don't restrict outbuf size to ndigits Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).