smtp: use the upload buffer size for scratch buffer malloc
[platform/upstream/curl.git] / lib / mprintf.c
index f30db75..d2d91d7 100644 (file)
@@ -1,17 +1,23 @@
-/****************************************************************************
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
  *
- * $Id$
+ * Copyright (C) 1999 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
- *************************************************************************
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
  *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
  *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
- * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
  *
  * Purpose:
  *  A merge of Bjorn Reese's format() function and Daniel's dsprintf()
  *
  * If you ever want truly portable and good *printf() clones, the project that
  * took on from here is named 'Trio' and you find more details on the trio web
- * page at http://daniel.haxx.se/trio/
+ * page at https://daniel.haxx.se/projects/trio/
  */
 
+#include "curl_setup.h"
+#include <curl/mprintf.h>
 
-#include "setup.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-
-#include <curl/curl.h> /* for the curl_off_t type */
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
 
-#include <curl/mprintf.h>
+/*
+ * If SIZEOF_SIZE_T has not been defined, default to the size of long.
+ */
 
-#ifndef SIZEOF_LONG_DOUBLE
-#define SIZEOF_LONG_DOUBLE 0
+#ifdef HAVE_LONGLONG
+#  define LONG_LONG_TYPE long long
+#  define HAVE_LONG_LONG_TYPE
+#else
+#  if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+#    define LONG_LONG_TYPE __int64
+#    define HAVE_LONG_LONG_TYPE
+#  else
+#    undef LONG_LONG_TYPE
+#    undef HAVE_LONG_LONG_TYPE
+#  endif
 #endif
 
+/*
+ * Non-ANSI integer extensions
+ */
 
-/* The last #include file should be: */
-#ifdef CURLDEBUG
-#include "memdebug.h"
+#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
+    (defined(__WATCOMC__) && defined(__386__)) || \
+    (defined(__POCC__) && defined(_MSC_VER)) || \
+    (defined(_WIN32_WCE)) || \
+    (defined(__MINGW32__)) || \
+    (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
+#  define MP_HAVE_INT_EXTENSIONS
 #endif
 
-#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
-#define MAX_PARAMETERS 128 /* lame static limit */
+/*
+ * Max integer data types that mprintf.c is capable
+ */
 
-#undef TRUE
-#undef FALSE
-#undef BOOL
-#ifdef __cplusplus
-# define TRUE true
-# define FALSE false
-# define BOOL bool
+#ifdef HAVE_LONG_LONG_TYPE
+#  define mp_intmax_t LONG_LONG_TYPE
+#  define mp_uintmax_t unsigned LONG_LONG_TYPE
 #else
-# define TRUE  ((char)(1 == 1))
-# define FALSE ((char)(0 == 1))
-# define BOOL char
+#  define mp_intmax_t long
+#  define mp_uintmax_t unsigned long
 #endif
 
+#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__
+# undef FORMAT_INT
+#endif
 
 /* Lower-case digits.  */
 static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
@@ -75,10 +98,16 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 /* Upper-case digits.  */
 static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
-#define        OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1)
+#define OUTCHAR(x) \
+  do{ \
+    if(stream((unsigned char)(x), (FILE *)data) != -1) \
+      done++; \
+    else \
+     return done; /* return immediately on failure */ \
+  } WHILE_FALSE
 
 /* Data type to read from the arglist */
-typedef enum  {
+typedef enum {
   FORMAT_UNKNOWN = 0,
   FORMAT_STRING,
   FORMAT_PTR,
@@ -91,7 +120,7 @@ typedef enum  {
   FORMAT_WIDTH /* For internal use */
 } FormatType;
 
-/* convertion and display flags */
+/* conversion and display flags */
 enum {
   FLAGS_NEW        = 0,
   FLAGS_SPACE      = 1<<0,
@@ -119,19 +148,16 @@ enum {
 typedef struct {
   FormatType type;
   int flags;
-  int width;     /* width OR width parameter number */
-  int precision; /* precision OR precision parameter number */
+  long width;     /* width OR width parameter number */
+  long precision; /* precision OR precision parameter number */
   union {
     char *str;
     void *ptr;
-    long num;
-#ifdef HAVE_LONGLONG
-    long long lnum;
-#endif
+    union {
+      mp_intmax_t as_signed;
+      mp_uintmax_t as_unsigned;
+    } num;
     double dnum;
-#if SIZEOF_LONG_DOUBLE
-    long double ldnum;
-#endif
   } data;
 } va_stack_t;
 
@@ -145,14 +171,14 @@ struct asprintf {
   char *buffer; /* allocated buffer */
   size_t len;   /* length of string */
   size_t alloc; /* length of alloc */
+  int fail;     /* (!= 0) if an alloc has failed and thus
+                   the output is not the complete data */
 };
 
-int curl_msprintf(char *buffer, const char *format, ...);
-
-static int dprintf_DollarString(char *input, char **end)
+static long dprintf_DollarString(char *input, char **end)
 {
-  int number=0;
-  while(isdigit((int)*input)) {
+  int number = 0;
+  while(ISDIGIT(*input)) {
     number *= 10;
     number += *input-'0';
     input++;
@@ -164,136 +190,57 @@ static int dprintf_DollarString(char *input, char **end)
   return 0;
 }
 
-static BOOL dprintf_IsQualifierNoDollar(char c)
+static bool dprintf_IsQualifierNoDollar(const char *fmt)
 {
-  switch (c) {
+#if defined(MP_HAVE_INT_EXTENSIONS)
+  if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
+    return TRUE;
+  }
+#endif
+
+  switch(*fmt) {
   case '-': case '+': case ' ': case '#': case '.':
   case '0': case '1': case '2': case '3': case '4':
   case '5': case '6': case '7': case '8': case '9':
-  case 'h': case 'l': case 'L': case 'Z': case 'q':
+  case 'h': case 'l': case 'L': case 'z': case 'q':
   case '*': case 'O':
+#if defined(MP_HAVE_INT_EXTENSIONS)
+  case 'I':
+#endif
     return TRUE;
+
   default:
     return FALSE;
   }
 }
 
-#ifdef DPRINTF_DEBUG2
-int dprintf_Pass1Report(va_stack_t *vto, int max)
-{
-  int i;
-  char buffer[128];
-  int bit;
-  int flags;
-
-  for(i=0; i<max; i++) {
-    char *type;
-    switch(vto[i].type) {
-    case FORMAT_UNKNOWN:
-      type = "unknown";
-      break;
-    case FORMAT_STRING:
-      type ="string";
-      break;
-    case FORMAT_PTR:
-      type ="pointer";
-      break;
-    case FORMAT_INT:
-      type = "int";
-      break;
-    case FORMAT_LONG:
-      type = "long";
-      break;
-    case FORMAT_LONGLONG:
-      type = "long long";
-      break;
-    case FORMAT_DOUBLE:
-      type = "double";
-      break;
-    case FORMAT_LONGDOUBLE:
-      type = "long double";
-      break;      
-    }
-
-
-    buffer[0]=0;
-
-    for(bit=0; bit<31; bit++) {
-      flags = vto[i].flags & (1<<bit);
-
-      if(flags & FLAGS_SPACE)
-       strcat(buffer, "space ");
-      else if(flags & FLAGS_SHOWSIGN)
-       strcat(buffer, "plus ");
-      else if(flags & FLAGS_LEFT)
-       strcat(buffer, "left ");
-      else if(flags & FLAGS_ALT)
-       strcat(buffer, "alt ");
-      else if(flags & FLAGS_SHORT)
-       strcat(buffer, "short ");
-      else if(flags & FLAGS_LONG)
-       strcat(buffer, "long ");
-      else if(flags & FLAGS_LONGLONG)
-       strcat(buffer, "longlong ");
-      else if(flags & FLAGS_LONGDOUBLE)
-       strcat(buffer, "longdouble ");
-      else if(flags & FLAGS_PAD_NIL)
-       strcat(buffer, "padnil ");
-      else if(flags & FLAGS_UNSIGNED)
-       strcat(buffer, "unsigned ");
-      else if(flags & FLAGS_OCTAL)
-       strcat(buffer, "octal ");
-      else if(flags & FLAGS_HEX)
-       strcat(buffer, "hex ");
-      else if(flags & FLAGS_UPPER)
-       strcat(buffer, "upper ");
-      else if(flags & FLAGS_WIDTH)
-       strcat(buffer, "width ");
-      else if(flags & FLAGS_WIDTHPARAM)
-       strcat(buffer, "widthparam ");
-      else if(flags & FLAGS_PREC)
-       strcat(buffer, "precision ");
-      else if(flags & FLAGS_PRECPARAM)
-       strcat(buffer, "precparam ");
-      else if(flags & FLAGS_CHAR)
-       strcat(buffer, "char ");
-      else if(flags & FLAGS_FLOATE)
-       strcat(buffer, "floate ");
-      else if(flags & FLAGS_FLOATG)
-       strcat(buffer, "floatg ");
-    }
-    printf("REPORT: %d. %s [%s]\n", i, type, buffer);
-
-  }
-
-
-}
-#endif
-
 /******************************************************************
  *
  * Pass 1:
  * Create an index with the type of each parameter entry and its
  * value (may vary in size)
  *
+ * Returns zero on success.
+ *
  ******************************************************************/
 
-static int dprintf_Pass1(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 = format;
+  char *fmt = (char *)format;
   int param_num = 0;
-  int this_param;
-  int width;
-  int precision;
+  long this_param;
+  long width;
+  long precision;
   int flags;
-  int max_param=0;
-  int i;
-
-  while (*fmt) {
-    if (*fmt++ == '%') {
-      if (*fmt == '%') {
-       fmt++;
-       continue; /* while */
+  long max_param = 0;
+  long i;
+
+  while(*fmt) {
+    if(*fmt++ == '%') {
+      if(*fmt == '%') {
+        fmt++;
+        continue; /* while */
       }
 
       flags = FLAGS_NEW;
@@ -301,14 +248,14 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
       /* Handle the positional case (N$) */
 
       param_num++;
-      
+
       this_param = dprintf_DollarString(fmt, &fmt);
-      if (0 == this_param)
-       /* we got no positional, get the next counter */
-       this_param = param_num;
+      if(0 == this_param)
+        /* we got no positional, get the next counter */
+        this_param = param_num;
 
-      if (this_param > max_param)
-       max_param = this_param;
+      if(this_param > max_param)
+        max_param = this_param;
 
       /*
        * The parameter with number 'i' should be used. Next, we need
@@ -321,254 +268,296 @@ static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list a
 
       /* Handle the flags */
 
-      while (dprintf_IsQualifierNoDollar(*fmt)) {
-       switch (*fmt++) {
-       case ' ':
-         flags |= FLAGS_SPACE;
-         break;
-       case '+':
-         flags |= FLAGS_SHOWSIGN;
-         break;
-       case '-':
-         flags |= FLAGS_LEFT;
-         flags &= ~FLAGS_PAD_NIL;
-         break;
-       case '#':
-         flags |= FLAGS_ALT;
-         break;
-       case '.':
-         flags |= FLAGS_PREC;
-         if ('*' == *fmt) {
-           /* The precision is picked from a specified parameter */
-
-           flags |= FLAGS_PRECPARAM;
-           fmt++;
-           param_num++;
-
-           i = dprintf_DollarString(fmt, &fmt);
-           if (i)
-             precision = i;
-           else
-             precision = param_num;
-
-           if (precision > max_param)
-             max_param = precision;
-                 }
-         else {
-           flags |= FLAGS_PREC;
-           precision = strtol(fmt, &fmt, 10);
-         }
-         break;
-       case 'h':
-         flags |= FLAGS_SHORT;
-         break;
-       case 'l':
-         if (flags & FLAGS_LONG)
-           flags |= FLAGS_LONGLONG;
-         else
-           flags |= FLAGS_LONG;
-         break;
-       case 'L':
-         flags |= FLAGS_LONGDOUBLE;
-         break;
-       case 'q':
-         flags |= FLAGS_LONGLONG;
-         break;
-#if 0
-       case 'Z':
-         if (sizeof(size_t) > sizeof(unsigned long int))
-           flags |= FLAGS_LONGLONG;
-         if (sizeof(size_t) > sizeof(unsigned int))
-           flags |= FLAGS_LONG;
-         break;
+      while(dprintf_IsQualifierNoDollar(fmt)) {
+#if defined(MP_HAVE_INT_EXTENSIONS)
+        if(!strncmp(fmt, "I32", 3)) {
+          flags |= FLAGS_LONG;
+          fmt += 3;
+        }
+        else if(!strncmp(fmt, "I64", 3)) {
+          flags |= FLAGS_LONGLONG;
+          fmt += 3;
+        }
+        else
+#endif
+
+        switch(*fmt++) {
+        case ' ':
+          flags |= FLAGS_SPACE;
+          break;
+        case '+':
+          flags |= FLAGS_SHOWSIGN;
+          break;
+        case '-':
+          flags |= FLAGS_LEFT;
+          flags &= ~FLAGS_PAD_NIL;
+          break;
+        case '#':
+          flags |= FLAGS_ALT;
+          break;
+        case '.':
+          if('*' == *fmt) {
+            /* The precision is picked from a specified parameter */
+
+            flags |= FLAGS_PRECPARAM;
+            fmt++;
+            param_num++;
+
+            i = dprintf_DollarString(fmt, &fmt);
+            if(i)
+              precision = i;
+            else
+              precision = param_num;
+
+            if(precision > max_param)
+              max_param = precision;
+          }
+          else {
+            flags |= FLAGS_PREC;
+            precision = strtol(fmt, &fmt, 10);
+          }
+          break;
+        case 'h':
+          flags |= FLAGS_SHORT;
+          break;
+#if defined(MP_HAVE_INT_EXTENSIONS)
+        case 'I':
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+          flags |= FLAGS_LONGLONG;
+#else
+          flags |= FLAGS_LONG;
+#endif
+          break;
+#endif
+        case 'l':
+          if(flags & FLAGS_LONG)
+            flags |= FLAGS_LONGLONG;
+          else
+            flags |= FLAGS_LONG;
+          break;
+        case 'L':
+          flags |= FLAGS_LONGDOUBLE;
+          break;
+        case 'q':
+          flags |= FLAGS_LONGLONG;
+          break;
+        case 'z':
+          /* the code below generates a warning if -Wunreachable-code is
+             used */
+#if (SIZEOF_SIZE_T > SIZEOF_LONG)
+          flags |= FLAGS_LONGLONG;
+#else
+          flags |= FLAGS_LONG;
 #endif
-       case 'O':
-#if SIZEOF_CURL_OFF_T > 4
+          break;
+        case 'O':
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
           flags |= FLAGS_LONGLONG;
 #else
           flags |= FLAGS_LONG;
 #endif
-         break;
-       case '0':
-         if (!(flags & FLAGS_LEFT))
-           flags |= FLAGS_PAD_NIL;
-         /* FALLTHROUGH */
-       case '1': case '2': case '3': case '4':
-       case '5': case '6': case '7': case '8': case '9':
-         flags |= FLAGS_WIDTH;
-         width = strtol(fmt-1, &fmt, 10);
-         break;
-       case '*':  /* Special case */
-         flags |= FLAGS_WIDTHPARAM;
-         param_num++;
-         
-         i = dprintf_DollarString(fmt, &fmt);
-         if(i)
-           width = i;
-         else
-           width = param_num;
-         if(width > max_param)
-           max_param=width;
-         break;
-       default:
-         break;
-       }
+          break;
+        case '0':
+          if(!(flags & FLAGS_LEFT))
+            flags |= FLAGS_PAD_NIL;
+          /* FALLTHROUGH */
+        case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+          flags |= FLAGS_WIDTH;
+          width = strtol(fmt-1, &fmt, 10);
+          break;
+        case '*':  /* Special case */
+          flags |= FLAGS_WIDTHPARAM;
+          param_num++;
+
+          i = dprintf_DollarString(fmt, &fmt);
+          if(i)
+            width = i;
+          else
+            width = param_num;
+          if(width > max_param)
+            max_param = width;
+          break;
+        default:
+          break;
+        }
       } /* switch */
 
       /* Handle the specifier */
 
       i = this_param - 1;
 
+      if((i < 0) || (i >= MAX_PARAMETERS))
+        /* out of allowed range */
+        return 1;
+
       switch (*fmt) {
       case 'S':
-       flags |= FLAGS_ALT;
-       /* FALLTHROUGH */
+        flags |= FLAGS_ALT;
+        /* FALLTHROUGH */
       case 's':
-       vto[i].type = FORMAT_STRING;
-       break;
+        vto[i].type = FORMAT_STRING;
+        break;
       case 'n':
-       vto[i].type = FORMAT_INTPTR;
-       break;
+        vto[i].type = FORMAT_INTPTR;
+        break;
       case 'p':
-       vto[i].type = FORMAT_PTR;
-       break;
+        vto[i].type = FORMAT_PTR;
+        break;
       case 'd': case 'i':
-       vto[i].type = FORMAT_INT;
-       break;
+        vto[i].type = FORMAT_INT;
+        break;
       case 'u':
-       vto[i].type = FORMAT_INT;
-       flags |= FLAGS_UNSIGNED;
-       break;
+        vto[i].type = FORMAT_INT;
+        flags |= FLAGS_UNSIGNED;
+        break;
       case 'o':
-       vto[i].type = FORMAT_INT;
-       flags |= FLAGS_OCTAL;
-       break;
+        vto[i].type = FORMAT_INT;
+        flags |= FLAGS_OCTAL;
+        break;
       case 'x':
-       vto[i].type = FORMAT_INT;
-       flags |= FLAGS_HEX;
-       break;
+        vto[i].type = FORMAT_INT;
+        flags |= FLAGS_HEX|FLAGS_UNSIGNED;
+        break;
       case 'X':
-       vto[i].type = FORMAT_INT;
-       flags |= FLAGS_HEX|FLAGS_UPPER;
-       break;
+        vto[i].type = FORMAT_INT;
+        flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
+        break;
       case 'c':
-       vto[i].type = FORMAT_INT;
-       flags |= FLAGS_CHAR;
-       break;  
+        vto[i].type = FORMAT_INT;
+        flags |= FLAGS_CHAR;
+        break;
       case 'f':
-       vto[i].type = FORMAT_DOUBLE;
-       break;
-      case 'e': case 'E':
-       vto[i].type = FORMAT_DOUBLE;
-       flags |= FLAGS_FLOATE| (('E' == *fmt)?FLAGS_UPPER:0);
-       break;
-      case 'g': case 'G':
-       vto[i].type = FORMAT_DOUBLE;
-       flags |= FLAGS_FLOATG| (('G' == *fmt)?FLAGS_UPPER:0);
-       break;  
+        vto[i].type = FORMAT_DOUBLE;
+        break;
+      case 'e':
+        vto[i].type = FORMAT_DOUBLE;
+        flags |= FLAGS_FLOATE;
+        break;
+      case 'E':
+        vto[i].type = FORMAT_DOUBLE;
+        flags |= FLAGS_FLOATE|FLAGS_UPPER;
+        break;
+      case 'g':
+        vto[i].type = FORMAT_DOUBLE;
+        flags |= FLAGS_FLOATG;
+        break;
+      case 'G':
+        vto[i].type = FORMAT_DOUBLE;
+        flags |= FLAGS_FLOATG|FLAGS_UPPER;
+        break;
       default:
-       vto[i].type = FORMAT_UNKNOWN;
-       break;
+        vto[i].type = FORMAT_UNKNOWN;
+        break;
       } /* switch */
 
       vto[i].flags = flags;
       vto[i].width = width;
       vto[i].precision = precision;
-      
-      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! */    
+
+      if(flags & FLAGS_WIDTHPARAM) {
+        /* we have the width specified from a parameter, so we make that
+           parameter's info setup properly */
+        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! */
+      if(flags & FLAGS_PRECPARAM) {
+        /* we have the precision specified from a parameter, so we make that
+           parameter's info setup properly */
+        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 */
     }
   }
 
-#ifdef DPRINTF_DEBUG2
-  dprintf_Pass1Report(vto, max_param);
-#endif
-
   /* Read the arg list parameters into our data list */
-  for (i=0; i<max_param; i++) {
-    if ((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH))
-      {
-       /* Width/precision arguments must be read before the main argument
-        * they are attached to
-        */
-       vto[i + 1].data.num = va_arg(arglist, int);
-      }
+  for(i = 0; i<max_param; i++) {
+    /* Width/precision arguments must be read before the main argument
+       they are attached to */
+    if(vto[i].flags & FLAGS_WIDTHPARAM) {
+      vto[vto[i].width].data.num.as_signed =
+        (mp_intmax_t)va_arg(arglist, int);
+    }
+    if(vto[i].flags & FLAGS_PRECPARAM) {
+      vto[vto[i].precision].data.num.as_signed =
+        (mp_intmax_t)va_arg(arglist, int);
+    }
 
-    switch (vto[i].type)
-      {
-      case FORMAT_STRING:
-       vto[i].data.str = va_arg(arglist, char *);
-       break;
-       
-      case FORMAT_INTPTR:
-      case FORMAT_UNKNOWN:
-      case FORMAT_PTR:
-       vto[i].data.ptr = va_arg(arglist, void *);
-       break;
-       
-      case FORMAT_INT:
-#ifdef HAVE_LONGLONG
-       if(vto[i].flags & FLAGS_LONGLONG)
-         vto[i].data.lnum = va_arg(arglist, long long);
-       else
-#endif
-         if(vto[i].flags & FLAGS_LONG)
-           vto[i].data.num = va_arg(arglist, long);
-       else
-         vto[i].data.num = va_arg(arglist, int);
-       break;
-       
-      case FORMAT_DOUBLE:
-#if SIZEOF_LONG_DOUBLE
-       if(vto[i].flags & FLAGS_LONG)
-         vto[i].data.ldnum = va_arg(arglist, long double);
-       else
+    switch(vto[i].type) {
+    case FORMAT_STRING:
+      vto[i].data.str = va_arg(arglist, char *);
+      break;
+
+    case FORMAT_INTPTR:
+    case FORMAT_UNKNOWN:
+    case FORMAT_PTR:
+      vto[i].data.ptr = va_arg(arglist, void *);
+      break;
+
+    case FORMAT_INT:
+#ifdef HAVE_LONG_LONG_TYPE
+      if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
+        vto[i].data.num.as_unsigned =
+          (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
+      else if(vto[i].flags & FLAGS_LONGLONG)
+        vto[i].data.num.as_signed =
+          (mp_intmax_t)va_arg(arglist, mp_intmax_t);
+      else
 #endif
-         vto[i].data.dnum = va_arg(arglist, double);
-       break;
-       
-      case FORMAT_WIDTH:
-       /* Argument has been read. Silently convert it into an integer
-        * for later use
-        */
-       vto[i].type = FORMAT_INT;
-       break;
-       
-      default:
-       break;
+      {
+        if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
+          vto[i].data.num.as_unsigned =
+            (mp_uintmax_t)va_arg(arglist, unsigned long);
+        else if(vto[i].flags & FLAGS_LONG)
+          vto[i].data.num.as_signed =
+            (mp_intmax_t)va_arg(arglist, long);
+        else if(vto[i].flags & FLAGS_UNSIGNED)
+          vto[i].data.num.as_unsigned =
+            (mp_uintmax_t)va_arg(arglist, unsigned int);
+        else
+          vto[i].data.num.as_signed =
+            (mp_intmax_t)va_arg(arglist, int);
       }
+      break;
+
+    case FORMAT_DOUBLE:
+      vto[i].data.dnum = va_arg(arglist, double);
+      break;
+
+    case FORMAT_WIDTH:
+      /* Argument has been read. Silently convert it into an integer
+       * for later use
+       */
+      vto[i].type = FORMAT_INT;
+      break;
+
+    default:
+      break;
+    }
   }
 
-  return max_param;
+  return 0;
 
 }
 
 static int dprintf_formatf(
-             void *data, /* untouched by format(), just sent to the
-                            stream() function in the first argument */
-            int (*stream)(int, FILE *), /* function pointer called for each
-                                           output character */
-            const char *format,    /* %-formatted string */
-            va_list ap_save) /* list of parameters */
+  void *data, /* untouched by format(), just sent to the stream() function in
+                 the second argument */
+  /* function pointer called for each output character */
+  int (*stream)(int, FILE *),
+  const char *format,    /* %-formatted string */
+  va_list ap_save) /* list of parameters */
 {
   /* Base-36 digits for numbers.  */
   const char *digits = lower_digits;
@@ -577,10 +566,10 @@ static int dprintf_formatf(
   char *f;
 
   /* Number of characters written.  */
-  register size_t done = 0;
+  int done = 0;
 
   long param; /* current parameter to read */
-  long param_num=0; /* parameter counter */
+  long param_num = 0; /* parameter counter */
 
   va_stack_t vto[MAX_PARAMETERS];
   char *endpos[MAX_PARAMETERS];
@@ -590,364 +579,393 @@ static int dprintf_formatf(
 
   va_stack_t *p;
 
+  /* '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];
+
   /* Do the actual %-code parsing */
-  dprintf_Pass1((char *)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 */
-  
+
   f = (char *)format;
-  while (*f != '\0') {
+  while(*f != '\0') {
     /* Format spec modifiers.  */
-    char alt;
-    
+    int is_alt;
+
     /* Width of a field.  */
-    register long width;
+    long width;
+
     /* Precision of a field.  */
     long prec;
-    
+
     /* Decimal integer is negative.  */
-    char is_neg;
-    
+    int is_neg;
+
     /* Base of a number to be written.  */
-    long base;
+    unsigned long base;
 
     /* Integral values to be written.  */
-#ifdef HAVE_LONGLONG
-    unsigned long long num;
-#else
-    unsigned long num;
-#endif
-    long signed_num;
-    
-    if (*f != '%') {
+    mp_uintmax_t num;
+
+    /* Used to convert negative in positive.  */
+    mp_intmax_t signed_num;
+
+    char *w;
+
+    if(*f != '%') {
       /* This isn't a format spec, so write everything out until the next one
-        OR end of string is reached.  */
+         OR end of string is reached.  */
       do {
-       OUTCHAR(*f);
+        OUTCHAR(*f);
       } while(*++f && ('%' != *f));
       continue;
     }
-    
+
     ++f;
-    
+
     /* Check for "%%".  Note that although the ANSI standard lists
        '%' as a conversion specifier, it says "The complete format
        specification shall be `%%'," so we can avoid all the width
        and precision processing.  */
-    if (*f == '%') {
+    if(*f == '%') {
       ++f;
       OUTCHAR('%');
       continue;
     }
 
-    /* If this is a positional parameter, the position must follow imediately
+    /* If this is a positional parameter, the position must follow immediately
        after the %, thus create a %<num>$ sequence */
-    param=dprintf_DollarString(f, &f);
+    param = dprintf_DollarString(f, &f);
 
     if(!param)
       param = param_num;
     else
       --param;
-    
+
     param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
-                   third %s will pick the 3rd argument */
+                    third %s will pick the 3rd argument */
 
     p = &vto[param];
 
     /* pick up the specified width */
-    if(p->flags & FLAGS_WIDTHPARAM)
-      width = vto[p->width].data.num;
+    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 = vto[p->precision].data.num;
+    if(p->flags & FLAGS_PRECPARAM) {
+      prec = (long)vto[p->precision].data.num.as_signed;
+      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;
     else
       prec = -1;
 
-    alt = p->flags & FLAGS_ALT;
-    
-    switch (p->type) {
+    is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
+
+    switch(p->type) {
     case FORMAT_INT:
-      num = p->data.num;
+      num = p->data.num.as_unsigned;
       if(p->flags & FLAGS_CHAR) {
-       /* Character.  */
-       if (!(p->flags & FLAGS_LEFT))
-         while (--width > 0)
-           OUTCHAR(' ');
-       OUTCHAR((char) num);
-       if (p->flags & FLAGS_LEFT)
-         while (--width > 0)
-           OUTCHAR(' ');
-       break;
-      }
-      if(p->flags & FLAGS_UNSIGNED) {
-       /* Decimal unsigned integer.  */
-       base = 10;
-       goto unsigned_number;
+        /* Character.  */
+        if(!(p->flags & FLAGS_LEFT))
+          while(--width > 0)
+            OUTCHAR(' ');
+        OUTCHAR((char) num);
+        if(p->flags & FLAGS_LEFT)
+          while(--width > 0)
+            OUTCHAR(' ');
+        break;
       }
       if(p->flags & FLAGS_OCTAL) {
-       /* Octal unsigned integer.  */
-       base = 8;
-       goto unsigned_number;
+        /* Octal unsigned integer.  */
+        base = 8;
+        goto unsigned_number;
       }
-      if(p->flags & FLAGS_HEX) {
-       /* Hexadecimal unsigned integer.  */
+      else if(p->flags & FLAGS_HEX) {
+        /* Hexadecimal unsigned integer.  */
 
-       digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
-       base = 16;
-       goto unsigned_number;
+        digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+        base = 16;
+        goto unsigned_number;
+      }
+      else if(p->flags & FLAGS_UNSIGNED) {
+        /* Decimal unsigned integer.  */
+        base = 10;
+        goto unsigned_number;
       }
 
       /* Decimal integer.  */
       base = 10;
 
-#ifdef HAVE_LONGLONG
-      if(p->flags & FLAGS_LONGLONG) {
-        /* long long */
-       is_neg = p->data.lnum < 0;
-       num = is_neg ? (- p->data.lnum) : p->data.lnum;
-      }
-      else
-#endif
-      {
-       signed_num = (long) num;
-      
-       is_neg = signed_num < 0;
-       num = is_neg ? (- signed_num) : signed_num;
+      is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
+      if(is_neg) {
+        /* signed_num might fail to hold absolute negative minimum by 1 */
+        signed_num = p->data.num.as_signed + (mp_intmax_t)1;
+        signed_num = -signed_num;
+        num = (mp_uintmax_t)signed_num;
+        num += (mp_uintmax_t)1;
       }
+
       goto number;
-      
-    unsigned_number:;
+
+      unsigned_number:
       /* Unsigned number of base BASE.  */
       is_neg = 0;
-      
-    number:;
+
+      number:
       /* Number of base BASE.  */
-      {
-       char *workend = &work[sizeof(work) - 1];
-       register char *w;
-       
-       /* Supply a default precision if none was given.  */
-       if (prec == -1)
-         prec = 1;
-       
-       /* Put the number in WORK.  */
-       w = workend;
-       while (num > 0) {
-         *w-- = digits[num % base];
-         num /= base;
-       }
-       width -= workend - w;
-       prec -= workend - w;
-       
-       if (alt && base == 8 && prec <= 0) {
-         *w-- = '0';
-         --width;
-       }
-       
-       if (prec > 0) {
-         width -= prec;
-         while (prec-- > 0)
-           *w-- = '0';
-       }
-       
-       if (alt && base == 16)
-         width -= 2;
-       
-       if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
-         --width;
-       
-       if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
-         while (width-- > 0)
-           OUTCHAR(' ');
-       
-       if (is_neg)
-         OUTCHAR('-');
-       else if (p->flags & FLAGS_SHOWSIGN)
-         OUTCHAR('+');
-       else if (p->flags & FLAGS_SPACE)
-         OUTCHAR(' ');
-       
-       if (alt && base == 16) {
-         OUTCHAR('0');
-         if(p->flags & FLAGS_UPPER)
-           OUTCHAR('X');
-         else
-           OUTCHAR('x');
-       }
-
-       if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
-         while (width-- > 0)
-           OUTCHAR('0');
-       
-       /* Write the number.  */
-       while (++w <= workend) {
-         OUTCHAR(*w);
-       }
-       
-       if (p->flags & FLAGS_LEFT)
-         while (width-- > 0)
-           OUTCHAR(' ');
+
+      /* Supply a default precision if none was given.  */
+      if(prec == -1)
+        prec = 1;
+
+      /* Put the number in WORK.  */
+      w = workend;
+      while(num > 0) {
+        *w-- = digits[num % base];
+        num /= base;
+      }
+      width -= (long)(workend - w);
+      prec -= (long)(workend - w);
+
+      if(is_alt && base == 8 && prec <= 0) {
+        *w-- = '0';
+        --width;
+      }
+
+      if(prec > 0) {
+        width -= prec;
+        while(prec-- > 0)
+          *w-- = '0';
+      }
+
+      if(is_alt && base == 16)
+        width -= 2;
+
+      if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
+        --width;
+
+      if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
+        while(width-- > 0)
+          OUTCHAR(' ');
+
+      if(is_neg)
+        OUTCHAR('-');
+      else if(p->flags & FLAGS_SHOWSIGN)
+        OUTCHAR('+');
+      else if(p->flags & FLAGS_SPACE)
+        OUTCHAR(' ');
+
+      if(is_alt && base == 16) {
+        OUTCHAR('0');
+        if(p->flags & FLAGS_UPPER)
+          OUTCHAR('X');
+        else
+          OUTCHAR('x');
+      }
+
+      if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
+        while(width-- > 0)
+          OUTCHAR('0');
+
+      /* Write the number.  */
+      while(++w <= workend) {
+        OUTCHAR(*w);
       }
+
+      if(p->flags & FLAGS_LEFT)
+        while(width-- > 0)
+          OUTCHAR(' ');
       break;
-      
+
     case FORMAT_STRING:
-           /* String.  */
+            /* String.  */
       {
-       static char null[] = "(nil)";
-       char *str;
-       size_t len;
-       
-       str = (char *) p->data.str;
-       if ( str == NULL) {
-         /* Write null[] if there's space.  */
-         if (prec == -1 || prec >= (long) sizeof(null) - 1) {
-           str = null;
-           len = sizeof(null) - 1;
-           /* Disable quotes around (nil) */
-           p->flags &= (~FLAGS_ALT);
-         }
-         else {
-           str = (char *)"";
-           len = 0;
-         }
-       }
-       else
-         len = strlen(str);
-       
-       if (prec != -1 && (size_t) prec < len)
-         len = prec;
-       width -= len;
-
-       if (p->flags & FLAGS_ALT)
-         OUTCHAR('"');
-
-       if (!(p->flags&FLAGS_LEFT))
-         while (width-- > 0)
-           OUTCHAR(' ');
-       
-       while (len-- > 0)
-         OUTCHAR(*str++);
-       if (p->flags&FLAGS_LEFT)
-         while (width-- > 0)
-           OUTCHAR(' ');
-
-       if (p->flags & FLAGS_ALT)
-         OUTCHAR('"');
+        static const char null[] = "(nil)";
+        const char *str;
+        size_t len;
+
+        str = (char *) p->data.str;
+        if(str == NULL) {
+          /* Write null[] if there's space.  */
+          if(prec == -1 || prec >= (long) sizeof(null) - 1) {
+            str = null;
+            len = sizeof(null) - 1;
+            /* Disable quotes around (nil) */
+            p->flags &= (~FLAGS_ALT);
+          }
+          else {
+            str = "";
+            len = 0;
+          }
+        }
+        else if(prec != -1)
+          len = (size_t)prec;
+        else
+          len = strlen(str);
+
+        width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
+
+        if(p->flags & FLAGS_ALT)
+          OUTCHAR('"');
+
+        if(!(p->flags&FLAGS_LEFT))
+          while(width-- > 0)
+            OUTCHAR(' ');
+
+        while((len-- > 0) && *str)
+          OUTCHAR(*str++);
+        if(p->flags&FLAGS_LEFT)
+          while(width-- > 0)
+            OUTCHAR(' ');
+
+        if(p->flags & FLAGS_ALT)
+          OUTCHAR('"');
       }
       break;
-      
+
     case FORMAT_PTR:
       /* Generic pointer.  */
       {
-       void *ptr;
-       ptr = (void *) p->data.ptr;
-       if (ptr != NULL) {
-         /* If the pointer is not NULL, write it as a %#x spec.  */
-         base = 16;
-         digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
-         alt = 1;
-         num = (unsigned long) ptr;
-         is_neg = 0;
-         goto number;
-       }
-       else {
-         /* Write "(nil)" for a nil pointer.  */
-         static char strnil[] = "(nil)";
-         register char *point;
-         
-         width -= sizeof(strnil) - 1;
-         if (p->flags & FLAGS_LEFT)
-           while (width-- > 0)
-             OUTCHAR(' ');
-         for (point = strnil; *point != '\0'; ++point)
-           OUTCHAR(*point);
-         if (! (p->flags & FLAGS_LEFT))
-           while (width-- > 0)
-             OUTCHAR(' ');
-       }
+        void *ptr;
+        ptr = (void *) p->data.ptr;
+        if(ptr != NULL) {
+          /* If the pointer is not NULL, write it as a %#x spec.  */
+          base = 16;
+          digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+          is_alt = 1;
+          num = (size_t) ptr;
+          is_neg = 0;
+          goto number;
+        }
+        else {
+          /* Write "(nil)" for a nil pointer.  */
+          static const char strnil[] = "(nil)";
+          const char *point;
+
+          width -= (long)(sizeof(strnil) - 1);
+          if(p->flags & FLAGS_LEFT)
+            while(width-- > 0)
+              OUTCHAR(' ');
+          for(point = strnil; *point != '\0'; ++point)
+            OUTCHAR(*point);
+          if(! (p->flags & FLAGS_LEFT))
+            while(width-- > 0)
+              OUTCHAR(' ');
+        }
       }
       break;
 
     case FORMAT_DOUBLE:
       {
-       char formatbuf[32]="%";
-       char *fptr;
-       
-       width = -1;
-       if (p->flags & FLAGS_WIDTH)
-         width = p->width;
-       else if (p->flags & FLAGS_WIDTHPARAM)
-         width = vto[p->width].data.num;
-
-       prec = -1;
-       if (p->flags & FLAGS_PREC)
-         prec = p->precision;
-       else if (p->flags & FLAGS_PRECPARAM)
-         prec = vto[p->precision].data.num;
-
-       if (p->flags & FLAGS_LEFT)
-         strcat(formatbuf, "-");
-       if (p->flags & FLAGS_SHOWSIGN)
-         strcat(formatbuf, "+");
-       if (p->flags & FLAGS_SPACE)
-         strcat(formatbuf, " ");
-       if (p->flags & FLAGS_ALT)
-         strcat(formatbuf, "#");
-
-       fptr=&formatbuf[strlen(formatbuf)];
-
-       if(width >= 0) {
-         /* RECURSIVE USAGE */
-         fptr += curl_msprintf(fptr, "%d", width);
-       }
-       if(prec >= 0) {
-         /* RECURSIVE USAGE */
-         fptr += curl_msprintf(fptr, ".%d", prec);
-       }
-       if (p->flags & FLAGS_LONG)
-         strcat(fptr, "l");
-
-       if (p->flags & FLAGS_FLOATE)
-         strcat(fptr, p->flags&FLAGS_UPPER?"E":"e");
-       else if (p->flags & FLAGS_FLOATG)
-         strcat(fptr, (p->flags & FLAGS_UPPER) ? "G" : "g");
-       else
-         strcat(fptr, "f");
-
-       /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number
-          of output characters */
-#if SIZEOF_LONG_DOUBLE
-       if (p->flags & FLAGS_LONG)
-         /* This is for support of the 'long double' type */
-         (sprintf)(work, formatbuf, p->data.ldnum);
-       else
-#endif
-         (sprintf)(work, formatbuf, p->data.dnum);
-
-       for(fptr=work; *fptr; fptr++)
-         OUTCHAR(*fptr);
+        char formatbuf[32]="%";
+        char *fptr = &formatbuf[1];
+        size_t left = sizeof(formatbuf)-strlen(formatbuf);
+        int len;
+
+        width = -1;
+        if(p->flags & FLAGS_WIDTH)
+          width = p->width;
+        else if(p->flags & FLAGS_WIDTHPARAM)
+          width = (long)vto[p->width].data.num.as_signed;
+
+        prec = -1;
+        if(p->flags & FLAGS_PREC)
+          prec = p->precision;
+        else if(p->flags & FLAGS_PRECPARAM)
+          prec = (long)vto[p->precision].data.num.as_signed;
+
+        if(p->flags & FLAGS_LEFT)
+          *fptr++ = '-';
+        if(p->flags & FLAGS_SHOWSIGN)
+          *fptr++ = '+';
+        if(p->flags & FLAGS_SPACE)
+          *fptr++ = ' ';
+        if(p->flags & FLAGS_ALT)
+          *fptr++ = '#';
+
+        *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 = (long)maxprec-1;
+          /* RECURSIVE USAGE */
+          len = curl_msnprintf(fptr, left, ".%ld", prec);
+          fptr += len;
+        }
+        if(p->flags & FLAGS_LONG)
+          *fptr++ = 'l';
+
+        if(p->flags & FLAGS_FLOATE)
+          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
+        else if(p->flags & FLAGS_FLOATG)
+          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
+        else
+          *fptr++ = 'f';
+
+        *fptr = 0; /* and a final zero termination */
+
+        /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+           output characters */
+        (sprintf)(work, formatbuf, p->data.dnum);
+        DEBUGASSERT(strlen(work) <= sizeof(work));
+        for(fptr = work; *fptr; fptr++)
+          OUTCHAR(*fptr);
       }
       break;
 
     case FORMAT_INTPTR:
       /* Answer the count of characters written.  */
-#ifdef HAVE_LONGLONG
-      if (p->flags & FLAGS_LONGLONG)
-       *(long long *) p->data.ptr = (long long)done;
+#ifdef HAVE_LONG_LONG_TYPE
+      if(p->flags & FLAGS_LONGLONG)
+        *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
       else
 #endif
-       if (p->flags & FLAGS_LONG)
-         *(long *) p->data.ptr = (long)done;
-      else if (!(p->flags & FLAGS_SHORT))
-       *(int *) p->data.ptr = (int)done;
+        if(p->flags & FLAGS_LONG)
+          *(long *) p->data.ptr = (long)done;
+      else if(!(p->flags & FLAGS_SHORT))
+        *(int *) p->data.ptr = (int)done;
       else
-       *(short *) p->data.ptr = (short)done;
+        *(short *) p->data.ptr = (short)done;
       break;
 
     default:
@@ -962,14 +980,15 @@ static int dprintf_formatf(
 /* fputc() look-alike */
 static int addbyter(int output, FILE *data)
 {
-  struct nsprintf *infop=(struct nsprintf *)data;
+  struct nsprintf *infop = (struct nsprintf *)data;
+  unsigned char outc = (unsigned char)output;
+
   if(infop->length < infop->max) {
     /* only do this if we haven't reached max length yet */
-    infop->buffer[0] = (char)output; /* store */
+    infop->buffer[0] = outc; /* store */
     infop->buffer++; /* increase pointer */
     infop->length++; /* we are now one byte larger */
-    return output; /* fputc() returns like this on success */
+    return outc;     /* fputc() returns like this on success */
   }
   return -1;
 }
@@ -985,7 +1004,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 */
@@ -1009,32 +1028,39 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
 /* fputc() look-alike */
 static int alloc_addbyter(int output, FILE *data)
 {
-  struct asprintf *infop=(struct asprintf *)data;
+  struct asprintf *infop = (struct asprintf *)data;
+  unsigned char outc = (unsigned char)output;
+
   if(!infop->buffer) {
-    infop->buffer=(char *)malloc(32);
-    if(!infop->buffer)
+    infop->buffer = malloc(32);
+    if(!infop->buffer) {
+      infop->fail = 1;
       return -1; /* fail */
+    }
     infop->alloc = 32;
-    infop->len =0;
+    infop->len = 0;
   }
-  else if(infop->len+1 >= infop->alloc) {
-    char *newptr;
+  else if(infop->len + 1 >= infop->alloc) {
+    char *newptr = NULL;
+    size_t newsize = infop->alloc*2;
 
-    newptr = (char *)realloc(infop->buffer, infop->alloc*2);
+    /* detect wrap-around or other overflow problems */
+    if(newsize > infop->alloc)
+      newptr = realloc(infop->buffer, newsize);
 
     if(!newptr) {
-      return -1;
+      infop->fail = 1;
+      return -1; /* fail */
     }
     infop->buffer = newptr;
-    infop->alloc *= 2;
+    infop->alloc = newsize;
   }
 
-  infop->buffer[ infop->len ] = output;
+  infop->buffer[ infop->len ] = outc;
 
   infop->len++;
 
-  return output; /* fputc() returns like this on success */
+  return outc; /* fputc() returns like this on success */
 }
 
 char *curl_maprintf(const char *format, ...)
@@ -1046,11 +1072,12 @@ char *curl_maprintf(const char *format, ...)
   info.buffer = NULL;
   info.len = 0;
   info.alloc = 0;
+  info.fail = 0;
 
   va_start(ap_save, format);
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
   va_end(ap_save);
-  if(-1 == retcode) {
+  if((-1 == retcode) || info.fail) {
     if(info.alloc)
       free(info.buffer);
     return NULL;
@@ -1059,8 +1086,7 @@ char *curl_maprintf(const char *format, ...)
     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
     return info.buffer;
   }
-  else
-    return strdup("");
+  return strdup("");
 }
 
 char *curl_mvaprintf(const char *format, va_list ap_save)
@@ -1071,9 +1097,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
   info.buffer = NULL;
   info.len = 0;
   info.alloc = 0;
+  info.fail = 0;
 
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
-  if(-1 == retcode) {
+  if((-1 == retcode) || info.fail) {
     if(info.alloc)
       free(info.buffer);
     return NULL;
@@ -1083,16 +1110,16 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
     info.buffer[info.len] = 0; /* we terminate this with a zero byte */
     return info.buffer;
   }
-  else
-    return strdup("");
+  return strdup("");
 }
 
 static int storebuffer(int output, FILE *data)
 {
   char **buffer = (char **)data;
-  **buffer = (char)output;
+  unsigned char outc = (unsigned char)output;
+  **buffer = outc;
   (*buffer)++;
-  return output; /* act like fputc() ! */
+  return outc; /* act like fputc() ! */
 }
 
 int curl_msprintf(char *buffer, const char *format, ...)
@@ -1102,19 +1129,16 @@ int curl_msprintf(char *buffer, const char *format, ...)
   va_start(ap_save, format);
   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
   va_end(ap_save);
-  *buffer=0; /* we terminate this with a zero byte */
+  *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
-#ifndef WIN32 /* not needed on win32 */
-extern int fputc(int, FILE *);
-#endif
-
 int curl_mprintf(const char *format, ...)
 {
   int retcode;
   va_list ap_save; /* argument pointer */
   va_start(ap_save, format);
+
   retcode = dprintf_formatf(stdout, fputc, format, ap_save);
   va_end(ap_save);
   return retcode;
@@ -1134,7 +1158,7 @@ int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
 {
   int retcode;
   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
-  *buffer=0; /* we terminate this with a zero byte */
+  *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
@@ -1147,43 +1171,3 @@ int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
 {
   return dprintf_formatf(whereto, fputc, format, ap_save);
 }
-
-#ifdef DPRINTF_DEBUG
-int main()
-{
-  char buffer[129];
-  char *ptr;
-#ifdef HAVE_LONGLONG
-  long long hullo;
-  dprintf("%3$12s %1$s %2$qd %4$d\n", "daniel", hullo, "stenberg", 65);
-#endif
-
-  mprintf("%3d %5d\n", 10, 1998);
-  
-  ptr=maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001);
-
-  puts(ptr);
-
-  memset(ptr, 55, strlen(ptr)+1);
-
-  free(ptr);
-
-#if 1
-  mprintf(buffer, "%s %s %d", "daniel", "stenberg", 19988);
-  puts(buffer);
-
-  mfprintf(stderr, "%s %#08x\n", "dummy", 65);
-
-  printf("%s %#08x\n", "dummy", 65);
-  {
-    double tryout = 3.14156592;
-    mprintf(buffer, "%.2g %G %f %e %E", tryout, tryout, tryout, tryout, tryout);
-    puts(buffer);
-    printf("%.2g %G %f %e %E\n", tryout, tryout, tryout, tryout, tryout);
-  }
-#endif
-
-  return 0;
-}
-
-#endif