From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by sourceware.org (Postfix) with ESMTPS id 43EC2385842C for ; Fri, 17 Dec 2021 00:57:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 43EC2385842C From: Hans-Peter Nilsson To: CC: , In-Reply-To: <87mtldojl3.fsf@oldenburg.str.redhat.com> Subject: [PATCH v2] timezone: handle truncated timezones from tzcode-2021d and later (BZ #28707) MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8BIT Message-ID: <20211217005744.E099F203C8@pchp3.se.axis.com> Date: Fri, 17 Dec 2021 01:57:44 +0100 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Dec 2021 00:57:48 -0000 I'm assisting Christopher, who sent the first version; this one includes a test-case and a bugzilla report reference. We're both covered by Axis' copyright assignment. Tested on x86_64-linux (Debian 9). brgds, H-P 8< ------------------------------------------------------ >8 When using a timezone file generated by the zic in IANA tzcode-2021d a.k.a. tzlib-2021d (also in tzlib-2021e; current as of this writing), glibc asserts in __tzfile_read (on e.g. tzset() for this file) and you may find lines matching "tzfile.c:435: __tzfile_read: Assertion `num_types == 1' failed" in your syslog. Attached is a test-case including the tzfile for Asuncion generated by tzlib-2021e as follows, using the tzlib-2021e zic: "zic -d DEST -r @1546300800 -L /dev/null -b slim SOURCE/southamerica". Note that in its type 2 header, it has two entries in its "time-types" array (types), but only one entry in its "transition types" array (type_idxs). This is valid and expected already in the published RFC8536, and not even frowned upon: "Local time for timestamps before the first transition is specified by the first time type (time type 0)" ... "every nonzero local time type index SHOULD appear at least once in the transition type array". Note the "nonzero ... index". Until the 2021d zic, index 0 has been shared by the first valid transition but with 2021d it's separate, set apart as a placeholder and only "implicitly" indexed. (A draft update of the RFC mandates that the entry at index 0 is a placeholder in this case, hence can no longer be shared.) * time/tzfile.c: Don't assert when no transitions are found. * timezone/Makefile, timezone/tst-pr28707.c, timezone/testdata/XT5: New test. Co-authored-by: Christopher Wong --- time/tzfile.c | 4 ++-- timezone/Makefile | 4 +++- timezone/testdata/XT5 | Bin 0 -> 156 bytes timezone/tst-bz28707.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 timezone/testdata/XT5 create mode 100644 timezone/tst-bz28707.c diff --git a/time/tzfile.c b/time/tzfile.c index 190a777152b3..8668392ad387 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -431,8 +431,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap) if (__tzname[0] == NULL) { /* This should only happen if there are no transition rules. - In this case there should be only one single type. */ - assert (num_types == 1); + In this case there's usually only one single type, unless + e.g. the data file has a truncated time-range. */ __tzname[0] = __tzstring (zone_names); } if (__tzname[1] == NULL) diff --git a/timezone/Makefile b/timezone/Makefile index c624a189b322..369b3e1698ba 100644 --- a/timezone/Makefile +++ b/timezone/Makefile @@ -23,7 +23,7 @@ subdir := timezone include ../Makeconfig others := zdump zic -tests := test-tz tst-timezone tst-tzset +tests := test-tz tst-timezone tst-tzset tst-bz28707 generated-dirs += testdata @@ -85,10 +85,12 @@ $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \ America/Sao_Paulo Asia/Tokyo \ Europe/London) $(objpfx)tst-tzset.out: $(addprefix $(testdata)/XT, 1 2 3 4) +$(objpfx)tst-bz28707.out: $(testdata)/XT5 test-tz-ENV = TZDIR=$(testdata) tst-timezone-ENV = TZDIR=$(testdata) tst-tzset-ENV = TZDIR=$(testdata) +tst-bz28707-ENV = TZDIR=$(testdata) # Note this must come second in the deps list for $(built-program-cmd) to work. zic-deps = $(objpfx)zic $(leapseconds) yearistype diff --git a/timezone/testdata/XT5 b/timezone/testdata/XT5 new file mode 100644 index 0000000000000000000000000000000000000000..aadcd6dccab37d1177d2c0ca725ea56c5dc7ca48 GIT binary patch literal 156 zcmWHE%1kq2AP5+NDnJ+nLI`UCDP;m;4v_j7t+fqMz5oATy}-z#Yhb{jYhcX4Wut3g cVrK#*jqP-N4Gr`R^$he4bbO8VOh61S07fYg0{{R3 literal 0 HcmV?d00001 diff --git a/timezone/tst-bz28707.c b/timezone/tst-bz28707.c new file mode 100644 index 000000000000..0a9df1e9a094 --- /dev/null +++ b/timezone/tst-bz28707.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +/* Test that we can use a truncated timezone-file, where the time-type + at index 0 is not indexed by the transition-types array (and the + transition-types array does not contain at least both one DST and one + normal time members). */ + +static int +do_test (void) +{ + if (setenv ("TZ", "XT5", 1)) + { + puts ("setenv failed."); + return 1; + } + + tzset (); + + return + /* Sanity-check that we got the right timezone-name for DST. For + normal time, we're likely to get "-00" (the "unspecified" marker), + even though the POSIX timezone string says "-04". Let's not test + that. */ + !(strcmp (tzname[1], "-03") == 0); +} +#include -- 2.11.0