[PATCH 1/2] Be more consistent about macro true/false vs 1/0
* private.h (HAVE_GETTEXT, HAVE_SYS_STAT_H, HAVE_UNISTD_H) (HAVE_STDINT_H, HAVE_STRTOLL, HAVE_STDCKDINT_H) (HAVE_DECL_TIMEGM): * strftime.c (MKTIME_MIGHT_OVERFLOW, DEPRECATE_TWO_DIGIT_YEARS): Default to 1 or 0, not to true or false, since these can be set via the command line as per the Makefile. * private.h (TZ_TIME_T): Set to true or false, not to 1 or 0, since this is boolean and is not set via the command line. --- private.h | 26 +++++++++++++------------- strftime.c | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/private.h b/private.h index 6088d885..1e4e69a4 100644 --- a/private.h +++ b/private.h @@ -88,11 +88,11 @@ #if !defined HAVE_GETTEXT && defined __has_include # if __has_include(<libintl.h>) -# define HAVE_GETTEXT true +# define HAVE_GETTEXT 1 # endif #endif #ifndef HAVE_GETTEXT -# define HAVE_GETTEXT false +# define HAVE_GETTEXT 0 #endif #ifndef HAVE_INCOMPATIBLE_CTIME_R @@ -125,20 +125,20 @@ #if !defined HAVE_SYS_STAT_H && defined __has_include # if !__has_include(<sys/stat.h>) -# define HAVE_SYS_STAT_H false +# define HAVE_SYS_STAT_H 0 # endif #endif #ifndef HAVE_SYS_STAT_H -# define HAVE_SYS_STAT_H true +# define HAVE_SYS_STAT_H 1 #endif #if !defined HAVE_UNISTD_H && defined __has_include # if !__has_include(<unistd.h>) -# define HAVE_UNISTD_H false +# define HAVE_UNISTD_H 0 # endif #endif #ifndef HAVE_UNISTD_H -# define HAVE_UNISTD_H true +# define HAVE_UNISTD_H 1 #endif #ifndef NETBSD_INSPIRED @@ -312,7 +312,7 @@ ** stdint.h, even with pre-C99 compilers. */ #if !defined HAVE_STDINT_H && defined __has_include -# define HAVE_STDINT_H true /* C23 __has_include implies C99 stdint.h. */ +# define HAVE_STDINT_H 1 /* C23 __has_include implies C99 stdint.h. */ #endif #ifndef HAVE_STDINT_H # define HAVE_STDINT_H \ @@ -386,7 +386,7 @@ typedef int int_fast32_t; # ifdef LLONG_MAX typedef long long intmax_t; # ifndef HAVE_STRTOLL -# define HAVE_STRTOLL true +# define HAVE_STRTOLL 1 # endif # if HAVE_STRTOLL # define strtoimax strtoll @@ -466,7 +466,7 @@ typedef unsigned long uintmax_t; hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG. */ #if !defined HAVE_STDCKDINT_H && defined __has_include # if __has_include(<stdckdint.h>) -# define HAVE_STDCKDINT_H true +# define HAVE_STDCKDINT_H 1 # endif #endif #ifdef HAVE_STDCKDINT_H @@ -634,9 +634,9 @@ typedef unsigned long uintmax_t; ** typical platforms. */ #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0 -# define TZ_TIME_T 1 +# define TZ_TIME_T true #else -# define TZ_TIME_T 0 +# define TZ_TIME_T false #endif #if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T @@ -753,9 +753,9 @@ void tzset(void); || defined __GLIBC__ || defined __tm_zone /* musl */ \ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \ || (defined __APPLE__ && defined __MACH__)) -# define HAVE_DECL_TIMEGM true +# define HAVE_DECL_TIMEGM 1 # else -# define HAVE_DECL_TIMEGM false +# define HAVE_DECL_TIMEGM 0 # endif #endif #if !HAVE_DECL_TIMEGM && !defined timegm diff --git a/strftime.c b/strftime.c index fc0c87d2..487a5234 100644 --- a/strftime.c +++ b/strftime.c @@ -79,9 +79,9 @@ !defined __NetBSD_Version__ || __NetBSD_Version__ < 600000000) \ && (/* OpenBSD 5.5 (2014-05-01) and later has 64-bit time_t. */ \ !defined OpenBSD || OpenBSD < 201405))) -# define MKTIME_MIGHT_OVERFLOW true +# define MKTIME_MIGHT_OVERFLOW 1 # else -# define MKTIME_MIGHT_OVERFLOW false +# define MKTIME_MIGHT_OVERFLOW 0 # endif #endif /* Check that MKTIME_MIGHT_OVERFLOW is consistent with time_t's range. */ @@ -95,7 +95,7 @@ static_assert(MKTIME_MIGHT_OVERFLOW #endif #ifndef DEPRECATE_TWO_DIGIT_YEARS -# define DEPRECATE_TWO_DIGIT_YEARS false +# define DEPRECATE_TWO_DIGIT_YEARS 0 #endif struct lc_time_T { -- 2.43.0
* Makefile, NEWS: Mention this. * localtime.c (TZNAME_MAXIMUM): Default to 254, not 255. (desigidx_type): New type. (struct ttinfo, init_ttinfo): Use it. (struct ttinfo): Shrink tt_utoff from int_fast32_t to int_least32_t. On x86-64 with GCC 14 -O2 these changes shrink struct state from 25480 to 21384 bytes, and shrink the size of the localtime.o insns from 33285 to 32485 bytes. They also fix an unlikely bug if the builder compiles with a TZNAME_MAXIMUM value not less than INT_MAX. * private.h (int_least32_t) [!INT_LEAST32_MAX]: Define, for benefit of pre-C99 platforms. --- Makefile | 2 +- NEWS | 10 ++++++++++ localtime.c | 34 +++++++++++++++++++++++++--------- private.h | 4 ++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 01db50d6..e8574551 100644 --- a/Makefile +++ b/Makefile @@ -286,7 +286,7 @@ LDLIBS= # This mishandles some past timestamps, as US DST rules have changed. # It also mishandles settings like TZ='EET-2EEST' for eastern Europe, # as Europe and US DST rules differ. -# -DTZNAME_MAXIMUM=N to limit time zone abbreviations to N bytes (default 255) +# -DTZNAME_MAXIMUM=N to limit time zone abbreviations to N bytes (default 254) # -DUNINIT_TRAP if reading uninitialized storage can cause problems # other than simply getting garbage data # -DUSE_LTZ=0 to build zdump with the system time zone library diff --git a/NEWS b/NEWS index fb3d5609..a484ded2 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,16 @@ Unreleased, experimental changes struct tm component near INT_MIN or INT_MAX overflows when a lower-order component carries into it. + TZNAME_MAXIMUM, the maximum number of bytes in a proleptic TZ + string's time zone abbreviation, now defaults to 254 not 255. + This helps reduce the size of internal state from 25480 to 21384 + on common platforms. This change should not be a problem, as + nobody uses such long "abbreviations" and the longstanding tzcode + maximum was 16 until release 2023a. For those who prefer no + arbitrary limits, you can now specify TZNAME_MAXIMUM values up to + PTRDIFF_MAX, a limit forced by C anyway; formerly tzcode silently + misbehaved unless TZNAME_MAXIMUM was less than INT_MAX. + Changes to documentation Cite Internet RFC 9636, which obsoletes RFC 8536 for TZif format. diff --git a/localtime.c b/localtime.c index e6d79d05..492965d9 100644 --- a/localtime.c +++ b/localtime.c @@ -145,10 +145,31 @@ static char const *utc = etc_utc + sizeof "Etc/" - 1; # define TZDEFRULESTRING ",M3.2.0,M11.1.0" #endif +/* Limit to time zone abbreviation length in proleptic TZ strings. + This is distinct from TZ_MAX_CHARS, which limits TZif file contents. + It defaults to 254, not 255, so that desigidx_type can be an unsigned char. + unsigned char suffices for TZif files, so the only reason to increase + TZNAME_MAXIMUM is to support TZ strings specifying abbreviations + longer than 254 bytes. There is little reason to do that, though, + as strings that long are hardly "abbreviations". */ +#ifndef TZNAME_MAXIMUM +# define TZNAME_MAXIMUM 254 +#endif + +#if TZNAME_MAXIMUM < UCHAR_MAX +typedef unsigned char desigidx_type; +#elif TZNAME_MAXIMUM < INT_MAX +typedef int desigidx_type; +#elif TZNAME_MAXIMUM < PTRDIFF_MAX +typedef ptrdiff_t desigidx_type; +#else +# error "TZNAME_MAXIMUM too large" +#endif + struct ttinfo { /* time type information */ - int_fast32_t tt_utoff; /* UT offset in seconds */ + int_least32_t tt_utoff; /* UT offset in seconds */ + desigidx_type tt_desigidx; /* abbreviation list index */ bool tt_isdst; /* used to set tm_isdst */ - int tt_desigidx; /* abbreviation list index */ bool tt_ttisstd; /* transition is std time */ bool tt_ttisut; /* transition is UT */ }; @@ -167,12 +188,6 @@ static char const UNSPEC[] = "-00"; for ttunspecified to work without crashing. */ enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 }; -/* Limit to time zone abbreviation length in proleptic TZ strings. - This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */ -#ifndef TZNAME_MAXIMUM -# define TZNAME_MAXIMUM 255 -#endif - /* A representation of the contents of a TZif file. Ideally this would have no size limits; the following sizes should suffice for practical use. This struct should not be too large, as instances @@ -273,7 +288,8 @@ long altzone; /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */ static void -init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx) +init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, + desigidx_type desigidx) { s->tt_utoff = utoff; s->tt_isdst = isdst; diff --git a/private.h b/private.h index 1e4e69a4..edc188a2 100644 --- a/private.h +++ b/private.h @@ -382,6 +382,10 @@ typedef int int_fast32_t; # endif #endif +#ifndef INT_LEAST32_MAX +typedef int_fast32_t int_least32_t; +#endif + #ifndef INTMAX_MAX # ifdef LLONG_MAX typedef long long intmax_t; -- 2.43.0
participants (1)
-
Paul Eggert