From owner-freebsd-hackers@freebsd.org Sat Jan 16 20:20:13 2021 Return-Path: Delivered-To: freebsd-hackers@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 2145B4E9462 for ; Sat, 16 Jan 2021 20:20:13 +0000 (UTC) (envelope-from "") Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.142]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4DJ8YS1zSwz4lHn for ; Sat, 16 Jan 2021 20:20:12 +0000 (UTC) (envelope-from "") Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id 147632400FD for ; Sat, 16 Jan 2021 21:20:10 +0100 (CET) Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4DJ8YP1Qs8z9rxw; Sat, 16 Jan 2021 21:20:09 +0100 (CET) From: Walter von Entferndt To: Mark Millard Cc: freebsd-hackers@freebsd.org Subject: Re: Implicit assumptions (was: Re: Some fun with -O2) Date: Sat, 16 Jan 2021 21:19:44 +0100 Message-ID: <1648904.MsCH1bHPGx@t450s.local.lan> In-Reply-To: <7623BADF-5FA9-4712-8D85-A1D2B82E3F74@yahoo.com> References: <1725854.nNRVL2rNYg@t450s.local.lan> <7623BADF-5FA9-4712-8D85-A1D2B82E3F74@yahoo.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart1974885.4WAli8B44Z" Content-Transfer-Encoding: 7Bit X-Rspamd-Queue-Id: 4DJ8YS1zSwz4lHn X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=fail reason="No valid SPF, No valid DKIM" header.from=posteo.net (policy=none); spf=none (mx1.freebsd.org: domain of mout02.posteo.de has no SPF policy when checking 185.67.36.142) smtp.helo=mout02.posteo.de X-Spamd-Result: default: False [-2.70 / 15.00]; RCVD_VIA_SMTP_AUTH(0.00)[]; CTE_CASE(0.50)[]; ARC_NA(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; NEURAL_HAM_LONG(-1.00)[-1.000]; MIME_GOOD(-0.10)[multipart/mixed,text/plain,text/x-patch]; PREVIOUSLY_DELIVERED(0.00)[freebsd-hackers@freebsd.org]; HAS_ATTACHMENT(0.00)[]; RCVD_COUNT_THREE(0.00)[3]; TO_MATCH_ENVRCPT_SOME(0.00)[]; RCVD_IN_DNSWL_MED(-0.20)[185.67.36.142:from]; RCPT_COUNT_TWO(0.00)[2]; NEURAL_HAM_SHORT(-1.00)[-1.000]; R_SPF_NA(0.00)[no SPF record]; FREEMAIL_TO(0.00)[yahoo.com]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+]; ASN(0.00)[asn:8495, ipnet:185.67.36.0/23, country:DE]; RCVD_TLS_ALL(0.00)[]; MAILMAN_DEST(0.00)[freebsd-hackers]; DMARC_POLICY_SOFTFAIL(0.10)[posteo.net : No valid SPF, No valid DKIM,none] X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 Jan 2021 20:20:13 -0000 This is a multi-part message in MIME format. --nextPart1974885.4WAli8B44Z Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" 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 # include # include +# include +#include +# include /* printf() */ +# include /* CHAR_BIT */ +#if 0 +# include /* 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) --nextPart1974885.4WAli8B44Z Content-Disposition: attachment; filename="check_mktime.c.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="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 # include # include +# include +#include +# include /* printf() */ +# include /* CHAR_BIT */ +#if 0 +# include /* 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: */ --nextPart1974885.4WAli8B44Z--