From 5cc964e88bc34721a1e718004c450ce20a9fb428 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 3 Apr 2016 16:04:20 +0200 Subject: [PATCH 1/6] lib557: allow too long lines Upstream-commit: adeaf95e2058a842badaddeae5501c0f5133dbea Signed-off-by: Kamil Dudka --- tests/libtest/lib557.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c index 2c0d5e0..2e72489 100644 --- a/tests/libtest/lib557.c +++ b/tests/libtest/lib557.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -453,6 +453,7 @@ static int test_unsigned_int_formatting(void) #elif (SIZEOF_INT == 8) + /* !checksrc! disable LONGLINE all */ i=1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = "18446744073709551615"; i++; ui_test[i].num = 0xFFFFFFFF00000000U; ui_test[i].expected = "18446744069414584320"; i++; ui_test[i].num = 0x00000000FFFFFFFFU; ui_test[i].expected = "4294967295"; @@ -1344,6 +1345,7 @@ static int test_curl_off_t_formatting(void) num_cofft_tests = i; #endif + /* !checksrc! enable LONGLINE */ for(i=1; i<=num_cofft_tests; i++) { @@ -1351,11 +1353,12 @@ static int test_curl_off_t_formatting(void) co_test[i].result[j] = 'X'; co_test[i].result[BUFSZ-1] = '\0'; - (void)curl_msprintf(co_test[i].result, "%" CURL_FORMAT_CURL_OFF_T, co_test[i].num); + (void)curl_msprintf(co_test[i].result, "%" CURL_FORMAT_CURL_OFF_T, + co_test[i].num); if(memcmp(co_test[i].result, - co_test[i].expected, - strlen(co_test[i].expected))) { + co_test[i].expected, + strlen(co_test[i].expected))) { printf("curl_off_t test #%.2d: Failed (Expected: %s Got: %s)\n", i, co_test[i].expected, co_test[i].result); failed++; -- 2.7.4 From 1e8206bd84b5bd2a41ea80631b6815d00c4ed813 Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Wed, 9 Mar 2016 02:59:05 -0500 Subject: [PATCH 2/6] mprintf: Fix processing of width and prec args Prior to this change a width arg could be erroneously output, and also width and precision args could not be used together without crashing. "%0*d%s", 2, 9, "foo" Before: "092" After: "09foo" "%*.*s", 5, 2, "foo" Before: crash After: " fo" Test 557 is updated to verify this and more Upstream-commit: 68701e51c1f794df59d9f70bcddbf714ee91b868 Signed-off-by: Kamil Dudka --- lib/mprintf.c | 60 +++++++++++++++++++++++++++++++++----------------- tests/data/test557 | 1 + tests/libtest/lib557.c | 49 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/lib/mprintf.c b/lib/mprintf.c index e47c10a..a110785 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -465,22 +465,24 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, if(flags & FLAGS_WIDTHPARAM) { /* we have the width specified from a parameter, so we make that parameter's info setup properly */ - vto[i].width = width - 1; - i = width - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + long k = width - 1; + vto[i].width = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; } if(flags & FLAGS_PRECPARAM) { /* we have the precision specified from a parameter, so we make that parameter's info setup properly */ - vto[i].precision = precision - 1; - i = precision - 1; - vto[i].type = FORMAT_WIDTH; - vto[i].flags = FLAGS_NEW; - vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + long k = precision - 1; + vto[i].precision = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; } *endpos++ = fmt + 1; /* end of this sequence */ } @@ -488,11 +490,15 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, /* Read the arg list parameters into our data list */ for(i=0; iflags & FLAGS_WIDTHPARAM) + if(p->flags & FLAGS_WIDTHPARAM) { width = (long)vto[p->width].data.num.as_signed; + param_num++; /* since the width is extracted from a parameter, we + must skip that to get to the next one properly */ + if(width < 0) { + /* "A negative field width is taken as a '-' flag followed by a + positive field width." */ + width = -width; + p->flags |= FLAGS_LEFT; + p->flags &= ~FLAGS_PAD_NIL; + } + } else width = p->width; /* pick up the specified precision */ if(p->flags & FLAGS_PRECPARAM) { prec = (long)vto[p->precision].data.num.as_signed; - param_num++; /* since the precision is extraced from a parameter, we + param_num++; /* since the precision is extracted from a parameter, we must skip that to get to the next one properly */ + if(prec < 0) + /* "A negative precision is taken as if the precision were + omitted." */ + prec = -1; } else if(p->flags & FLAGS_PREC) prec = p->precision; @@ -809,7 +829,7 @@ static int dprintf_formatf( else len = strlen(str); - width -= (long)len; + width -= (len > LONG_MAX) ? LONG_MAX : (long)len; if(p->flags & FLAGS_ALT) OUTCHAR('"'); diff --git a/tests/data/test557 b/tests/data/test557 index ee2793f..8d0944a 100644 --- a/tests/data/test557 +++ b/tests/data/test557 @@ -39,6 +39,7 @@ All curl_mprintf() signed int tests OK! All curl_mprintf() unsigned long tests OK! All curl_mprintf() signed long tests OK! All curl_mprintf() curl_off_t tests OK! +All curl_mprintf() strings tests OK! diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c index 2e72489..5bdb8ab 100644 --- a/tests/libtest/lib557.c +++ b/tests/libtest/lib557.c @@ -1374,6 +1374,53 @@ static int test_curl_off_t_formatting(void) return failed; } +static int string_check(char *buf, const char *buf2) +{ + if(strcmp(buf, buf2)) { + /* they shouldn't differ */ + printf("sprintf failed:\nwe '%s'\nsystem: '%s'\n", + buf, buf2); + return 1; + } + return 0; +} + +/* + * The output strings in this test need to have been verified with a system + * sprintf() before used here. + */ +static int test_string_formatting(void) +{ + int errors = 0; + char buf[256]; + curl_msnprintf(buf, sizeof(buf), "%0*d%s", 2, 9, "foo"); + errors += string_check(buf, "09foo"); + + curl_msnprintf(buf, sizeof(buf), "%*.*s", 5, 2, "foo"); + errors += string_check(buf, " fo"); + + curl_msnprintf(buf, sizeof(buf), "%*.*s", 2, 5, "foo"); + errors += string_check(buf, "foo"); + + curl_msnprintf(buf, sizeof(buf), "%*.*s", 0, 10, "foo"); + errors += string_check(buf, "foo"); + + curl_msnprintf(buf, sizeof(buf), "%-10s", "foo"); + errors += string_check(buf, "foo "); + + curl_msnprintf(buf, sizeof(buf), "%10s", "foo"); + errors += string_check(buf, " foo"); + + curl_msnprintf(buf, sizeof(buf), "%*.*s", -10, -10, "foo"); + errors += string_check(buf, "foo "); + + if(!errors) + printf("All curl_mprintf() strings tests OK!\n"); + else + printf("Some curl_mprintf() string tests Failed!\n"); + + return errors; +} int test(char *URL) { @@ -1394,6 +1441,8 @@ int test(char *URL) errors += test_curl_off_t_formatting(); + errors += test_string_formatting(); + if(errors) return TEST_ERR_MAJOR_BAD; else -- 2.7.4 From cf803e5d0041aaf77b95506a49895b7fa78c9541 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 8 Oct 2016 20:47:04 +0200 Subject: [PATCH 3/6] mprintf: return error on too many arguments 128 arguments should be enough for everyone Upstream-commit: 71588c9aef8112025c7525d20f57eb367a947344 Signed-off-by: Kamil Dudka --- lib/mprintf.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/mprintf.c b/lib/mprintf.c index a110785..f51fe6d 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -232,10 +232,12 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt) * Create an index with the type of each parameter entry and its * value (may vary in size) * + * Returns zero on success. + * ******************************************************************/ -static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, - va_list arglist) +static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, + va_list arglist) { char *fmt = (char *)format; int param_num = 0; @@ -398,6 +400,10 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, i = this_param - 1; + if((i < 0) || (i >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; + switch (*fmt) { case 'S': flags |= FLAGS_ALT; @@ -554,7 +560,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, } } - return max_param; + return 0; } @@ -587,7 +593,8 @@ static int dprintf_formatf( va_stack_t *p; /* Do the actual %-code parsing */ - dprintf_Pass1(format, vto, endpos, ap_save); + if(dprintf_Pass1(format, vto, endpos, ap_save)) + return -1; end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1() created for us */ @@ -994,7 +1001,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, info.max = maxlength; retcode = dprintf_formatf(&info, addbyter, format, ap_save); - if(info.max) { + if((retcode != -1) && info.max) { /* we terminate this with a zero byte */ if(info.max == info.length) /* we're at maximum, scrap the last letter */ -- 2.7.4 From 329eb5d7f36049fa294dac1f89125ae5dd41fd84 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 8 Oct 2016 20:47:44 +0200 Subject: [PATCH 4/6] test557: verify printf() with 128 and 129 arguments Upstream-commit: ac8a3149133fd3420770baf37190e47f5f7a46c7 Signed-off-by: Kamil Dudka --- tests/libtest/lib557.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c index 5bdb8ab..683ca08 100644 --- a/tests/libtest/lib557.c +++ b/tests/libtest/lib557.c @@ -1422,11 +1422,115 @@ static int test_string_formatting(void) return errors; } +static int test_weird_arguments(void) +{ + int errors = 0; + char buf[256]; + int rc; + + /* MAX_PARAMETERS is 128, try exact 128! */ + rc = curl_msnprintf(buf, sizeof(buf), + "%d%d%d%d%d%d%d%d%d%d" /* 10 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */ + "%d%d%d%d%d%d%d%d" /* 8 */ + , + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */ + 0, 1, 2, 3, 4, 5, 6, 7); /* 8 */ + + if(rc != 128) { + printf("curl_mprintf() returned %d and not 128!\n", rc); + errors++; + } + + errors += string_check(buf, + "0123456789" /* 10 */ + "0123456789" /* 10 1 */ + "0123456789" /* 10 2 */ + "0123456789" /* 10 3 */ + "0123456789" /* 10 4 */ + "0123456789" /* 10 5 */ + "0123456789" /* 10 6 */ + "0123456789" /* 10 7 */ + "0123456789" /* 10 8 */ + "0123456789" /* 10 9 */ + "0123456789" /* 10 10*/ + "0123456789" /* 10 11 */ + "01234567" /* 8 */ + ); + + /* MAX_PARAMETERS is 128, try more! */ + buf[0] = 0; + rc = curl_msnprintf(buf, sizeof(buf), + "%d%d%d%d%d%d%d%d%d%d" /* 10 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */ + "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */ + "%d%d%d%d%d%d%d%d%d" /* 9 */ + , + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8); /* 9 */ + + if(rc != -1) { + printf("curl_mprintf() returned %d and not -1!\n", rc); + errors++; + } + + errors += string_check(buf, ""); + + if(errors) + printf("Some curl_mprintf() weird arguments tests failed!\n"); + + return errors; +} + + int test(char *URL) { int errors = 0; (void)URL; /* not used */ + errors += test_weird_arguments(); + errors += test_unsigned_short_formatting(); errors += test_signed_short_formatting(); -- 2.7.4 From 7ad1cdfb256f7e1b84fc960a8ca1403cca5d930f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 8 Nov 2016 15:30:33 +0100 Subject: [PATCH 5/6] printf: fix ".*f" handling It would always use precision 1 instead of reading it from the argument list as intended. Reported-by: Ray Satiro Bug: #1113 Upstream-commit: 5dd1b65f79bc6dc75b752c53f3fa853b2a3b6d69 Signed-off-by: Kamil Dudka --- lib/mprintf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mprintf.c b/lib/mprintf.c index f51fe6d..07830db 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -308,7 +308,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, flags |= FLAGS_ALT; break; case '.': - flags |= FLAGS_PREC; if('*' == *fmt) { /* The precision is picked from a specified parameter */ -- 2.7.4 From 3162df571802b2c94d9969b6b269cd0d50c6650d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 8 Nov 2016 15:32:37 +0100 Subject: [PATCH 6/6] printf: fix floating point buffer overflow issues ... and add a bunch of floating point printf tests Upstream-commit: 3ab3c16db6a5674f53cf23d56512a405fde0b2c9 Signed-off-by: Kamil Dudka --- lib/mprintf.c | 20 +++++++- tests/data/test557 | 1 + tests/libtest/lib557.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 5 deletions(-) diff --git a/lib/mprintf.c b/lib/mprintf.c index e1ad537..e3a690b 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -97,7 +97,8 @@ # define mp_uintmax_t unsigned long #endif -#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ +#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should + fit negative DBL_MAX (317 letters) */ #define MAX_PARAMETERS 128 /* lame static limit */ #ifdef __AMIGA__ @@ -918,12 +919,25 @@ static int dprintf_formatf( *fptr = 0; if(width >= 0) { + if(width >= (long)sizeof(work)) + width = sizeof(work)-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, "%ld", width); fptr += len; left -= len; } if(prec >= 0) { + /* for each digit in the integer part, we can have one less + precision */ + size_t maxprec = sizeof(work) - 2; + double val = p->data.dnum; + while(val >= 10.0) { + val /= 10; + maxprec--; + } + + if(prec > (long)maxprec) + prec = maxprec-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, ".%ld", prec); fptr += len; @@ -943,7 +957,9 @@ static int dprintf_formatf( /* NOTE NOTE NOTE!! Not all sprintf implementations return number of output characters */ (sprintf)(work, formatbuf, p->data.dnum); - +#ifdef CURLDEBUG + assert(strlen(work) <= sizeof(work)); +#endif for(fptr=work; *fptr; fptr++) OUTCHAR(*fptr); } diff --git a/tests/data/test557 b/tests/data/test557 index 8d0944a..ad9350f 100644 --- a/tests/data/test557 +++ b/tests/data/test557 @@ -40,6 +40,7 @@ All curl_mprintf() unsigned long tests OK! All curl_mprintf() signed long tests OK! All curl_mprintf() curl_off_t tests OK! All curl_mprintf() strings tests OK! +All float strings tests OK! diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c index 683ca08..8c62a0e 100644 --- a/tests/libtest/lib557.c +++ b/tests/libtest/lib557.c @@ -1374,16 +1374,31 @@ static int test_curl_off_t_formatting(void) return failed; } -static int string_check(char *buf, const char *buf2) +static int _string_check(int linenumber, char *buf, const char *buf2) { if(strcmp(buf, buf2)) { /* they shouldn't differ */ - printf("sprintf failed:\nwe '%s'\nsystem: '%s'\n", - buf, buf2); + printf("sprintf line %d failed:\nwe '%s'\nsystem: '%s'\n", + linenumber, buf, buf2); return 1; } return 0; } +#define string_check(x,y) _string_check(__LINE__, x, y) + +static int _strlen_check(int linenumber, char *buf, size_t len) +{ + size_t buflen = strlen(buf); + if(len != buflen) { + /* they shouldn't differ */ + printf("sprintf strlen:%d failed:\nwe '%d'\nsystem: '%d'\n", + linenumber, buflen, len); + return 1; + } + return 0; +} + +#define strlen_check(x,y) _strlen_check(__LINE__, x, y) /* * The output strings in this test need to have been verified with a system @@ -1523,6 +1538,119 @@ static int test_weird_arguments(void) return errors; } +/* DBL_MAX value from Linux */ +#define MAXIMIZE -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 + +static int test_float_formatting(void) +{ + int errors = 0; + char buf[512]; /* larger than max float size */ + curl_msnprintf(buf, sizeof(buf), "%f", 9.0); + errors += string_check(buf, "9.000000"); + + curl_msnprintf(buf, sizeof(buf), "%.1f", 9.1); + errors += string_check(buf, "9.1"); + + curl_msnprintf(buf, sizeof(buf), "%.2f", 9.1); + errors += string_check(buf, "9.10"); + + curl_msnprintf(buf, sizeof(buf), "%.0f", 9.1); + errors += string_check(buf, "9"); + + curl_msnprintf(buf, sizeof(buf), "%0f", 9.1); + errors += string_check(buf, "9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%10f", 9.1); + errors += string_check(buf, " 9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%10.3f", 9.1); + errors += string_check(buf, " 9.100"); + + curl_msnprintf(buf, sizeof(buf), "%-10.3f", 9.1); + errors += string_check(buf, "9.100 "); + + curl_msnprintf(buf, sizeof(buf), "%-10.3f", 9.123456); + errors += string_check(buf, "9.123 "); + + curl_msnprintf(buf, sizeof(buf), "%.-2f", 9.1); + errors += string_check(buf, "9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%*f", 10, 9.1); + errors += string_check(buf, " 9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%*f", 3, 9.1); + errors += string_check(buf, "9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.2987654); + errors += string_check(buf, "9.298765"); + + curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.298765); + errors += string_check(buf, "9.298765"); + + curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.29876); + errors += string_check(buf, "9.298760"); + + curl_msnprintf(buf, sizeof(buf), "%.*f", 6, 9.2987654); + errors += string_check(buf, "9.298765"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 5, 9.2987654); + errors += string_check(buf, "9.29877"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 4, 9.2987654); + errors += string_check(buf, "9.2988"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 3, 9.2987654); + errors += string_check(buf, "9.299"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 2, 9.2987654); + errors += string_check(buf, "9.30"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 1, 9.2987654); + errors += string_check(buf, "9.3"); + curl_msnprintf(buf, sizeof(buf), "%.*f", 0, 9.2987654); + errors += string_check(buf, "9"); + + /* very large precisions easily turn into system specific outputs so we only + check the output buffer length here as we know the internal limit */ + + curl_msnprintf(buf, sizeof(buf), "%.*f", (1<<30), 9.2987654); + errors += strlen_check(buf, 325); + + curl_msnprintf(buf, sizeof(buf), "%10000.10000f", 9.2987654); + errors += strlen_check(buf, 325); + + curl_msnprintf(buf, sizeof(buf), "%240.10000f", + 123456789123456789123456789.2987654); + errors += strlen_check(buf, 325); + + /* 1<<31 turns negative (-2147483648) when used signed */ + curl_msnprintf(buf, sizeof(buf), "%*f", (1<<31), 9.1); + errors += string_check(buf, "9.100000"); + + /* curl_msnprintf() limits a single float output to 325 bytes maximum + width */ + curl_msnprintf(buf, sizeof(buf), "%*f", (1<<30), 9.1); + errors += string_check(buf, " 9.100000"); + curl_msnprintf(buf, sizeof(buf), "%100000f", 9.1); + errors += string_check(buf, " 9.100000"); + + curl_msnprintf(buf, sizeof(buf), "%f", MAXIMIZE); + errors += strlen_check(buf, 317); + + curl_msnprintf(buf, 2, "%f", MAXIMIZE); + errors += strlen_check(buf, 1); + curl_msnprintf(buf, 3, "%f", MAXIMIZE); + errors += strlen_check(buf, 2); + curl_msnprintf(buf, 4, "%f", MAXIMIZE); + errors += strlen_check(buf, 3); + curl_msnprintf(buf, 5, "%f", MAXIMIZE); + errors += strlen_check(buf, 4); + curl_msnprintf(buf, 6, "%f", MAXIMIZE); + errors += strlen_check(buf, 5); + + if(!errors) + printf("All float strings tests OK!\n"); + else + printf("test_float_formatting Failed!\n"); + + return errors; +} + int test(char *URL) { @@ -1547,6 +1675,8 @@ int test(char *URL) errors += test_string_formatting(); + errors += test_float_formatting(); + if(errors) return TEST_ERR_MAJOR_BAD; else -- 2.7.4