]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.15] time: fix LoadLocationFromTZData with slim tzdata
authorChristopher Hlubek <christopher.hlubek@networkteam.com>
Mon, 26 Oct 2020 12:44:44 +0000 (13:44 +0100)
committerIan Lance Taylor <iant@golang.org>
Thu, 29 Oct 2020 22:30:25 +0000 (22:30 +0000)
The extend information of a time zone file with last transition < now
could result in a wrong cached zone because it used the zone of the
last transition.

This could lead to wrong zones in systems with slim zoneinfo.

For #42216
Fixes #42138

Change-Id: I7c57c35b5cfa58482ac7925b5d86618c52f5444d
Reviewed-on: https://go-review.googlesource.com/c/go/+/264939
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 70e022e4a83dc996ac4f108e811fbc399ad5565b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/266299
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
src/time/zoneinfo_read.go
src/time/zoneinfo_test.go

index e9f1ab2ec686fd127ad7d07d44c8fc0e360a2cdb..22a60f32116e7b6477d0237d1b631ba0a395dda7 100644 (file)
@@ -323,17 +323,26 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
                if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
                        l.cacheStart = tx[i].when
                        l.cacheEnd = omega
+                       zoneIdx := tx[i].index
                        if i+1 < len(tx) {
                                l.cacheEnd = tx[i+1].when
                        } else if l.extend != "" {
                                // If we're at the end of the known zone transitions,
                                // try the extend string.
-                               if _, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok {
+                               if name, _, estart, eend, ok := tzset(l.extend, l.cacheEnd, sec); ok {
                                        l.cacheStart = estart
                                        l.cacheEnd = eend
+                                       // Find the zone that is returned by tzset,
+                                       // the last transition is not always the correct zone.
+                                       for i, z := range l.zone {
+                                               if z.name == name {
+                                                       zoneIdx = uint8(i)
+                                                       break
+                                               }
+                                       }
                                }
                        }
-                       l.cacheZone = &l.zone[tx[i].index]
+                       l.cacheZone = &l.zone[zoneIdx]
                        break
                }
        }
index 72829bc9fb22aa027c2d46ed139283b837f45742..277b68f798dd669c67dea5c7b7c0e942902de9d5 100644 (file)
@@ -183,6 +183,25 @@ func TestMalformedTZData(t *testing.T) {
        }
 }
 
+func TestLoadLocationFromTZDataSlim(t *testing.T) {
+       // A 2020b slim tzdata for Europe/Berlin
+       tzData := "TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00TZif2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x04\x00\x00\x00\x12\xff\xff\xff\xffo\xa2a\xf8\xff\xff\xff\xff\x9b\f\x17`\xff\xff\xff\xff\x9b\xd5\xda\xf0\xff\xff\xff\xff\x9cٮ\x90\xff\xff\xff\xff\x9d\xa4\xb5\x90\xff\xff\xff\xff\x9e\xb9\x90\x90\xff\xff\xff\xff\x9f\x84\x97\x90\xff\xff\xff\xff\xc8\tq\x90\xff\xff\xff\xff\xcc\xe7K\x10\xff\xff\xff\xffͩ\x17\x90\xff\xff\xff\xff\u03a2C\x10\xff\xff\xff\xffϒ4\x10\xff\xff\xff\xffЂ%\x10\xff\xff\xff\xff\xd1r\x16\x10\xff\xff\xff\xffѶ\x96\x00\xff\xff\xff\xff\xd2X\xbe\x80\xff\xff\xff\xffҡO\x10\xff\xff\xff\xff\xd3c\x1b\x90\xff\xff\xff\xff\xd4K#\x90\xff\xff\xff\xff\xd59\xd1 \xff\xff\xff\xff\xd5g\xe7\x90\xff\xff\xff\xffըs\x00\xff\xff\xff\xff\xd6)\xb4\x10\xff\xff\xff\xff\xd7,\x1a\x10\xff\xff\xff\xff\xd8\t\x96\x10\xff\xff\xff\xff\xd9\x02\xc1\x90\xff\xff\xff\xff\xd9\xe9x\x10\x00\x00\x00\x00\x13MD\x10\x00\x00\x00\x00\x143\xfa\x90\x00\x00\x00\x00\x15#\xeb\x90\x00\x00\x00\x00\x16\x13ܐ\x00\x00\x00\x00\x17\x03͐\x00\x00\x00\x00\x17\xf3\xbe\x90\x00\x00\x00\x00\x18㯐\x00\x00\x00\x00\x19Ӡ\x90\x00\x00\x00\x00\x1aÑ\x90\x00\x00\x00\x00\x1b\xbc\xbd\x10\x00\x00\x00\x00\x1c\xac\xae\x10\x00\x00\x00\x00\x1d\x9c\x9f\x10\x00\x00\x00\x00\x1e\x8c\x90\x10\x00\x00\x00\x00\x1f|\x81\x10\x00\x00\x00\x00 lr\x10\x00\x00\x00\x00!\\c\x10\x00\x00\x00\x00\"LT\x10\x00\x00\x00\x00#<E\x10\x00\x00\x00\x00$,6\x10\x00\x00\x00\x00%\x1c'\x10\x00\x00\x00\x00&\f\x18\x10\x00\x00\x00\x00'\x05C\x90\x00\x00\x00\x00'\xf54\x90\x00\x00\x00\x00(\xe5%\x90\x00\x00\x00\x00)\xd5\x16\x90\x00\x00\x00\x00*\xc5\a\x90\x00\x00\x00\x00+\xb4\xf8\x90\x00\x00\x00\x00,\xa4\xe9\x90\x00\x00\x00\x00-\x94ڐ\x00\x00\x00\x00.\x84ː\x00\x00\x00\x00/t\xbc\x90\x00\x00\x00\x000d\xad\x90\x00\x00\x00\x001]\xd9\x10\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x03\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x02\x01\x00\x00\f\x88\x00\x00\x00\x00\x1c \x01\x04\x00\x00\x0e\x10\x00\t\x00\x00*0\x01\rLMT\x00CEST\x00CET\x00CEMT\x00\nCET-1CEST,M3.5.0,M10.5.0/3\n"
+
+       reference, err := time.LoadLocationFromTZData("Europe/Berlin", []byte(tzData))
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       d := time.Date(2020, time.October, 29, 15, 30, 0, 0, reference)
+       tzName, tzOffset := d.Zone()
+       if want := "CET"; tzName != want {
+               t.Errorf("Zone name == %s, want %s", tzName, want)
+       }
+       if want := 3600; tzOffset != want {
+               t.Errorf("Zone offset == %d, want %d", tzOffset, want)
+       }
+}
+
 func TestTzset(t *testing.T) {
        for _, test := range []struct {
                inStr string