This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fix p_secstodate overflow handling (bug 22463)


On 11/21/2017 05:33 AM, Joseph Myers wrote:
RFC 4034 does not provide a specification of the
function p_secstodate.

Although RFC 4034 does not specify the p_secstodate API, it does specify the string format and p_secstodate is supposed to generate that format.

I reread the RFC, and found that our patches both mishandled out-of-range timestamps. The RFC says that, for a timestamp greater than the 32-bit range, the string should be a decimal representation of the timestamp's low-order 32 bits. With this in mind we can simplify the fix since we need not worry about going past the year 2106 or about tm_year overflow or anything like that. We can also fix another bug, since the code is mishandling post-2106 timestamps now on 64-bit time_t platforms (just as it is mishandling post-2038 timestamps on 32-bit time_t platforms).

Attached is an (untested) patch with this simplification in mind. It uses your idea of a 'clock < 0' test along with a static assertion (though the assertion is merely that time_t is at least 32 bits wide, since that's all we need now) to avoid the need for complicated integer-overflow checking. It uses my idea to use strftime instead of sprintf to simplify and shorten the code and avoid having confusing gotos and pragmas merely to pacify GCC's false alarms. And it passes just an unsigned int to sprintf so that GCC doesn't spout off unnecessarily about format overflow.

>From c6e58222ed279191add7ec97d98b33ed6eb08a17 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 21 Nov 2017 13:01:14 -0800
Subject: [PATCH] [BZ #22463]

* resolv/res_debug.c (p_secstodate): If the timestamp is out of
time_t or 32-bit unsigned range, just generate an unsigned decimal
integer representing the low-order 32 bits, as required by RFC
4034.  Use strftime instead of sprintf to format timestamps, as
this is simpler and avoids the need to pacify GCC about overflows
that cannot occur.
---
 ChangeLog          | 10 ++++++++++
 resolv/res_debug.c | 19 ++++++++++---------
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c72be0c301..5bf75fd3c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2017-11-21  Paul Eggert  <eggert@cs.ucla.edu>
+
+	[BZ #22463]
+	* resolv/res_debug.c (p_secstodate): If the timestamp is out of
+	time_t or 32-bit unsigned range, just generate an unsigned decimal
+	integer representing the low-order 32 bits, as required by RFC
+	4034.  Use strftime instead of sprintf to format timestamps, as
+	this is simpler and avoids the need to pacify GCC about overflows
+	that cannot occur.
+
 2017-11-21  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
 	* nptl/pthreadP.h (ASSERT_PTHREAD_INTERNAL_SIZE): Add workarond for
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 4114c2db46..93fcded381 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -1052,23 +1052,24 @@ libresolv_hidden_def (__dn_count_labels)
 
 
 /*
- * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * Convert SECS, a count of seconds since 1970-01-01, to the string
+ * format expected by Internet RFC 4034.
  * SIG records are required to be printed like this, by the Secure DNS RFC.
  */
 char *
 p_secstodate (u_long secs) {
 	/* XXX nonreentrant */
 	static char output[15];		/* YYYYMMDDHHMMSS and null */
+	_Static_assert ((time_t) 0x80000000 != 0,
+			"time_t contains at least 32 bits");
+	unsigned int losecs = secs & 0xffffffff;
 	time_t clock = secs;
-	struct tm *time;
-
 	struct tm timebuf;
-	time = __gmtime_r(&clock, &timebuf);
-	time->tm_year += 1900;
-	time->tm_mon += 1;
-	sprintf(output, "%04d%02d%02d%02d%02d%02d",
-		time->tm_year, time->tm_mon, time->tm_mday,
-		time->tm_hour, time->tm_min, time->tm_sec);
+	if (losecs != secs || clock < 0
+	    || __gmtime_r (&clock, &timebuf) == NULL)
+	  sprintf (output, "%u", losecs);
+	else
+	  strftime (output, sizeof output, "%Y%M%D%H%M%S", &timebuf);
 	return (output);
 }
 libresolv_hidden_def (__p_secstodate)
-- 
2.14.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]