From 2019cf29e29c4e5226d1c164177131b60cb5a25b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 3 Aug 2017 08:42:27 +1000 Subject: [PATCH] 4668. [bug] Use localtime_r and gmtime_r for thread safety. [RT #45664] --- CHANGES | 3 +++ bin/dig/dig.c | 6 +++++ bin/tests/net/driver.c | 16 ++++++++----- lib/dns/update.c | 7 ++++++ lib/isc/unix/time.c | 51 ++++++++++++++++++++++++++++++++++++++++++ lib/tests/t_api.c | 8 +++++++ 6 files changed, 85 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index d6dee6a332..d3de6fb339 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4668. [bug] Use localtime_r and gmtime_r for thread safety. + [RT #45664] + 4667. [cleanup] Refactor RDATA unit tests. [RT #45610] 4666. [bug] dnssec-keymgr: Domain names beginning with digits (0-9) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index e38d036180..92e0438cc3 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -261,7 +262,12 @@ received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { printf(";; Query time: %ld msec\n", (long) diff / 1000); printf(";; SERVER: %s(%s)\n", fromtext, query->servname); time(&tnow); +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + (void)localtime_r(&tnow, &tmnow); +#else tmnow = *localtime(&tnow); +#endif + if (strftime(time_str, sizeof(time_str), "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) printf(";; WHEN: %s\n", time_str); diff --git a/bin/tests/net/driver.c b/bin/tests/net/driver.c index d6fe3f77a9..db9a54b167 100644 --- a/bin/tests/net/driver.c +++ b/bin/tests/net/driver.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -27,19 +28,22 @@ const char *gettime(void); const char *test_result_totext(test_result_t); -/* - * Not thread safe. - */ const char * gettime(void) { static char now[512]; time_t t; +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + struct tm tm; +#endif (void)time(&t); - strftime(now, sizeof(now) - 1, - "%A %d %B %H:%M:%S %Y", - localtime(&t)); +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + strftime(now, sizeof(now) - 1, "%A %d %B %H:%M:%S %Y", + localtime_r(&t, &tm)); +#else + strftime(now, sizeof(now) - 1, "%A %d %B %H:%M:%S %Y", localtime(&t)); +#endif return (now); } diff --git a/lib/dns/update.c b/lib/dns/update.c index bcbbd26b08..34243c99f0 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -2023,7 +2024,13 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, static isc_stdtime_t epoch_to_yyyymmdd(time_t when) { struct tm *tm; + +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + struct tm tm0; + tm = localtime_r(&when, &tm0); +#else tm = localtime(&when); +#endif return (((tm->tm_year + 1900) * 10000) + ((tm->tm_mon + 1) * 100) + tm->tm_mday); } diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index 725d49472d..49aa967e97 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -21,6 +21,7 @@ #include /* Required for struct timeval on some platforms. */ #include +#include #include #include #include @@ -376,11 +377,18 @@ void isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t) t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%d-%b-%Y %X", localtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now)); +#endif INSIST(flen < len); if (flen != 0) snprintf(buf + flen, len - flen, @@ -395,6 +403,9 @@ void isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); @@ -402,7 +413,12 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+) */ now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", + gmtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); +#endif INSIST(flen < len); } @@ -428,11 +444,18 @@ void isc_time_formatISO8601L(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime(&now)); +#endif INSIST(flen < len); } @@ -440,11 +463,18 @@ void isc_time_formatISO8601Lms(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%S", localtime(&now)); +#endif INSIST(flen < len); if (flen > 0U && len - flen >= 6) { snprintf(buf + flen, len - flen, ".%03u", @@ -456,11 +486,18 @@ void isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now)); +#endif INSIST(flen < len); } @@ -468,11 +505,18 @@ void isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now)); +#endif INSIST(flen < len); if (flen > 0U && len - flen >= 5) { flen -= 1; /* rewind one character (Z) */ @@ -486,11 +530,18 @@ isc_time_formatshorttimestamp(const isc_time_t *t, char *buf, unsigned int len) { time_t now; unsigned int flen; +#ifdef ISC_PLATFORM_USETHREADS + struct tm tm; +#endif REQUIRE(len > 0); now = (time_t)t->seconds; +#ifdef ISC_PLATFORM_USETHREADS + flen = strftime(buf, len, "%Y%m%d%H%M%S", gmtime_r(&now, &tm)); +#else flen = strftime(buf, len, "%Y%m%d%H%M%S", gmtime(&now)); +#endif INSIST(flen < len); if (flen > 0U && len - flen >= 5) { flen -= 1; /* rewind one character (Z) */ diff --git a/lib/tests/t_api.c b/lib/tests/t_api.c index 5b7b03e250..8280c299fa 100644 --- a/lib/tests/t_api.c +++ b/lib/tests/t_api.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -596,9 +597,16 @@ t_getdate(char *buf, size_t buflen) { size_t n; time_t t; struct tm *p; +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + struct tm tm; +#endif t = time(NULL); +#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32) + p = localtime_r(&t, &tm); +#else p = localtime(&t); +#endif n = strftime(buf, buflen - 1, "%A %d %B %H:%M:%S %Y\n", p); return(n != 0U ? buf : NULL); }