From 6763475160ceb051028206a4e4f1833a0a028da4 Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Thu, 26 Dec 2024 17:55:14 +0100 Subject: [PATCH] sprintf_s: strip leading zeros and dot on %g (not %#g) fixes parts of GH #68 --- ChangeLog | 7 +++++++ src/str/vsnprintf_s.c | 20 ++++++++++++++++---- tests/test_sprintf_s.c | 10 +++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index d79a0abf..8d52e2a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ ChangeLog file for safeclib +Changes in 3.9 + - Add long double support to vsnprintf_s. GH #103 + With fixes for %a, %g, %G, %#g. + - Fixed %lc, %ls bug in vsnprintf_s. + - Fixes for non-POSIX systems missing fileno and ftruncate. GH #136 + (ecospro compiler) + Changes in 3.8.2 - Fixed vsnprintf_s safec_etoa div-by-zero exceptions. GH #144 - Fixed C90 compliance, decl-after-stmt. Matthias Schulz. diff --git a/src/str/vsnprintf_s.c b/src/str/vsnprintf_s.c index fba820de..486f5720 100644 --- a/src/str/vsnprintf_s.c +++ b/src/str/vsnprintf_s.c @@ -392,7 +392,7 @@ static size_t safec_ftoa(out_fct_type out, const char *funcname, char *buffer, unsigned int prec, unsigned int width, unsigned int flags) { char buf[PRINTF_FTOA_BUFFER_SIZE]; - size_t len = 0U; + size_t len = 0U, off = 0U; double tmp; double diff = 0.0; unsigned long frac; @@ -525,6 +525,19 @@ static size_t safec_ftoa(out_fct_type out, const char *funcname, char *buffer, } } + // strip leading zeros and dots + if ((flags & FLAGS_ADAPT_EXP) && !(flags & FLAGS_HASH)) { + size_t olen = len; + while (buf[off] == '0') { + off++; len--; + if (off >= olen) + break; + } + if (buf[off] == '.' && off < olen) { + off++; len--; + } + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { if (negative) { buf[len++] = '-'; @@ -535,7 +548,7 @@ static size_t safec_ftoa(out_fct_type out, const char *funcname, char *buffer, } } - return safec_out_rev(out, buffer, idx, maxlen, buf, len, width, flags); + return safec_out_rev(out, buffer, idx, maxlen, &buf[off], len, width, flags); } #ifdef PRINTF_SUPPORT_LONG_DOUBLE @@ -763,7 +776,6 @@ static size_t safec_etoa(out_fct_type out, const char *funcname, char *buffer, // in "%g" mode, "prec" is the number of *significant figures* not decimals if (flags & FLAGS_ADAPT_EXP) { // do we want to fall-back to "%f" mode? - // TODO: strip trailing zeros and dot if ((flags & FLAGS_HASH) || ((value >= 1e-4) && (value < 1e6))) { if ((int)prec > expval) { prec = (unsigned)((int)prec - expval - 1); @@ -807,7 +819,7 @@ static size_t safec_etoa(out_fct_type out, const char *funcname, char *buffer, const size_t start_idx = idx; idx = safec_ftoa(out, funcname, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, - flags & ~FLAGS_ADAPT_EXP); + flags); // output the exponent part if (minwidth) { diff --git a/tests/test_sprintf_s.c b/tests/test_sprintf_s.c index d41c348b..af94cb3b 100644 --- a/tests/test_sprintf_s.c +++ b/tests/test_sprintf_s.c @@ -393,22 +393,22 @@ int test_sprintf_s(void) { EXPSTR(str2, "0.100000") rc = sprintf_s(str2, LEN, "%g", 0.1); NOERRNULL() - EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped + EXPSTR(str2, "0.1") rc = sprintf_s(str2, LEN, "%#g", 0.1); // alternate form NOERRNULL() EXPSTR(str2, "0.100000") rc = sprintf_s(str2, LEN, "%G", 0.1); NOERRNULL() - EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped + EXPSTR(str2, "0.1") rc = sprintf_s(str2, LEN, "%g", 0.1f); NOERRNULL() - EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped + EXPSTR(str2, "0.1") rc = sprintf_s(str2, LEN, "%g", 1.0); NOERRNULL() - EXPSTR(str2, "1") // FIXME 0.100000 trailing-zeros and dot not stripped + EXPSTR(str2, "1") rc = sprintf_s(str2, LEN, "%lg", 0.1); NOERRNULL() - EXPSTR(str2, "0.1") // FIXME 0.100000 trailing-zeros not stripped + EXPSTR(str2, "0.1") rc = sprintf_s(str2, LEN, "%a", 0.1f); NOERRNULL() EXPSTR(str2, "0x1.99999ap-4")