Implicit assumptions (was: Re: Some fun with -O2)
Walter von Entferndt
walter.von.entferndt at posteo.net
Sat Jan 16 20:20:13 UTC 2021
At Samstag, 16. Januar 2021, 11:23:03 CET, Mark Millard wrote:
> This is the sort of thing where FreeBSD and Linux use a C subset
> for the specific issue, as defined by POSIX.1-2017/"The Open Group
> Base Specifications" Issue 7, 2018 edition/IEEE STd 1003-2017/... .
> For example:
>
> https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
>
> reports (in its own terminology that may not be a full match to C's):
>
> QUOTE
> clock_t shall be an integer or real-floating type. time_t shall be an
> integer type. END QUOTE
>
> Limiting to such a time_t is easier to cover. [...]
> Restricting time_t to integer types leaves a compatible context.
> So: no "conflict" in that respect.
>
My understanding is that check_mktime.c is a test program called by autoconf
or such, designed to run on various UNIX platforms? I mean it does not only
need to run on BSD & Linux.
Maybe something like this will cover the most cases in practice:
--- check_mktime.c.patch ---
--- check_mktime.c.orig 2021-01-15 03:19:33.962253000 +0100
+++ check_mktime.c 2021-01-16 21:00:36.160616000 +0100
@@ -3,6 +3,13 @@
# include <sys/time.h>
# include <time.h>
# include <unistd.h>
+# include <stdlib.h>
+#include <stdint.h>
+# include <stdio.h> /* printf() */
+# include <limits.h> /* CHAR_BIT */
+#if 0
+# include <inttypes.h> /* format spec PRIX64: ll/l + X on 32/64-bit arch */
+#endif
/* Work around redefinition to rpl_putenv by other config tests. */
#undef putenv
@@ -16,6 +23,78 @@
};
#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0]))
+/* Count the bits set in any unsigned integer type.
+ * Returns the precision (width - padding bits - sign bit) iff given
+ * the xxx_MAX value of any integer type, signed or unsigned.
+ * From SEI CERT C Coding Standard:
+ * Rules for Developing Safe, Reliable, and Secure Systems (2016)
+ */
+size_t
+popcount (num)
+uintmax_t num;
+{
+ size_t cnt = 0;
+
+ while (num != 0)
+ {
+ if (num % 2 == 1)
+ cnt++;
+ num >>= 1;
+ }
+ return cnt;
+}
+#define PRECISION(max_value) popcount(max_value)
+
+/* Guess the maximum value of a time_t from it's storage width.
+ * ASSERT time_t is not a floating point, or of any arcane width, or
unsigned.
+ * Only 4...8 byte width of a time_t are tested.
+ * On error: returns (time_t)(-1)
+ */
+time_t
+guess_time_t_max ()
+{
+ time_t t0, t1 = (time_t)(-1);
+ size_t size, prec;
+
+ switch ((size = sizeof(time_t)))
+ {
+ case 4:
+ prec = PRECISION((time_t) 0xFFFFFFFF);
+ break;
+ case 5:
+ prec = PRECISION((time_t) 0xFFFFFFFFFF);
+ break;
+ case 6:
+ prec = PRECISION((time_t) 0xFFFFFFFFFFFF);
+ break;
+ case 7:
+ prec = PRECISION((time_t) 0xFFFFFFFFFFFFFF);
+ break;
+ case 8:
+ prec = PRECISION((time_t) 0xFFFFFFFFFFFFFFFF);
+ break;
+ default:
+ prec = 1;
+ break;
+ }
+ prec--; /* assumption: time_t is signed */
+ if (prec)
+ {
+ t0 = (time_t) 1 << (prec - 1);
+ t1 = t0|(t0 - 1);
+ }
+
+ /* FIXME not portable: time_t can be floating point type,
+ * or another integer type other than long or long long.
+ *
+ fprintf (stderr, "time_t_max\t= 0x%"PRIX64"\n", t1);*/
+ fprintf (stderr, "sizeof(time_t)\t= %2zd byte\n", size);
+ fprintf (stderr, "precision\t= %2zd bit\n", prec);
+ fprintf (stderr, "padding\t\t= %2zd bit\n", size*CHAR_BIT - prec - 1 /*
sign */);
+
+ return t1;
+}
+
/* Fail if mktime fails to convert a date in the spring-forward gap.
Based on a problem report from Andreas Jaeger. */
static void
@@ -106,9 +185,7 @@
time_t t, delta;
int i, j;
- for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
- continue;
- time_t_max--;
+ time_t_max = guess_time_t_max ();
delta = time_t_max / 997; /* a suitable prime number */
for (i = 0; i < N_STRINGS; i++)
{
@@ -128,3 +205,4 @@
spring_forward_gap ();
exit (0);
}
+/*! vi: set ai tabstop=8 shiftwidth=2: */
---
--
=|o) "Stell' Dir vor es geht und keiner kriegt's hin." (Wolfgang Neuss)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: check_mktime.c.patch
Type: text/x-patch
Size: 2932 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20210116/1be9b7ce/attachment.bin>
More information about the freebsd-hackers
mailing list