Fix p_secstodate overflow handling (bug 22463)

Message ID c9614ea5-153d-3be8-a28d-7ca8723fb3b6@cs.ucla.edu
State New, archived
Headers

Commit Message

Paul Eggert Nov. 21, 2017, 11:56 p.m. UTC
  On 11/21/2017 02:26 PM, Joseph Myers wrote:
> The strftime use is incorrect - the %M%D needs to be %m%d.

Thanks for catching that. Revised patch attached. I plead guilty to 
being too lazy to test this.
  

Patch

From da0f551929e7d97befd6bec598328d560e0a3f1d 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..e6f7932049 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