struct outsegment output[MAX_SEGMENTS];
struct va_input input[MAX_PARAMETERS];
- char work[BUFFSIZE];
+ char work[BUFFSIZE + 2];
/* 'workend' points to the final buffer byte position, but with an extra
byte as margin to avoid the (FALSE?) warning Coverity gives us
otherwise */
- char *workend = &work[sizeof(work) - 2];
+ char *workend = &work[BUFFSIZE - 2];
/* Parse the format string */
if(parsefmt(format, output, input, &ocount, &icount, ap_save))
if(width >= 0) {
size_t dlen;
- if(width >= (int)sizeof(work))
- width = sizeof(work)-1;
+ if(width >= BUFFSIZE)
+ width = BUFFSIZE - 1;
/* RECURSIVE USAGE */
dlen = (size_t)curl_msnprintf(fptr, left, "%d", width);
fptr += dlen;
if(prec >= 0) {
/* for each digit in the integer part, we can have one less
precision */
- size_t maxprec = sizeof(work) - 2;
+ int maxprec = BUFFSIZE - 1;
double val = iptr->val.dnum;
+ if(prec > maxprec)
+ prec = maxprec - 1;
if(width > 0 && prec <= width)
- maxprec -= (size_t)width;
+ maxprec -= width;
while(val >= 10.0) {
val /= 10;
maxprec--;
}
- if(prec > (int)maxprec)
- prec = (int)maxprec-1;
+ if(prec > maxprec)
+ prec = maxprec - 1;
if(prec < 0)
prec = 0;
/* RECURSIVE USAGE */
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
#ifdef HAVE_SNPRINTF
- (snprintf)(work, sizeof(work), formatbuf, iptr->val.dnum); /* NOLINT */
+ (snprintf)(work, BUFFSIZE, formatbuf, iptr->val.dnum); /* NOLINT */
#else
(sprintf)(work, formatbuf, iptr->val.dnum);
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
- DEBUGASSERT(strlen(work) <= sizeof(work));
+ DEBUGASSERT(strlen(work) < BUFFSIZE);
+#ifdef __MINGW32__
+ /* Work-around for a nasty bug seen with old-mingw and gcc 7.3.0 when it
+ writes one byte more than permitted. */
+ work[BUFFSIZE - 1] = 0;
+#endif
for(fptr = work; *fptr; fptr++)
OUTCHAR(*fptr);
break;
return errors;
}
+static int test_width_precision(void)
+{
+ /* 325 is max precision (and width) for a double */
+ char larger[1024];
+#define SPACE60 " "
+#define SPACE300 SPACE60 SPACE60 SPACE60 SPACE60 SPACE60
+#define OK325 SPACE300 " 0"
+
+ int rc;
+ int errors = 0;
+ rc = curl_msnprintf(larger, sizeof(larger), "%325.325f", 0.1);
+ if(rc != 325)
+ errors++;
+ errors += string_check(larger, OK325);
+
+ rc = curl_msnprintf(larger, sizeof(larger), "%326.326f", 0.1);
+ if(rc != 325)
+ errors++;
+ errors += string_check(larger, OK325);
+
+ rc = curl_msnprintf(larger, sizeof(larger), "%1000.1000f", 0.1);
+ if(rc != 325)
+ errors++;
+ errors += string_check(larger, OK325);
+
+ rc = curl_msnprintf(larger, sizeof(larger), "%324.324f", 0.1);
+ if(rc != 324)
+ errors++;
+ rc = curl_msnprintf(larger, sizeof(larger), "%324.0f", 0.1);
+ if(rc != 324)
+ errors++;
+ rc = curl_msnprintf(larger, sizeof(larger), "%0.324f", 0.1);
+ if(rc != 325)
+ errors++;
+
+ return errors;
+}
+
+
+
static int test_weird_arguments(void)
{
int errors = 0;
errors += string_check(buf, "");
+ errors += test_width_precision();
+
if(errors)
printf("Some curl_mprintf() weird arguments tests failed!\n");