From 0d2cd0ef5a29244a1c272a69e8a7e336bac3999f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 21 Nov 2016 22:20:43 +0100 Subject: [PATCH 1/2] common/snprintf.c and configure.ac : avoid a few compilation warnings --- common/snprintf.c | 15 ++++++++++++++- configure.ac | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/common/snprintf.c b/common/snprintf.c index a1802696b1..f56a70bedd 100644 --- a/common/snprintf.c +++ b/common/snprintf.c @@ -543,6 +543,7 @@ static void fmtint (char *buffer, size_t *currlen, size_t maxlen, } } +#ifndef HAVE_ABS_VAL static LDOUBLE abs_val (LDOUBLE value) { LDOUBLE result = value; @@ -552,7 +553,13 @@ static LDOUBLE abs_val (LDOUBLE value) return result; } +#endif +#ifndef HAVE_FCVT +/* The two routines that may get defined below are only used if we also don't + * have a fcvt() in the system. Defining and not using the routines may be a + * warning (fatal with -Werror), so we hide them here. */ +# ifndef HAVE_POW10 static LDOUBLE pow10 (int exp) { LDOUBLE result = 1; @@ -565,7 +572,9 @@ static LDOUBLE pow10 (int exp) return result; } +# endif +# ifndef HAVE_ROUND static long round (LDOUBLE value) { long intpart; @@ -577,6 +586,8 @@ static long round (LDOUBLE value) return intpart; } +# endif +#endif /* HAVE_FCVT */ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags) @@ -602,10 +613,12 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; +#ifndef HAVE_FCVT int caps = 0; long intpart; long fracpart; - +#endif + /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 diff --git a/configure.ac b/configure.ac index cf2adb1b52..f6338fddf4 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,7 @@ AC_C_BIGENDIAN AC_C_INLINE AC_C_FLEXIBLE_ARRAY_MEMBER AC_C_VARARRAYS -AC_CHECK_FUNCS(flock lockf fcvt fcvtl) +AC_CHECK_FUNCS(flock lockf fcvt fcvtl pow10 round abs_val) AC_CHECK_FUNCS(cfsetispeed tcsendbreak) AC_CHECK_FUNCS(seteuid setsid getpassphrase) AC_CHECK_FUNCS(on_exit strptime setlogmask) From 5adaf1e72d27954ca232c1f8fc33c0cfe7770e24 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 21 Nov 2016 23:34:00 +0100 Subject: [PATCH 2/2] common/snprintf.c : avoid a few compilation warnings and a possible crash due to padded ints in variadic functions --- common/snprintf.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/common/snprintf.c b/common/snprintf.c index f56a70bedd..62c8c14182 100644 --- a/common/snprintf.c +++ b/common/snprintf.c @@ -137,10 +137,26 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); /* Conversion Flags */ #define DP_C_SHORT 1 +/* Note: Originally DP_C_SHORT converted to "short int" types, but modernish + * (C99+ or even earlier) standards require that the minimal type passed + * through variadic args '...' is an int, and smaller types are padded up + * to it - so value shifts in memory and erroneous access crashes can occur + * if smaller data is accessed blindly. Code below has been fixed to not pass + * "short int" anymore - it just casts the int to desired smaller type (and + * so drops the padding bits). */ #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define DP_C_LLONG 4 +#ifdef C89PLUS +#undef C89PLUS +#endif + +#if defined(__STDC__) || defined(__STDC_VERSION__) +/* C89+ and C90+ code respectively */ +#define C89PLUS 1 +#endif + #define char_to_int(p) ((p)- '0') #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) @@ -275,7 +291,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) case 'd': case 'i': if (cflags == DP_C_SHORT) +#ifdef C89PLUS + value = (short int)va_arg (args, int); +#else value = va_arg (args, short int); +#endif else if (cflags == DP_C_LONG) value = va_arg (args, long int); else if (cflags == DP_C_LLONG) @@ -287,7 +307,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) +#ifdef C89PLUS + value = (unsigned short int)va_arg (args, unsigned int); +#else value = va_arg (args, unsigned short int); +#endif else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) @@ -299,7 +323,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) +#ifdef C89PLUS + value = (unsigned short int)va_arg (args, unsigned int); +#else value = va_arg (args, unsigned short int); +#endif else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) @@ -313,7 +341,11 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) +#ifdef C89PLUS + value = (unsigned short int)va_arg (args, unsigned int); +#else value = va_arg (args, unsigned short int); +#endif else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) @@ -365,7 +397,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) short int *num; num = va_arg (args, short int *); *num = currlen; - } + } else if (cflags == DP_C_LONG) { long int *num;