From cadf8d687b9719b87c121d5cc8b028b1ddccc642 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 21 May 2015 14:55:15 -0700 Subject: [PATCH] [master] add %z format options to printf 4123. [port] Added %z (size_t) format options to the portable internal printf/sprintf implementation. [RT #39586] --- CHANGES | 3 + configure | 42 ++++++ configure.in | 24 +++ lib/dns/rpz.c | 4 +- lib/isc/include/isc/platform.h.in | 12 +- lib/isc/include/isc/print.h | 24 ++- lib/isc/print.c | 233 +++++++++++++++++------------- lib/isc/tests/Makefile.in | 3 +- lib/isc/tests/print_test.c | 63 +++++++- 9 files changed, 302 insertions(+), 106 deletions(-) diff --git a/CHANGES b/CHANGES index 27529832f1..0e07b43e23 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4123. [port] Added %z (size_t) format options to the portable + internal printf/sprintf implementation. [RT #39586] + 4122. [bug] The server could match a shorter prefix than what was available in CLIENT-IP policy triggers, and so, an unexpected action could be taken. This has been diff --git a/configure b/configure index 4076a57875..af53cea909 100755 --- a/configure +++ b/configure @@ -719,6 +719,8 @@ LWRES_PLATFORM_USEDECLSPEC ISC_PLATFORM_USEDECLSPEC ISC_PLATFORM_RLIMITTYPE ISC_PLATFORM_HAVESYSUNH +ISC_PLATFORM_NEEDFPRINTF +ISC_PLATFORM_NEEDPRINTF LWRES_PLATFORM_QUADFORMAT ISC_PLATFORM_QUADFORMAT DST_EXTRA_SRCS @@ -18764,6 +18766,46 @@ fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking printf for %z support" >&5 +$as_echo_n "checking printf for %z support... " >&6; } +if test "$cross_compiling" = yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming target platform supports %z" >&5 +$as_echo "assuming target platform supports %z" >&6; } + ISC_PLATFORM_NEEDPRINTF='#undef ISC_PLATFORM_NEEDPRINTF' + ISC_PLATFORM_NEEDFPRINTF='#undef ISC_PLATFORM_NEEDFPRINTF' +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +main() { + /* Assume sprintf matches printf/fprintf. */ + size_t j = 0; + char buf[100]; + buf[0] = 0; + sprintf(buf, "%zu", j); + exit(strcmp(buf, "0") != 0); +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ISC_PLATFORM_NEEDPRINTF='#undef ISC_PLATFORM_NEEDPRINTF' + ISC_PLATFORM_NEEDFPRINTF='#undef ISC_PLATFORM_NEEDFPRINTF' +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ISC_PLATFORM_NEEDPRINTF='#define ISC_PLATFORM_NEEDPRINTF 1' + ISC_PLATFORM_NEEDFPRINTF='#define ISC_PLATFORM_NEEDFPRINTF 1' +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + + # # Security Stuff # diff --git a/configure.in b/configure.in index 24324da577..080593350c 100644 --- a/configure.in +++ b/configure.in @@ -3345,6 +3345,30 @@ main() { AC_SUBST(ISC_PLATFORM_QUADFORMAT) AC_SUBST(LWRES_PLATFORM_QUADFORMAT) +AC_MSG_CHECKING([printf for %z support]) +AC_TRY_RUN([ +#include +main() { + /* Assume sprintf matches printf/fprintf. */ + size_t j = 0; + char buf[100]; + buf[0] = 0; + sprintf(buf, "%zu", j); + exit(strcmp(buf, "0") != 0); +} +], + [AC_MSG_RESULT(yes) + ISC_PLATFORM_NEEDPRINTF='#undef ISC_PLATFORM_NEEDPRINTF' + ISC_PLATFORM_NEEDFPRINTF='#undef ISC_PLATFORM_NEEDFPRINTF'], + [AC_MSG_RESULT(no) + ISC_PLATFORM_NEEDPRINTF='#define ISC_PLATFORM_NEEDPRINTF 1' + ISC_PLATFORM_NEEDFPRINTF='#define ISC_PLATFORM_NEEDFPRINTF 1'], + [AC_MSG_RESULT([assuming target platform supports %z]) + ISC_PLATFORM_NEEDPRINTF='#undef ISC_PLATFORM_NEEDPRINTF' + ISC_PLATFORM_NEEDFPRINTF='#undef ISC_PLATFORM_NEEDFPRINTF']) +AC_SUBST(ISC_PLATFORM_NEEDPRINTF) +AC_SUBST(ISC_PLATFORM_NEEDFPRINTF) + # # Security Stuff # diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index 159709dc68..e622a0fb19 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -1656,8 +1656,8 @@ fix_triggers(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB, DNS_RPZ_INFO_LEVEL, "(re)loading policy zone '%s' changed from" - " %ld to %ld qname, %ld to %ld nsdname," - " %ld to %ld IP, %ld to %ld NSIP entries", + " %zd to %zd qname, %zd to %zd nsdname," + " %zd to %zd IP, %zd to %zd NSIP entries", namebuf, old_totals.qname, rpzs->total_triggers.qname, old_totals.nsdname, rpzs->total_triggers.nsdname, diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in index 79d0136932..29b50abd41 100644 --- a/lib/isc/include/isc/platform.h.in +++ b/lib/isc/include/isc/platform.h.in @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: platform.h.in,v 1.56 2010/12/18 01:56:23 each Exp $ */ - #ifndef ISC_PLATFORM_H #define ISC_PLATFORM_H 1 @@ -171,6 +169,16 @@ */ @ISC_PLATFORM_NEEDSPRINTF@ +/*! \brief + * If this system need a modern printf() that format size %z (size_t). + */ +@ISC_PLATFORM_NEEDPRINTF@ + +/*! \brief + * If this system need a modern fprintf() that format size %z (size_t). + */ +@ISC_PLATFORM_NEEDFPRINTF@ + /*! \brief * The printf format string modifier to use with isc_uint64_t values. */ diff --git a/lib/isc/include/isc/print.h b/lib/isc/include/isc/print.h index 2b9169001f..f4caecf7dd 100644 --- a/lib/isc/include/isc/print.h +++ b/lib/isc/include/isc/print.h @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.h,v 1.26 2007/06/19 23:47:18 tbox Exp $ */ - #ifndef ISC_PRINT_H #define ISC_PRINT_H 1 @@ -47,6 +45,16 @@ #undef sprintf #endif +#if !defined(ISC_PLATFORM_NEEDFPRINTF) && defined(ISC__PRINT_SOURCE) +#define ISC_PLATFORM_NEEDFPRINTF +#undef fprintf +#endif + +#if !defined(ISC_PLATFORM_NEEDPRINTF) && defined(ISC__PRINT_SOURCE) +#define ISC_PLATFORM_NEEDPRINTF +#undef printf +#endif + /*** *** Macros ***/ @@ -85,6 +93,18 @@ isc_print_sprintf(char *str, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); #define sprintf isc_print_sprintf #endif +#ifdef ISC_PLATFORM_NEEDPRINTF +int +isc_print_printf(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); +#define printf isc_print_printf +#endif + +#ifdef ISC_PLATFORM_NEEDFPRINTF +int +isc_print_fprintf(FILE * fp, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); +#define fprintf isc_print_fprintf +#endif + ISC_LANG_ENDDECLS #endif /* ISC_PRINT_H */ diff --git a/lib/isc/print.c b/lib/isc/print.c index 06719e83a5..a251de7b28 100644 --- a/lib/isc/print.c +++ b/lib/isc/print.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.c,v 1.37 2010/10/18 23:47:08 tbox Exp $ */ - /*! \file */ #include @@ -34,6 +32,44 @@ #include #include +static int +isc__print_printf(void (*emit)(char, void *), void *arg, const char *format, va_list ap); + +static void +file_emit(char c, void *arg) { + fputc(c, arg); +} + +static int +isc_print_vfprintf(FILE *fp, const char *format, va_list ap) { + INSIST(fp != NULL); + INSIST(format != NULL); + + return (isc__print_printf(file_emit, fp, format, ap)); +} + +int +isc_print_printf(const char *format, ...) { + va_list ap; + int n; + + va_start(ap, format); + n = isc_print_vfprintf(stdout, format, ap); + va_end(ap); + return (n); +} + +int +isc_print_fprintf(FILE *fp, const char *format, ...) { + va_list ap; + int n; + + va_start(ap, format); + n = isc_print_vfprintf(fp, format, ap); + va_end(ap); + return (n); +} + int isc_print_sprintf(char *str, const char *format, ...) { va_list ap; @@ -64,10 +100,40 @@ isc_print_snprintf(char *str, size_t size, const char *format, ...) { * Return length of string that would have been written if not truncated. */ +static void +string_emit(char c, void *arg) { + struct { char *str; size_t size; } *p = arg; + + if (p->size > 0) { + *(p->str)++ = c; + (p->size)--; + } +} + int isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + struct { char *str; size_t size; } arg; + int n; + + INSIST(str != NULL); + INSIST(format != NULL); + + arg.str = str; + arg.size = size; + + n = isc__print_printf(string_emit, &arg, format, ap); + if (arg.size > 0) + *arg.str = '\0'; + return (n); +} + +static int +isc__print_printf(void (*emit)(char, void *), void *arg, + const char *format, va_list ap) +{ int h; int l; + int z; int q; int alt; int zero; @@ -83,7 +149,6 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { char buf[1024]; char c; void *v; - char *save = str; const char *cp; const char *head; int count = 0; @@ -96,17 +161,14 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { #endif char fmt[32]; - INSIST(str != NULL); + INSIST(emit != NULL); + INSIST(arg != NULL); INSIST(format != NULL); while (*format != '\0') { if (*format != '%') { - if (size > 1) { - *str++ = *format; - size--; - } + emit(*format++, arg); count++; - format++; continue; } format++; @@ -114,7 +176,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { /* * Reset flags. */ - dot = neg = space = plus = left = zero = alt = h = l = q = 0; + dot = neg = space = plus = left = zero = alt = h = l = q = z = 0; width = precision = 0; head = ""; pad = zeropad = 0; @@ -175,10 +237,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { case '\0': continue; case '%': - if (size > 1) { - *str++ = *format; - size--; - } + emit(*format, arg); count++; break; case 'q': @@ -197,6 +256,10 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { format++; } goto doint; + case 'z': + z = 1; + format++; + goto doint; case 'n': case 'i': case 'd': @@ -213,17 +276,22 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { short int *p; p = va_arg(ap, short *); REQUIRE(p != NULL); - *p = str - save; + *p = count; } else if (l) { long int *p; p = va_arg(ap, long *); REQUIRE(p != NULL); - *p = str - save; + *p = count; + } else if (z) { + size_t *p; + p = va_arg(ap, size_t *); + REQUIRE(p != NULL); + *p = count; } else { int *p; p = va_arg(ap, int *); REQUIRE(p != NULL); - *p = str - save; + *p = count; } break; case 'i': @@ -232,6 +300,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpi = va_arg(ap, isc_int64_t); else if (l) tmpi = va_arg(ap, long int); + else if (z) + tmpi = va_arg(ap, ssize_t); else tmpi = va_arg(ap, int); if (tmpi < 0) { @@ -270,6 +340,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, int); if (tmpui <= 0xffffffffU) @@ -301,6 +373,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (tmpui <= 0xffffffffU) @@ -327,6 +401,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (alt) { @@ -349,6 +425,8 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { tmpui = va_arg(ap, isc_uint64_t); else if (l) tmpui = va_arg(ap, unsigned long int); + else if (z) + tmpui = va_arg(ap, size_t); else tmpui = va_arg(ap, unsigned int); if (alt) { @@ -383,30 +461,23 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { count += strlen(head) + strlen(buf) + pad + zeropad; if (!left) { - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } } cp = head; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (zeropad > 0) { + emit('0', arg); zeropad--; } cp = buf; - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -440,26 +511,20 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } count += pad + length; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } if (precision != 0) - while (precision > 0 && *cp != '\0' && - size > 1) { - *str++ = *cp++; - size--; + while (precision > 0 && *cp != '\0') { + emit(*cp++, arg); precision--; } else - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -468,24 +533,15 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { if (width > 0) { count += width; width--; - if (left && size > 1) { - *str++ = c; - size--; - } - while (width-- > 0 && size > 1) { - *str++ = ' '; - size--; - } - if (!left && size > 1) { - *str++ = c; - size--; - } + if (left) + emit(c, arg); + while (width-- > 0) + emit(' ', arg); + if (!left) + emit(c, arg); } else { count++; - if (size > 1) { - *str++ = c; - size--; - } + emit(c, arg); } break; case 'p': @@ -501,35 +557,24 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } count += length + pad + zeropad; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } cp = buf; if (zeropad > 0 && buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { - if (size > 1) { - *str++ = *cp++; - size--; - } - if (size > 1) { - *str++ = *cp++; - size--; - } - while (zeropad > 0 && size > 1) { - *str++ = '0'; - size--; + emit(*cp++, arg); + emit(*cp++, arg); + while (zeropad > 0) { + emit('0', arg); zeropad--; } } - while (*cp != '\0' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != '\0') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -593,19 +638,15 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } count += length + pad; if (!left) - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (pad > 0) { + emit(' ', arg); pad--; } cp = buf; - while (*cp != ' ' && size > 1) { - *str++ = *cp++; - size--; - } - while (pad > 0 && size > 1) { - *str++ = ' '; - size--; + while (*cp != ' ') + emit(*cp++, arg); + while (pad > 0) { + emit(' ', arg); pad--; } break; @@ -618,7 +659,5 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { } format++; } - if (size > 0) - *str = '\0'; return (count); } diff --git a/lib/isc/tests/Makefile.in b/lib/isc/tests/Makefile.in index 117ed849d0..6735e5d930 100644 --- a/lib/isc/tests/Makefile.in +++ b/lib/isc/tests/Makefile.in @@ -99,7 +99,8 @@ sockaddr_test@EXEEXT@: sockaddr_test.@O@ isctest.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ sockaddr_test.@O@ isctest.@O@ ${ISCLIBS} ${LIBS} -print_test@EXEEXT@: print_test.@O@ ${ISCDEPLIBS} ${top_srcdir}/lib/isc/print.c +print_test.@O@: ${top_srcdir}/lib/isc/print.c +print_test@EXEEXT@: print_test.@O@ ${ISCDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ print_test.@O@ ${ISCLIBS} ${LIBS} diff --git a/lib/isc/tests/print_test.c b/lib/isc/tests/print_test.c index 46a1ea3ad2..be864de798 100644 --- a/lib/isc/tests/print_test.c +++ b/lib/isc/tests/print_test.c @@ -28,11 +28,17 @@ * it on all platforms even if we don't include it in libisc. */ #include -#if !defined(ISC_PLATFORM_NEEDVSNPRINTF) && !defined(ISC_PLATFORM_NEEDSPRINTF) +#if !defined(ISC_PLATFORM_NEEDPRINTF) && \ + !defined(ISC_PLATFORM_NEEDFPRINTF) && \ + !defined(ISC_PLATFORM_NEEDSPRINTF) && \ + !defined(ISC_PLATFORM_NEEDVSNPRINTF) #define ISC__PRINT_SOURCE #include "../print.c" #else -#if !defined(ISC_PLATFORM_NEEDVSNPRINTF) || !defined(ISC_PLATFORM_NEEDSPRINTF) +#if !defined(ISC_PLATFORM_NEEDPRINTF) || \ + !defined(ISC_PLATFORM_NEEDFPRINTF) || \ + !defined(ISC_PLATFORM_NEEDSPRINTF) || \ + !defined(ISC_PLATFORM_NEEDVSNPRINTF) #define ISC__PRINT_SOURCE #endif #include @@ -48,6 +54,7 @@ ATF_TC_BODY(snprintf, tc) { char buf[10000]; isc_uint64_t ll = 8589934592ULL; int n; + size_t size; UNUSED(tc); @@ -65,6 +72,57 @@ ATF_TC_BODY(snprintf, tc) { n = isc_print_snprintf(buf, sizeof(buf), "%llu", ll); ATF_CHECK_EQ(n, 10); ATF_CHECK_STREQ(buf, "8589934592"); + + size = 1000; + memset(buf, 0xff, sizeof(buf)); + n = isc_print_snprintf(buf, sizeof(buf), "%zu", size); + ATF_CHECK_EQ(n, 4); + ATF_CHECK_STREQ(buf, "1000"); + + size = 1000; + memset(buf, 0xff, sizeof(buf)); + n = isc_print_snprintf(buf, sizeof(buf), "%zx", size); + ATF_CHECK_EQ(n, 3); + ATF_CHECK_STREQ(buf, "3e8"); + + size = 1000; + memset(buf, 0xff, sizeof(buf)); + n = isc_print_snprintf(buf, sizeof(buf), "%zo", size); + ATF_CHECK_EQ(n, 4); + ATF_CHECK_STREQ(buf, "1750"); +} + +ATF_TC(fprintf); +ATF_TC_HEAD(fprintf, tc) { + atf_tc_set_md_var(tc, "descr", "fprintf implementation"); +} +ATF_TC_BODY(fprintf, tc) { + FILE *f; + int n; + size_t size; + char buf[10000]; + + UNUSED(tc); + + f = fopen("fprintf.test", "w+"); + ATF_REQUIRE(f != NULL); + + size = 1000; + n = isc_print_fprintf(f, "%zu", size); + ATF_CHECK_EQ(n, 4); + + rewind(f); + + memset(buf, 0, sizeof(buf)); + n = fread(buf, 1, sizeof(buf), f); + ATF_CHECK_EQ(n, 4); + + fclose(f); + + ATF_CHECK_STREQ(buf, "1000"); + + if ((n > 0) && (!strcmp(buf, "1000"))) + unlink("fprintf.test"); } /* @@ -72,5 +130,6 @@ ATF_TC_BODY(snprintf, tc) { */ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, snprintf); + ATF_TP_ADD_TC(tp, fprintf); return (atf_no_error()); }