bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* [PATCH] posixtm: pacify latest GCC
@ 2021-07-17 23:03 Paul Eggert
  0 siblings, 0 replies; only message in thread
From: Paul Eggert @ 2021-07-17 23:03 UTC (permalink / raw)
  To: bug-gnulib; +Cc: Paul Eggert

Also, modernize while I’m at it.
* lib/posixtm.c: Include c-ctype.h, idx.h, intprops.h, verify.h
instead of stdlib.h.
(ISDIGIT): Remove.  All uses replaced by c_isdigit.
(year, posix_time_parse): Prefer idx_t to size_t.  Use assume
instead of abort.
(posixtime): Do not parse twice; once is enough.  That way, we
needn’t worry about a bogus warning about strcpy overrunning a
buffer from GCC 11.1.1 20210531 (Red Hat 11.1.1-3) x86-64
when coreutils is configured with --enable-gcc-warnings.
* modules/posixtm (Depends-on): Add c-ctype, intprops, verify.
Remove stpcpy.
---
 ChangeLog       |  16 +++++++
 lib/posixtm.c   | 115 ++++++++++++++++++++++--------------------------
 modules/posixtm |   5 ++-
 3 files changed, 72 insertions(+), 64 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 356f40596..6ba44e7df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2021-07-17  Paul Eggert  <eggert@cs.ucla.edu>
+
+	posixtm: pacify latest GCC
+	Also, modernize while I’m at it.
+	* lib/posixtm.c: Include c-ctype.h, idx.h, intprops.h, verify.h
+	instead of stdlib.h.
+	(ISDIGIT): Remove.  All uses replaced by c_isdigit.
+	(year, posix_time_parse): Prefer idx_t to size_t.  Use assume
+	instead of abort.
+	(posixtime): Do not parse twice; once is enough.  That way, we
+	needn’t worry about a bogus warning about strcpy overrunning a
+	buffer from GCC 11.1.1 20210531 (Red Hat 11.1.1-3) x86-64
+	when coreutils is configured with --enable-gcc-warnings.
+	* modules/posixtm (Depends-on): Add c-ctype, intprops, verify.
+	Remove stpcpy.
+
 2021-07-17  Bruno Haible  <bruno@clisp.org>
 
 	Don't use '#pragma weak' for thread functions in Linux/glibc>=2.34.
diff --git a/lib/posixtm.c b/lib/posixtm.c
index d142484f7..d468f70df 100644
--- a/lib/posixtm.c
+++ b/lib/posixtm.c
@@ -22,17 +22,12 @@
 
 #include "posixtm.h"
 
-#include <stdlib.h>
-#include <string.h>
+#include "c-ctype.h"
+#include "idx.h"
+#include "intprops.h"
+#include "verify.h"
 
-/* ISDIGIT differs from isdigit, as follows:
-   - Its arg may be any int or unsigned int; it need not be an unsigned char
-     or EOF.
-   - It's typically faster.
-   POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
-   isdigit unless it's important to use the locale's definition
-   of "digit" even when the host does not conform to POSIX.  */
-#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+#include <string.h>
 
 /*
   POSIX requires:
@@ -52,7 +47,7 @@
 */
 
 static bool
-year (struct tm *tm, const int *digit_pair, size_t n, unsigned int syntax_bits)
+year (struct tm *tm, const int *digit_pair, idx_t n, unsigned int syntax_bits)
 {
   switch (n)
     {
@@ -77,12 +72,9 @@ year (struct tm *tm, const int *digit_pair, size_t n, unsigned int syntax_bits)
 
     case 0:
       {
-        time_t now;
-        struct tm *tmp;
-
         /* Use current year.  */
-        time (&now);
-        tmp = localtime (&now);
+        time_t now = time (NULL);
+        struct tm *tmp = localtime (&now);
         if (! tmp)
           return false;
         tm->tm_year = tmp->tm_year;
@@ -90,7 +82,7 @@ year (struct tm *tm, const int *digit_pair, size_t n, unsigned int syntax_bits)
       break;
 
     default:
-      abort ();
+      assume (false);
     }
 
   return true;
@@ -101,11 +93,9 @@ posix_time_parse (struct tm *tm, const char *s, unsigned int syntax_bits)
 {
   const char *dot = NULL;
   int pair[6];
-  int *p;
-  size_t i;
 
-  size_t s_len = strlen (s);
-  size_t len = s_len;
+  idx_t s_len = strlen (s);
+  idx_t len = s_len;
 
   if (syntax_bits & PDS_SECONDS)
     {
@@ -121,15 +111,15 @@ posix_time_parse (struct tm *tm, const char *s, unsigned int syntax_bits)
   if (! (8 <= len && len <= 12 && len % 2 == 0))
     return false;
 
-  for (i = 0; i < len; i++)
-    if (!ISDIGIT (s[i]))
+  for (idx_t i = 0; i < len; i++)
+    if (!c_isdigit (s[i]))
       return false;
 
   len /= 2;
-  for (i = 0; i < len; i++)
+  for (idx_t i = 0; i < len; i++)
     pair[i] = 10 * (s[2*i] - '0') + s[2*i + 1] - '0';
 
-  p = pair;
+  int *p = pair;
   if (! (syntax_bits & PDS_TRAILING_YEAR))
     {
       if (! year (tm, p, len - 4, syntax_bits))
@@ -155,7 +145,7 @@ posix_time_parse (struct tm *tm, const char *s, unsigned int syntax_bits)
   /* Handle seconds.  */
   if (!dot)
     tm->tm_sec = 0;
-  else if (ISDIGIT (dot[1]) && ISDIGIT (dot[2]))
+  else if (c_isdigit (dot[1]) && c_isdigit (dot[2]))
     tm->tm_sec = 10 * (dot[1] - '0') + dot[2] - '0';
   else
     return false;
@@ -169,51 +159,50 @@ bool
 posixtime (time_t *p, const char *s, unsigned int syntax_bits)
 {
   struct tm tm0;
-  struct tm tm1;
-  time_t t;
+  bool leapsec = false;
 
   if (! posix_time_parse (&tm0, s, syntax_bits))
     return false;
 
-  tm1.tm_sec = tm0.tm_sec;
-  tm1.tm_min = tm0.tm_min;
-  tm1.tm_hour = tm0.tm_hour;
-  tm1.tm_mday = tm0.tm_mday;
-  tm1.tm_mon = tm0.tm_mon;
-  tm1.tm_year = tm0.tm_year;
-  tm1.tm_wday = -1;
-  tm1.tm_isdst = -1;
-  t = mktime (&tm1);
-
-  if (tm1.tm_wday < 0)
-    return false;
-
-  /* Reject dates like "September 31" and times like "25:61".
-     However, allow a seconds count of 60 even in time zones that do
-     not support leap seconds, treating it as the following second;
-     POSIX requires this.  */
-  if ((tm0.tm_year ^ tm1.tm_year)
-      | (tm0.tm_mon ^ tm1.tm_mon)
-      | (tm0.tm_mday ^ tm1.tm_mday)
-      | (tm0.tm_hour ^ tm1.tm_hour)
-      | (tm0.tm_min ^ tm1.tm_min)
-      | (tm0.tm_sec ^ tm1.tm_sec))
+  while (true)
     {
+      struct tm tm1;
+      tm1.tm_sec = tm0.tm_sec;
+      tm1.tm_min = tm0.tm_min;
+      tm1.tm_hour = tm0.tm_hour;
+      tm1.tm_mday = tm0.tm_mday;
+      tm1.tm_mon = tm0.tm_mon;
+      tm1.tm_year = tm0.tm_year;
+      tm1.tm_wday = -1;
+      tm1.tm_isdst = -1;
+      time_t t = mktime (&tm1);
+
+      if (tm1.tm_wday < 0)
+        return false;
+
+      /* Reject dates like "September 31" and times like "25:61".
+         However, allow a seconds count of 60 even in time zones that do
+         not support leap seconds, treating it as the following second;
+         POSIX requires this.  */
+      if (! ((tm0.tm_year ^ tm1.tm_year)
+             | (tm0.tm_mon ^ tm1.tm_mon)
+             | (tm0.tm_mday ^ tm1.tm_mday)
+             | (tm0.tm_hour ^ tm1.tm_hour)
+             | (tm0.tm_min ^ tm1.tm_min)
+             | (tm0.tm_sec ^ tm1.tm_sec)))
+        {
+          if (INT_ADD_WRAPV (t, leapsec, &t))
+            return false;
+          *p = t;
+          return true;
+        }
+
       /* Any mismatch without 60 in the tm_sec field is invalid.  */
       if (tm0.tm_sec != 60)
         return false;
 
-      {
-        /* Allow times like 01:35:60 or 23:59:60.  */
-        time_t dummy;
-        char buf[16];
-        char *b = stpcpy (buf, s);
-        strcpy (b - 2, "59");
-        if (!posixtime (&dummy, buf, syntax_bits))
-          return false;
-      }
+      /* Allow times like 01:35:60 or 23:59:60.  */
+      tm0.tm_sec = 59;
+      leapsec = true;
     }
-
-  *p = t;
-  return true;
 }
diff --git a/modules/posixtm b/modules/posixtm
index 8e3a4db65..5ecc016ae 100644
--- a/modules/posixtm
+++ b/modules/posixtm
@@ -7,9 +7,12 @@ lib/posixtm.c
 m4/posixtm.m4
 
 Depends-on:
+c-ctype
+idx
+intprops
 mktime
 stdbool
-stpcpy
+verify
 
 configure.ac:
 gl_POSIXTM
-- 
2.31.1



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-17 23:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-17 23:03 [PATCH] posixtm: pacify latest GCC Paul Eggert

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).