2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

4130. [bug] The compatability shim for *printf() misprinted some

large numbers. [RT #39586]
This commit is contained in:
Mark Andrews
2015-05-29 07:21:49 +10:00
parent 8bb630c751
commit 38c19e5779
3 changed files with 109 additions and 41 deletions

View File

@@ -1,3 +1,6 @@
4130. [bug] The compatability shim for *printf() misprinted some
large numbers. [RT #39586]
4129. [port] Address API changes in OpenSSL 1.1.0. [RT #39532] 4129. [port] Address API changes in OpenSSL 1.1.0. [RT #39532]
4128. [bug] Address issues raised by Coverity 7.6. [RT #39537] 4128. [bug] Address issues raised by Coverity 7.6. [RT #39537]

View File

@@ -22,6 +22,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdio.h> /* for sprintf() */ #include <stdio.h> /* for sprintf() */
#include <string.h> /* for strlen() */ #include <string.h> /* for strlen() */
#include <assert.h> /* for assert() */
#define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */ #define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */
@@ -32,29 +33,42 @@
#include <isc/stdlib.h> #include <isc/stdlib.h>
#include <isc/util.h> #include <isc/util.h>
/*
* We use the system's sprintf so we undef it here.
*/
#undef sprintf
static int static int
isc__print_printf(void (*emit)(char, void *), void *arg, const char *format, va_list ap); isc__print_printf(void (*emit)(char, void *), void *arg,
const char *format, va_list ap);
static void static void
file_emit(char c, void *arg) { file_emit(char c, void *arg) {
fputc(c, arg); FILE *fp = arg;
int i = c & 0xff;
putc(i, fp);
} }
#if 0
static int static int
isc_print_vfprintf(FILE *fp, const char *format, va_list ap) { isc_print_vfprintf(FILE *fp, const char *format, va_list ap) {
INSIST(fp != NULL); assert(fp != NULL);
INSIST(format != NULL); assert(format != NULL);
return (isc__print_printf(file_emit, fp, format, ap)); return (isc__print_printf(file_emit, fp, format, ap));
} }
#endif
int int
isc_print_printf(const char *format, ...) { isc_print_printf(const char *format, ...) {
va_list ap; va_list ap;
int n; int n;
assert(format != NULL);
va_start(ap, format); va_start(ap, format);
n = isc_print_vfprintf(stdout, format, ap); n = isc__print_printf(file_emit, stdout, format, ap);
va_end(ap); va_end(ap);
return (n); return (n);
} }
@@ -64,20 +78,34 @@ isc_print_fprintf(FILE *fp, const char *format, ...) {
va_list ap; va_list ap;
int n; int n;
assert(fp != NULL);
assert(format != NULL);
va_start(ap, format); va_start(ap, format);
n = isc_print_vfprintf(fp, format, ap); n = isc__print_printf(file_emit, fp, format, ap);
va_end(ap); va_end(ap);
return (n); return (n);
} }
static void
nocheck_emit(char c, void *arg) {
struct { char *str; } *a = arg;
*(a->str)++ = c;
}
int int
isc_print_sprintf(char *str, const char *format, ...) { isc_print_sprintf(char *str, const char *format, ...) {
struct { char *str; } arg;
int n;
va_list ap; va_list ap;
arg.str = str;
va_start(ap, format); va_start(ap, format);
vsprintf(str, format, ap); n = isc__print_printf(nocheck_emit, &arg, format, ap);
va_end(ap); va_end(ap);
return (strlen(str)); return (n);
} }
/*! /*!
@@ -90,7 +118,7 @@ isc_print_snprintf(char *str, size_t size, const char *format, ...) {
int ret; int ret;
va_start(ap, format); va_start(ap, format);
ret = vsnprintf(str, size, format, ap); ret = isc_print_vsnprintf(str, size, format, ap);
va_end(ap); va_end(ap);
return (ret); return (ret);
@@ -106,7 +134,7 @@ string_emit(char c, void *arg) {
if (p->size > 0U) { if (p->size > 0U) {
*(p->str)++ = c; *(p->str)++ = c;
(p->size)--; p->size--;
} }
} }
@@ -115,8 +143,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
struct { char *str; size_t size; } arg; struct { char *str; size_t size; } arg;
int n; int n;
INSIST(str != NULL); assert(str != NULL);
INSIST(format != NULL); assert(format != NULL);
arg.str = str; arg.str = str;
arg.size = size; arg.size = size;
@@ -156,14 +184,15 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
int zeropad; int zeropad;
int dot; int dot;
double dbl; double dbl;
isc_boolean_t precision_set;
#ifdef HAVE_LONG_DOUBLE #ifdef HAVE_LONG_DOUBLE
long double ldbl; long double ldbl;
#endif #endif
char fmt[32]; char fmt[32];
INSIST(emit != NULL); assert(emit != NULL);
INSIST(arg != NULL); assert(arg != NULL);
INSIST(format != NULL); assert(format != NULL);
while (*format != '\0') { while (*format != '\0') {
if (*format != '%') { if (*format != '%') {
@@ -180,6 +209,7 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
width = precision = 0; width = precision = 0;
head = ""; head = "";
pad = zeropad = 0; pad = zeropad = 0;
precision_set = ISC_FALSE;
do { do {
if (*format == '#') { if (*format == '#') {
@@ -225,10 +255,12 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
dot = 1; dot = 1;
if (*format == '*') { if (*format == '*') {
precision = va_arg(ap, int); precision = va_arg(ap, int);
precision_set = ISC_TRUE;
format++; format++;
} else if (isdigit((unsigned char)*format)) { } else if (isdigit((unsigned char)*format)) {
char *e; char *e;
precision = strtoul(format, &e, 10); precision = strtoul(format, &e, 10);
precision_set = ISC_TRUE;
format = e; format = e;
} }
} }
@@ -275,22 +307,22 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
if (h) { if (h) {
short int *p; short int *p;
p = va_arg(ap, short *); p = va_arg(ap, short *);
REQUIRE(p != NULL); assert(p != NULL);
*p = count; *p = count;
} else if (l) { } else if (l) {
long int *p; long int *p;
p = va_arg(ap, long *); p = va_arg(ap, long *);
REQUIRE(p != NULL); assert(p != NULL);
*p = count; *p = count;
} else if (z) { } else if (z) {
size_t *p; size_t *p;
p = va_arg(ap, size_t *); p = va_arg(ap, size_t *);
REQUIRE(p != NULL); assert(p != NULL);
*p = count; *p = count;
} else { } else {
int *p; int *p;
p = va_arg(ap, int *); p = va_arg(ap, int *);
REQUIRE(p != NULL); assert(p != NULL);
*p = count; *p = count;
} }
break; break;
@@ -327,12 +359,14 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
tmpui /= 1000000000; tmpui /= 1000000000;
mid = tmpui % 1000000000; mid = tmpui % 1000000000;
hi = tmpui / 1000000000; hi = tmpui / 1000000000;
if (hi != 0U) if (hi != 0U) {
sprintf(buf, "%lu", hi); sprintf(buf, "%lu", hi);
else sprintf(buf + strlen(buf),
buf[0] = '\0'; "%09lu", mid);
sprintf(buf + strlen(buf), "%lu", mid); } else
sprintf(buf + strlen(buf), "%lu", lo); sprintf(buf, "%lu", mid);
sprintf(buf + strlen(buf), "%09lu",
lo);
} }
goto printint; goto printint;
case 'o': case 'o':
@@ -360,12 +394,12 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
alt ? "%#lo" : "%lo", alt ? "%#lo" : "%lo",
hi); hi);
sprintf(buf + strlen(buf), sprintf(buf + strlen(buf),
"%lo", mid); "%09lo", mid);
} else } else
sprintf(buf, sprintf(buf,
alt ? "%#lo" : "%lo", alt ? "%#lo" : "%lo",
mid); mid);
sprintf(buf + strlen(buf), "%lo", lo); sprintf(buf + strlen(buf), "%09lo", lo);
} }
goto printint; goto printint;
case 'u': case 'u':
@@ -388,12 +422,14 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
tmpui /= 1000000000; tmpui /= 1000000000;
mid = tmpui % 1000000000; mid = tmpui % 1000000000;
hi = tmpui / 1000000000; hi = tmpui / 1000000000;
if (hi != 0U) if (hi != 0U) {
sprintf(buf, "%lu", hi); sprintf(buf, "%lu", hi);
else sprintf(buf + strlen(buf),
buf[0] = '\0'; "%09lu", mid);
sprintf(buf + strlen(buf), "%lu", mid); } else
sprintf(buf + strlen(buf), "%lu", lo); sprintf(buf, "%lu", mid);
sprintf(buf + strlen(buf), "%09lu",
lo);
} }
goto printint; goto printint;
case 'x': case 'x':
@@ -417,7 +453,7 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
unsigned long hi = tmpui>>32; unsigned long hi = tmpui>>32;
unsigned long lo = tmpui & 0xffffffff; unsigned long lo = tmpui & 0xffffffff;
sprintf(buf, "%lx", hi); sprintf(buf, "%lx", hi);
sprintf(buf + strlen(buf), "%lx", lo); sprintf(buf + strlen(buf), "%08lx", lo);
} }
goto printint; goto printint;
case 'X': case 'X':
@@ -441,11 +477,11 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
unsigned long hi = tmpui>>32; unsigned long hi = tmpui>>32;
unsigned long lo = tmpui & 0xffffffff; unsigned long lo = tmpui & 0xffffffff;
sprintf(buf, "%lX", hi); sprintf(buf, "%lX", hi);
sprintf(buf + strlen(buf), "%lX", lo); sprintf(buf + strlen(buf), "%08lX", lo);
} }
goto printint; goto printint;
printint: printint:
if (precision != 0U || width != 0U) { if (precision_set || width != 0U) {
length = strlen(buf); length = strlen(buf);
if (length < precision) if (length < precision)
zeropad = precision - length; zeropad = precision - length;
@@ -487,21 +523,23 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
break; break;
case 's': case 's':
cp = va_arg(ap, char *); cp = va_arg(ap, char *);
REQUIRE(cp != NULL);
if (precision != 0U) { if (precision_set) {
/* /*
* cp need not be NULL terminated. * cp need not be NULL terminated.
*/ */
const char *tp; const char *tp;
unsigned long n; unsigned long n;
if (precision != 0U)
assert(cp != NULL);
n = precision; n = precision;
tp = cp; tp = cp;
while (n != 0U && *tp != '\0') while (n != 0U && *tp != '\0')
n--, tp++; n--, tp++;
length = precision - n; length = precision - n;
} else { } else {
assert(cp != NULL);
length = strlen(cp); length = strlen(cp);
} }
if (width != 0U) { if (width != 0U) {
@@ -515,7 +553,7 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
emit(' ', arg); emit(' ', arg);
pad--; pad--;
} }
if (precision != 0U) if (precision_set)
while (precision > 0U && *cp != '\0') { while (precision > 0U && *cp != '\0') {
emit(*cp++, arg); emit(*cp++, arg);
precision--; precision--;
@@ -579,17 +617,17 @@ isc__print_printf(void (*emit)(char, void *), void *arg,
} }
break; break;
case 'D': /*deprecated*/ case 'D': /*deprecated*/
INSIST("use %ld instead of %D" == NULL); assert("use %ld instead of %D" == NULL);
case 'O': /*deprecated*/ case 'O': /*deprecated*/
INSIST("use %lo instead of %O" == NULL); assert("use %lo instead of %O" == NULL);
case 'U': /*deprecated*/ case 'U': /*deprecated*/
INSIST("use %lu instead of %U" == NULL); assert("use %lu instead of %U" == NULL);
case 'L': case 'L':
#ifdef HAVE_LONG_DOUBLE #ifdef HAVE_LONG_DOUBLE
l = 1; l = 1;
#else #else
INSIST("long doubles are not supported" == NULL); assert("long doubles are not supported" == NULL);
#endif #endif
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case 'e': case 'e':

View File

@@ -53,6 +53,8 @@ ATF_TC_HEAD(snprintf, tc) {
ATF_TC_BODY(snprintf, tc) { ATF_TC_BODY(snprintf, tc) {
char buf[10000]; char buf[10000];
isc_uint64_t ll = 8589934592ULL; isc_uint64_t ll = 8589934592ULL;
isc_uint64_t nn = 20000000000000ULL;
isc_uint64_t zz = 10000000000000000000LLU;
int n; int n;
size_t size; size_t size;
@@ -73,6 +75,31 @@ ATF_TC_BODY(snprintf, tc) {
ATF_CHECK_EQ(n, 10); ATF_CHECK_EQ(n, 10);
ATF_CHECK_STREQ(buf, "8589934592"); ATF_CHECK_STREQ(buf, "8589934592");
memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%qu", nn);
ATF_CHECK_EQ(n, 14);
ATF_CHECK_STREQ(buf, "20000000000000");
memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%llu", nn);
ATF_CHECK_EQ(n, 14);
ATF_CHECK_STREQ(buf, "20000000000000");
memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%qu", zz);
ATF_CHECK_EQ(n, 20);
ATF_CHECK_STREQ(buf, "10000000000000000000");
memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%llu", zz);
ATF_CHECK_EQ(n, 20);
ATF_CHECK_STREQ(buf, "10000000000000000000");
memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%lld", nn);
ATF_CHECK_EQ(n, 14);
ATF_CHECK_STREQ(buf, "20000000000000");
size = 1000; size = 1000;
memset(buf, 0xff, sizeof(buf)); memset(buf, 0xff, sizeof(buf));
n = isc_print_snprintf(buf, sizeof(buf), "%zu", size); n = isc_print_snprintf(buf, sizeof(buf), "%zu", size);