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:
3
CHANGES
3
CHANGES
@@ -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]
|
||||||
|
120
lib/isc/print.c
120
lib/isc/print.c
@@ -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':
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user