Commit 9bb5da96 authored by Yang Tse's avatar Yang Tse
Browse files

Improved curl_m*printf() integral data type size and signedness handling

parent d5a71fd5
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -6,8 +6,9 @@

                                  Changelog

Yang Tse (21 Aug 2008)
- Fixed a couple of bugs in libcurl's internal curl_m*printf() functions.
Yang Tse (22 Aug 2008)
- Improved libcurl's internal curl_m*printf() functions integral data type
  size and signedness handling.

Daniel Fandrich (20 Aug 2008)
- Added an edited version of Vincent Le Normand's documentation of SFTP quote
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ This release includes the following bugfixes:
 o potential buffer overflows in the MS-DOS command-line port fixed
 o --stderr is now honoured with the -v option
 o memory leak in libcurl on Windows built with OpenSSL
 o improved curl_m*printf() integral data type size and signedness handling

This release includes the following known bugs:

+53 −55
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@

#include <curl/mprintf.h>

#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"

#ifndef SIZEOF_LONG_DOUBLE
#define SIZEOF_LONG_DOUBLE 0
#endif
@@ -74,9 +78,17 @@
#  endif
#endif

#include "memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/*
 * Max integer data types that mprintf.c is capable
 */

#ifdef HAVE_LONG_LONG_TYPE
#  define mp_intmax_t LONG_LONG_TYPE
#  define mp_uintmax_t unsigned LONG_LONG_TYPE
#else
#  define mp_intmax_t long
#  define mp_uintmax_t unsigned long
#endif

#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
#define MAX_PARAMETERS 128 /* lame static limit */
@@ -146,10 +158,10 @@ typedef struct {
  union {
    char *str;
    void *ptr;
    long num;
#ifdef HAVE_LONG_LONG_TYPE
    LONG_LONG_TYPE lnum;
#endif
    union {
      mp_intmax_t as_signed;
      mp_uintmax_t as_unsigned;
    } num;
    double dnum;
  } data;
} va_stack_t;
@@ -544,7 +556,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
        /* Width/precision arguments must be read before the main argument
         * they are attached to
         */
        vto[i + 1].data.num = va_arg(arglist, int);
        vto[i + 1].data.num.as_signed = (mp_intmax_t)va_arg(arglist, int);
      }

    switch (vto[i].type)
@@ -561,15 +573,27 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,

      case FORMAT_INT:
#ifdef HAVE_LONG_LONG_TYPE
        if(vto[i].flags & FLAGS_LONGLONG)
          vto[i].data.lnum = va_arg(arglist, 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, unsigned LONG_LONG_TYPE);
        else if(vto[i].flags & FLAGS_LONGLONG)
          vto[i].data.num.as_signed =
            (mp_intmax_t)va_arg(arglist, LONG_LONG_TYPE);
        else
#endif
        {
          if(vto[i].flags & FLAGS_LONG)
            vto[i].data.num = va_arg(arglist, long);
          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 = va_arg(arglist, int);
            vto[i].data.num.as_signed =
              (mp_intmax_t)va_arg(arglist, int);
        }
        break;

@@ -645,13 +669,10 @@ static int dprintf_formatf(
    long base;

    /* Integral values to be written.  */
#ifdef HAVE_LONG_LONG_TYPE
    unsigned LONG_LONG_TYPE num;
    LONG_LONG_TYPE signed_num;
#else
    unsigned long num;
    long signed_num;
#endif
    mp_uintmax_t num;

    /* Used to convert negative in positive.  */
    mp_intmax_t signed_num;

    if(*f != '%') {
      /* This isn't a format spec, so write everything out until the next one
@@ -690,13 +711,13 @@ static int dprintf_formatf(

    /* pick up the specified width */
    if(p->flags & FLAGS_WIDTHPARAM)
      width = vto[p->width].data.num;
      width = (long)vto[p->width].data.num.as_signed;
    else
      width = p->width;

    /* pick up the specified precision */
    if(p->flags & FLAGS_PRECPARAM) {
      prec = vto[p->precision].data.num;
      prec = (long)vto[p->precision].data.num.as_signed;
      param_num++; /* since the precision is extraced from a parameter, we
                      must skip that to get to the next one properly */
    }
@@ -709,12 +730,7 @@ static int dprintf_formatf(

    switch (p->type) {
    case FORMAT_INT:
#ifdef HAVE_LONG_LONG_TYPE
      if(p->flags & FLAGS_LONGLONG)
        num = (unsigned LONG_LONG_TYPE)p->data.lnum;
      else
#endif
        num = (unsigned long)p->data.num;
      num = p->data.num.as_unsigned;
      if(p->flags & FLAGS_CHAR) {
        /* Character.  */
        if(!(p->flags & FLAGS_LEFT))
@@ -747,32 +763,14 @@ static int dprintf_formatf(
      /* Decimal integer.  */
      base = 10;

#ifdef HAVE_LONG_LONG_TYPE
      if(p->flags & FLAGS_LONGLONG) {
        /* long long */
        is_neg = (p->data.lnum < 0);
      is_neg = p->data.num.as_signed < 0;
      if(is_neg) {
          /* signed long long might fail to hold absolute LLONG_MIN by 1 */
          signed_num = p->data.lnum + (LONG_LONG_TYPE)1;
          num = (unsigned LONG_LONG_TYPE)-signed_num;
          num += (unsigned LONG_LONG_TYPE)1;
        }
        else
          num = p->data.lnum;
      }
      else
#endif
      {
        is_neg = (p->data.num < 0);
        if(is_neg) {
          /* signed long might fail to hold absolute LONG_MIN by 1 */
          signed_num = p->data.num + (long)1;
          num = (unsigned long)-signed_num;
          num += (unsigned long)1;
        }
        else
          num = p->data.num;
        /* signed_num might fail to hold absolute negative minimum by 1 */
        signed_num = p->data.num.as_signed + (mp_intmax_t)1;
        num = (mp_uintmax_t)-signed_num;
        num += (mp_uintmax_t)1;
      }

      goto number;

      unsigned_number:
@@ -938,13 +936,13 @@ static int dprintf_formatf(
        if(p->flags & FLAGS_WIDTH)
          width = p->width;
        else if(p->flags & FLAGS_WIDTHPARAM)
          width = vto[p->width].data.num;
          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 = vto[p->precision].data.num;
          prec = (long)vto[p->precision].data.num.as_signed;

        if(p->flags & FLAGS_LEFT)
          strcat(formatbuf, "-");