summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rw-r--r--strings/apr_snprintf.c3
-rw-r--r--test/teststr.c19
3 files changed, 24 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index 0c504ed3c..2e82371e1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -142,6 +142,9 @@ Changes with APR 1.0
Changes with APR 0.9.5
+ *) Fix apr_snprintf() to respect precision for small floating point
+ numbers. PR 29621. [Artur Zaprzala <zybi talex.pl>]
+
*) Add command type APR_SHELLCMD_ENV for creating a process
which is started by the shell and which inherits the parent's
environment variables. [Jeff Trawick]
diff --git a/strings/apr_snprintf.c b/strings/apr_snprintf.c
index 73856a257..fa4cee3a0 100644
--- a/strings/apr_snprintf.c
+++ b/strings/apr_snprintf.c
@@ -132,11 +132,12 @@ static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign,
p1 = &buf[ndigits];
if (eflag == 0)
p1 += r2;
- *decpt = r2;
if (p1 < &buf[0]) {
+ *decpt = -ndigits;
buf[0] = '\0';
return (buf);
}
+ *decpt = r2;
while (p <= p1 && p < &buf[NDIG]) {
arg *= 10;
arg = modf(arg, &fj);
diff --git a/test/teststr.c b/test/teststr.c
index a046660cb..300a1b576 100644
--- a/test/teststr.c
+++ b/test/teststr.c
@@ -125,6 +125,24 @@ static void snprintf_0nonNULL(abts_case *tc, void *data)
ABTS_ASSERT(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0);
}
+static void snprintf_underflow(abts_case *tc, void *data)
+{
+ char buf[20];
+ int rv;
+
+ rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001);
+ ABTS_INT_EQUAL(tc, 4, rv);
+ ABTS_STR_EQUAL(tc, "0.00", buf);
+
+ rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001);
+ ABTS_INT_EQUAL(tc, 4, rv);
+ ABTS_STR_EQUAL(tc, "0.00", buf);
+
+ rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01);
+ ABTS_INT_EQUAL(tc, 4, rv);
+ ABTS_STR_EQUAL(tc, "0.01", buf);
+}
+
static void string_error(abts_case *tc, void *data)
{
char buf[128], *rv;
@@ -267,6 +285,7 @@ abts_suite *teststr(abts_suite *suite)
abts_run_test(suite, snprintf_0NULL, NULL);
abts_run_test(suite, snprintf_0nonNULL, NULL);
abts_run_test(suite, snprintf_noNULL, NULL);
+ abts_run_test(suite, snprintf_underflow, NULL);
abts_run_test(suite, test_strtok, NULL);
abts_run_test(suite, string_error, NULL);
abts_run_test(suite, string_long, NULL);