From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id BF1C73858D35; Mon, 22 Nov 2021 12:59:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BF1C73858D35 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org, newlib-cvs@sourceware.org Subject: [newlib-cygwin/cygwin-3_3-branch] ldtoa: don't restrict outbuf size to ndigits X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/cygwin-3_3-branch X-Git-Oldrev: 4889390c3f19bb038fcb60ea5b6d8a5beaee368b X-Git-Newrev: dda1874380312b440b613343ed032eb5f7db964e Message-Id: <20211122125920.BF1C73858D35@sourceware.org> Date: Mon, 22 Nov 2021 12:59:20 +0000 (GMT) X-BeenThere: newlib-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib GIT logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Nov 2021 12:59:20 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=dda1874380312b440b613343ed032eb5f7db964e commit dda1874380312b440b613343ed032eb5f7db964e Author: Corinna Vinschen 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 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