Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: z...@debian.org
Please unblock package golang-golang-x-text [ Reason ] New upstream bugfix release, which fixes 1. CVE-2020-28851 In x/text in Go 1.15.4, an "index out of range" panic occurs in language.ParseAcceptLanguage while parsing the -u- extension. (x/text/language is supposed to be able to parse an HTTP Accept-Language header.) 2. x/text: panic in regionGroupDist https://github.com/golang/go/issues/43834 The package is key package, thus it needs unblock manually. [ Impact ] Security issue is not fixed. [ Tests ] Upstream thorough unit tests. [ Risks ] The change of the code is complex which I can't fully reviewed, but since it fixes security problem, it may should be complex. The code is reviewed by official Go team, and I trust them. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] There are only three commits between 0.3.5 and 0.3.6 https://github.com/golang/text/compare/v0.3.5...v0.3.6 Two commits fix the issue mentioned above. And another one is code format, which unfortunately makes the diff quite large. I will omit the format change in debdiff attached in this request. unblock golang-golang-x-text/0.3.6-1 diff -Nru golang-golang-x-text-0.3.5/debian/changelog golang-golang-x-text-0.3.6/debian/changelog --- golang-golang-x-text-0.3.5/debian/changelog 2021-01-19 02:11:19.000000000 +0800 +++ golang-golang-x-text-0.3.6/debian/changelog 2021-04-07 02:18:47.000000000 +0800 @@ -1,3 +1,10 @@ +golang-golang-x-text (0.3.6-1) unstable; urgency=medium + + * Team upload. + * New upstream release v0.3.6 (Closes: #980001, CVE-2020-28851) + + -- Shengjing Zhu <z...@debian.org> Wed, 07 Apr 2021 02:18:47 +0800 + golang-golang-x-text (0.3.5-1) unstable; urgency=medium * Team upload. diff -Nru golang-golang-x-text-0.3.5/debian/control golang-golang-x-text-0.3.6/debian/control --- golang-golang-x-text-0.3.5/debian/control 2021-01-19 02:11:19.000000000 +0800 +++ golang-golang-x-text-0.3.6/debian/control 2021-04-07 02:18:47.000000000 +0800 @@ -1,13 +1,13 @@ Source: golang-golang-x-text Maintainer: Debian Go Packaging Team <team+pkg...@tracker.debian.org> Uploaders: MartÃn Ferrari <tin...@debian.org>, - Anthony Fok <f...@debian.org> + Anthony Fok <f...@debian.org>, Section: golang Testsuite: autopkgtest-pkg-go Priority: optional Build-Depends: debhelper-compat (= 13), dh-golang (>= 1.31~), - golang-any (>= 2:1.7~) + golang-any (>= 2:1.7~), Standards-Version: 4.5.1 Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-golang-x-text Vcs-Git: https://salsa.debian.org/go-team/packages/golang-golang-x-text.git @@ -18,8 +18,8 @@ Package: golang-golang-x-text-dev Architecture: all Multi-Arch: foreign -Depends: ${shlibs:Depends}, - ${misc:Depends} +Depends: ${misc:Depends}, + ${shlibs:Depends}, Description: Supplementary Go text-related libraries golang.org/x/text is a repository of text-related packages, such as character encodings, text transformations, and locale-specific text handling. diff -Nru golang-golang-x-text-0.3.5/debian/watch golang-golang-x-text-0.3.6/debian/watch --- golang-golang-x-text-0.3.5/debian/watch 2021-01-19 02:11:19.000000000 +0800 +++ golang-golang-x-text-0.3.6/debian/watch 2021-04-07 02:18:47.000000000 +0800 @@ -1,4 +1,3 @@ version=4 -opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%golang-golang-x-text-$1.tar.gz%" \ - https://github.com/golang/text/releases \ - (?:.*?/)?v?(\d[\d.]*)\.tar\.gz +opts="mode=git, pgpmode=none" \ + https://github.com/golang/text refs/tags/v([\d\.]+) diff -Nru golang-golang-x-text-0.3.5/internal/language/language.go golang-golang-x-text-0.3.6/internal/language/language.go --- golang-golang-x-text-0.3.5/internal/language/language.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/internal/language/language.go 2021-03-30 13:48:03.000000000 +0800 @@ -303,9 +303,17 @@ // are of the allowed values defined for the Unicode locale extension ('u') in // https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. // TypeForKey will traverse the inheritance chain to get the correct value. +// +// If there are multiple types associated with a key, only the first will be +// returned. If there is no type associated with a key, it returns the empty +// string. func (t Tag) TypeForKey(key string) string { - if start, end, _ := t.findTypeForKey(key); end != start { - return t.str[start:end] + if _, start, end, _ := t.findTypeForKey(key); end != start { + s := t.str[start:end] + if p := strings.IndexByte(s, '-'); p >= 0 { + s = s[:p] + } + return s } return "" } @@ -329,13 +337,13 @@ // Remove the setting if value is "". if value == "" { - start, end, _ := t.findTypeForKey(key) - if start != end { - // Remove key tag and leading '-'. - start -= 4 - + start, sep, end, _ := t.findTypeForKey(key) + if start != sep { // Remove a possible empty extension. - if (end == len(t.str) || t.str[end+2] == '-') && t.str[start-2] == '-' { + switch { + case t.str[start-2] != '-': // has previous elements. + case end == len(t.str), // end of string + end+2 < len(t.str) && t.str[end+2] == '-': // end of extension start -= 2 } if start == int(t.pVariant) && end == len(t.str) { @@ -381,14 +389,14 @@ t.str = string(buf[:uStart+len(b)]) } else { s := t.str - start, end, hasExt := t.findTypeForKey(key) - if start == end { + start, sep, end, hasExt := t.findTypeForKey(key) + if start == sep { if hasExt { b = b[2:] } - t.str = fmt.Sprintf("%s-%s%s", s[:start], b, s[end:]) + t.str = fmt.Sprintf("%s-%s%s", s[:sep], b, s[end:]) } else { - t.str = fmt.Sprintf("%s%s%s", s[:start], value, s[end:]) + t.str = fmt.Sprintf("%s-%s%s", s[:start+3], value, s[end:]) } } return t, nil @@ -399,10 +407,10 @@ // wasn't found. The hasExt return value reports whether an -u extension was present. // Note: the extensions are typically very small and are likely to contain // only one key-type pair. -func (t Tag) findTypeForKey(key string) (start, end int, hasExt bool) { +func (t Tag) findTypeForKey(key string) (start, sep, end int, hasExt bool) { p := int(t.pExt) if len(key) != 2 || p == len(t.str) || p == 0 { - return p, p, false + return p, p, p, false } s := t.str @@ -410,10 +418,10 @@ for p++; s[p] != 'u'; p++ { if s[p] > 'u' { p-- - return p, p, false + return p, p, p, false } if p = nextExtension(s, p); p == len(s) { - return len(s), len(s), false + return len(s), len(s), len(s), false } } // Proceed to the hyphen following the extension name. @@ -424,40 +432,28 @@ // Iterate over keys until we get the end of a section. for { - // p points to the hyphen preceding the current token. - if p3 := p + 3; s[p3] == '-' { - // Found a key. - // Check whether we just processed the key that was requested. - if curKey == key { - return start, p, true - } - // Set to the next key and continue scanning type tokens. - curKey = s[p+1 : p3] - if curKey > key { - return p, p, true - } - // Start of the type token sequence. - start = p + 4 - // A type is at least 3 characters long. - p += 7 // 4 + 3 - } else { - // Attribute or type, which is at least 3 characters long. - p += 4 + end = p + for p++; p < len(s) && s[p] != '-'; p++ { } - // p points past the third character of a type or attribute. - max := p + 5 // maximum length of token plus hyphen. - if len(s) < max { - max = len(s) - } - for ; p < max && s[p] != '-'; p++ { - } - // Bail if we have exhausted all tokens or if the next token starts - // a new extension. - if p == len(s) || s[p+2] == '-' { - if curKey == key { - return start, p, true + n := p - end - 1 + if n <= 2 && curKey == key { + if sep < end { + sep++ + } + return start, sep, end, true + } + switch n { + case 0, // invalid string + 1: // next extension + return end, end, end, true + case 2: + // next key + curKey = s[end+1 : p] + if curKey > key { + return end, end, end, true } - return p, p, true + start = end + sep = p } } } diff -Nru golang-golang-x-text-0.3.5/internal/language/language_test.go golang-golang-x-text-0.3.6/internal/language/language_test.go --- golang-golang-x-text-0.3.5/internal/language/language_test.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/internal/language/language_test.go 2021-03-30 13:48:03.000000000 +0800 @@ -432,7 +432,9 @@ {"co", "pinyin", "en-u-co-phonebk-cu-xau", "en-u-co-pinyin-cu-xau", false}, {"co", "pinyin", "en-u-co-phonebk-v-xx", "en-u-co-pinyin-v-xx", false}, {"co", "pinyin", "en-u-co-phonebk-x-x", "en-u-co-pinyin-x-x", false}, + {"co", "pinyin", "en-u-co-x-x", "en-u-co-pinyin-x-x", false}, {"nu", "arabic", "en-u-co-phonebk-nu-vaai", "en-u-co-phonebk-nu-arabic", false}, + {"nu", "arabic", "en-u-co-phonebk-nu", "en-u-co-phonebk-nu-arabic", false}, // add to existing -u extension {"co", "pinyin", "en-u-ca-gregory", "en-u-ca-gregory-co-pinyin", false}, {"co", "pinyin", "en-u-ca-gregory-nu-vaai", "en-u-ca-gregory-co-pinyin-nu-vaai", false}, @@ -441,8 +443,12 @@ {"ca", "gregory", "en-u-co-pinyin", "en-u-ca-gregory-co-pinyin", false}, // remove pair {"co", "", "en-u-co-phonebk", "en", false}, + {"co", "", "en-u-co", "en", false}, + {"co", "", "en-u-co-v", "en", false}, + {"co", "", "en-u-co-v-", "en", false}, {"co", "", "en-u-ca-gregory-co-phonebk", "en-u-ca-gregory", false}, {"co", "", "en-u-co-phonebk-nu-arabic", "en-u-nu-arabic", false}, + {"co", "", "en-u-co-nu-arabic", "en-u-nu-arabic", false}, {"co", "", "en", "en", false}, // add -u extension {"co", "pinyin", "en", "en-u-co-pinyin", false}, @@ -504,6 +510,8 @@ {"cu", false, "en-a-va-v-va", "en-a-va"}, {"cu", false, "en-x-a", "en"}, // Tags with the -u extension. + {"nu", true, "en-u-cu-nu", "en-u-cu"}, + {"cu", true, "en-u-cu-nu", "en-u"}, {"co", true, "en-u-co-standard", "standard"}, {"co", true, "yue-u-co-pinyin", "pinyin"}, {"co", true, "en-u-co-abc", "abc"}, @@ -519,9 +527,9 @@ {"cu", true, "en-u-co-abc-def-nu-arabic", "en-u-co-abc-def"}, } for i, tt := range tests { - start, end, hasExt := Make(tt.in).findTypeForKey(tt.key) - if start != end { - res := tt.in[start:end] + start, sep, end, hasExt := Make(tt.in).findTypeForKey(tt.key) + if sep != end { + res := tt.in[sep:end] if res != tt.out { t.Errorf("%d:%s: was %q; want %q", i, tt.in, res, tt.out) } diff -Nru golang-golang-x-text-0.3.5/internal/language/parse.go golang-golang-x-text-0.3.6/internal/language/parse.go --- golang-golang-x-text-0.3.5/internal/language/parse.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/internal/language/parse.go 2021-03-30 13:48:03.000000000 +0800 @@ -138,7 +138,7 @@ b = make([]byte, n) copy(b, s.b[:oldStart]) } else { - b = s.b[:n:n] + b = s.b[:n] } copy(b[end:], s.b[oldEnd:]) s.b = b @@ -483,7 +483,7 @@ func parseExtension(scan *scanner) int { start, end := scan.start, scan.end switch scan.token[0] { - case 'u': + case 'u': // https://www.ietf.org/rfc/rfc6067.txt attrStart := end scan.scan() for last := []byte{}; len(scan.token) > 2; scan.scan() { @@ -503,27 +503,29 @@ last = scan.token end = scan.end } + // Scan key-type sequences. A key is of length 2 and may be followed + // by 0 or more "type" subtags from 3 to the maximum of 8 letters. var last, key []byte for attrEnd := end; len(scan.token) == 2; last = key { key = scan.token - keyEnd := scan.end - end = scan.acceptMinSize(3) + end = scan.end + for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() { + end = scan.end + } // TODO: check key value validity - if keyEnd == end || bytes.Compare(key, last) != 1 { + if bytes.Compare(key, last) != 1 || scan.err != nil { // We have an invalid key or the keys are not sorted. // Start scanning keys from scratch and reorder. p := attrEnd + 1 scan.next = p keys := [][]byte{} for scan.scan(); len(scan.token) == 2; { - keyStart, keyEnd := scan.start, scan.end - end = scan.acceptMinSize(3) - if keyEnd != end { - keys = append(keys, scan.b[keyStart:end]) - } else { - scan.setError(ErrSyntax) - end = keyStart + keyStart := scan.start + end = scan.end + for scan.scan(); end < scan.end && len(scan.token) > 2; scan.scan() { + end = scan.end } + keys = append(keys, scan.b[keyStart:end]) } sort.Stable(bytesSort{keys, 2}) if n := len(keys); n > 0 { @@ -547,7 +549,7 @@ break } } - case 't': + case 't': // https://www.ietf.org/rfc/rfc6497.txt scan.scan() if n := len(scan.token); n >= 2 && n <= 3 && isAlpha(scan.token[1]) { _, end = parseTag(scan) diff -Nru golang-golang-x-text-0.3.5/internal/language/parse_test.go golang-golang-x-text-0.3.6/internal/language/parse_test.go --- golang-golang-x-text-0.3.5/internal/language/parse_test.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/internal/language/parse_test.go 2021-03-30 13:48:03.000000000 +0800 @@ -164,13 +164,13 @@ {in: "en-9-aa-0-aa-z-bb-x-a", lang: "en", extList: []string{"0-aa", "9-aa", "z-bb", "x-a"}, changed: true}, {in: "en-u-c", lang: "en", ext: "", invalid: true}, {in: "en-u-co-phonebk", lang: "en", ext: "u-co-phonebk"}, - {in: "en-u-co-phonebk-ca", lang: "en", ext: "u-co-phonebk", invalid: true}, - {in: "en-u-nu-arabic-co-phonebk-ca", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-x", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-s", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-a12345678", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-co-phonebook", lang: "en", ext: "", invalid: true}, - {in: "en-u-co-phonebook-cu-xau", lang: "en", ext: "u-cu-xau", invalid: true, changed: true}, + {in: "en-u-co-phonebk-ca", lang: "en", ext: "u-ca-co-phonebk", changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-x", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-s", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-a12345678", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-co-phonebook", lang: "en", ext: "u-co", invalid: true}, + {in: "en-u-co-phonebook-cu-xau", lang: "en", ext: "u-co-cu-xau", invalid: true, changed: true}, {in: "en-Cyrl-u-co-phonebk", lang: "en", script: "Cyrl", ext: "u-co-phonebk"}, {in: "en-US-u-co-phonebk", lang: "en", region: "US", ext: "u-co-phonebk"}, {in: "en-US-u-co-phonebk-cu-xau", lang: "en", region: "US", ext: "u-co-phonebk-cu-xau"}, @@ -179,9 +179,8 @@ {in: "en-u-def-abc-cu-xua-co-phonebk", lang: "en", ext: "u-abc-def-co-phonebk-cu-xua", changed: true}, {in: "en-u-def-abc", lang: "en", ext: "u-abc-def", changed: true}, {in: "en-u-cu-xua-co-phonebk-a-cd", lang: "en", extList: []string{"a-cd", "u-co-phonebk-cu-xua"}, changed: true}, - // Invalid "u" extension. Drop invalid parts. - {in: "en-u-cu-co-phonebk", lang: "en", extList: []string{"u-co-phonebk"}, invalid: true, changed: true}, - {in: "en-u-cu-xau-co", lang: "en", extList: []string{"u-cu-xau"}, invalid: true}, + {in: "en-u-cu-co-phonebk", lang: "en", extList: []string{"u-co-phonebk-cu"}, changed: true}, + {in: "en-u-cu-xau-co", lang: "en", extList: []string{"u-co-cu-xau"}, changed: true}, // LDML spec is not specific about it, but remove duplicates and return an error if the values differ. {in: "en-u-cu-xau-co-phonebk-cu-xau", lang: "en", ext: "u-co-phonebk-cu-xau", changed: true}, // No change as the result is a substring of the original! @@ -351,8 +350,8 @@ {"aa-AB", mkInvalid("AB")}, // ill-formed wins over invalid. {"ac-u", ErrSyntax}, - {"ac-u-ca", ErrSyntax}, - {"ac-u-ca-co-pinyin", ErrSyntax}, + {"ac-u-ca", mkInvalid("ac")}, + {"ac-u-ca-co-pinyin", mkInvalid("ac")}, {"noob", ErrSyntax}, } for _, tt := range tests { diff -Nru golang-golang-x-text-0.3.5/language/language.go golang-golang-x-text-0.3.6/language/language.go --- golang-golang-x-text-0.3.5/language/language.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/language/language.go 2021-03-30 13:48:03.000000000 +0800 @@ -412,6 +412,10 @@ // are of the allowed values defined for the Unicode locale extension ('u') in // https://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers. // TypeForKey will traverse the inheritance chain to get the correct value. +// +// If there are multiple types associated with a key, only the first will be +// returned. If there is no type associated with a key, it returns the empty +// string. func (t Tag) TypeForKey(key string) string { if !compact.Tag(t).MayHaveExtensions() { if key != "rg" && key != "va" { diff -Nru golang-golang-x-text-0.3.5/language/language_test.go golang-golang-x-text-0.3.6/language/language_test.go --- golang-golang-x-text-0.3.5/language/language_test.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/language/language_test.go 2021-03-30 13:48:03.000000000 +0800 @@ -523,6 +523,13 @@ {"en-GB-u-rg-usz", "en-GB-u-rg-usz", Raw}, {"en-GB-u-rg-usz-va-posix", "en-GB-u-rg-usz-va-posix", Raw}, {"en-GB-u-rg-usz-co-phonebk", "en-GB-u-co-phonebk-rg-usz", Raw}, + + // CVE-2020-28851 + // invalid key-value pair of -u- extension. + {"ES-u-000-00", "es-u-000-00", Raw}, + {"ES-u-000-00-v-00", "es-u-000-00-v-00", Raw}, + // reordered and unknown extension. + {"ES-v-00-u-000-00", "es-u-000-00-v-00", Raw}, } for i, tt := range tests { in, _ := Raw.Parse(tt.in) @@ -553,6 +560,12 @@ {"rg", "en-u-rg-gbzzzz", "gbzzzz"}, {"nu", "en-u-co-phonebk-nu-arabic", "arabic"}, {"kc", "cmn-u-co-stroke", ""}, + {"rg", "cmn-u-rg", ""}, + {"rg", "cmn-u-rg-co-stroke", ""}, + {"co", "cmn-u-rg-co-stroke", "stroke"}, + {"co", "cmn-u-co-rg-gbzzzz", ""}, + {"rg", "cmn-u-co-rg-gbzzzz", "gbzzzz"}, + {"rg", "cmn-u-rg-gbzzzz-nlzzzz", "gbzzzz"}, } for _, tt := range tests { if v := Make(tt.in).TypeForKey(tt.key); v != tt.out { diff -Nru golang-golang-x-text-0.3.5/language/match_test.go golang-golang-x-text-0.3.6/language/match_test.go --- golang-golang-x-text-0.3.5/language/match_test.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/language/match_test.go 2021-03-30 13:48:03.000000000 +0800 @@ -224,6 +224,20 @@ return fmt.Sprintf("%v:%d:%v:%v-%v|%v", t.tag, t.index, t.conf, t.maxRegion, t.maxScript, t.altScript) } +func TestIssue43834(t *testing.T) { + matcher := NewMatcher([]Tag{English}) + + // ZZ is the largest region code and should not cause overflow. + desired, _, err := ParseAcceptLanguage("en-ZZ") + if err != nil { + t.Error(err) + } + _, i, _ := matcher.Match(desired...) + if i != 0 { + t.Errorf("got %v; want 0", i) + } +} + func TestBestMatchAlloc(t *testing.T) { m := NewMatcher(makeTagList("en sr nl")) // Go allocates when creating a list of tags from a single tag! diff -Nru golang-golang-x-text-0.3.5/language/parse_test.go golang-golang-x-text-0.3.6/language/parse_test.go --- golang-golang-x-text-0.3.5/language/parse_test.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/language/parse_test.go 2021-03-30 13:48:03.000000000 +0800 @@ -101,13 +101,13 @@ {in: "en-9-aa-0-aa-z-bb-x-a", lang: "en", extList: []string{"0-aa", "9-aa", "z-bb", "x-a"}, changed: true}, {in: "en-u-c", lang: "en", ext: "", invalid: true}, {in: "en-u-co-phonebk", lang: "en", ext: "u-co-phonebk"}, - {in: "en-u-co-phonebk-ca", lang: "en", ext: "u-co-phonebk", invalid: true}, - {in: "en-u-nu-arabic-co-phonebk-ca", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-x", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-s", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-nu-arabic-co-phonebk-ca-a12345678", lang: "en", ext: "u-co-phonebk-nu-arabic", invalid: true, changed: true}, - {in: "en-u-co-phonebook", lang: "en", ext: "", invalid: true}, - {in: "en-u-co-phonebook-cu-xau", lang: "en", ext: "u-cu-xau", invalid: true, changed: true}, + {in: "en-u-co-phonebk-ca", lang: "en", ext: "u-ca-co-phonebk", invalid: true}, + {in: "en-u-nu-arabic-co-phonebk-ca", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-x", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-s", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-nu-arabic-co-phonebk-ca-a12345678", lang: "en", ext: "u-ca-co-phonebk-nu-arabic", invalid: true, changed: true}, + {in: "en-u-co-phonebook", lang: "en", ext: "u-co", invalid: true}, + {in: "en-u-co-phonebook-cu-xau", lang: "en", ext: "u-co-cu-xau", invalid: true, changed: true}, {in: "en-Cyrl-u-co-phonebk", lang: "en", script: "Cyrl", ext: "u-co-phonebk"}, {in: "en-US-u-co-phonebk", lang: "en", region: "US", ext: "u-co-phonebk"}, {in: "en-US-u-co-phonebk-cu-xau", lang: "en", region: "US", ext: "u-co-phonebk-cu-xau"}, @@ -117,8 +117,8 @@ {in: "en-u-def-abc", lang: "en", ext: "u-abc-def", changed: true}, {in: "en-u-cu-xua-co-phonebk-a-cd", lang: "en", extList: []string{"a-cd", "u-co-phonebk-cu-xua"}, changed: true}, // Invalid "u" extension. Drop invalid parts. - {in: "en-u-cu-co-phonebk", lang: "en", extList: []string{"u-co-phonebk"}, invalid: true, changed: true}, - {in: "en-u-cu-xau-co", lang: "en", extList: []string{"u-cu-xau"}, invalid: true}, + {in: "en-u-cu-co-phonebk", lang: "en", extList: []string{"u-co-phonebk-cu"}, invalid: true, changed: true}, + {in: "en-u-cu-xau-co", lang: "en", extList: []string{"u-co-cu-xau"}, invalid: true}, // We allow duplicate keys as the LDML spec does not explicitly prohibit it. // TODO: Consider eliminating duplicates and returning an error. {in: "en-u-cu-xau-co-phonebk-cu-xau", lang: "en", ext: "u-co-phonebk-cu-xau", changed: true}, @@ -219,8 +219,8 @@ {"aa-AB", mkInvalid("AB")}, // ill-formed wins over invalid. {"ac-u", errSyntax}, - {"ac-u-ca", errSyntax}, - {"ac-u-ca-co-pinyin", errSyntax}, + {"ac-u-ca", mkInvalid("ac")}, + {"ac-u-ca-co-pinyin", mkInvalid("ac")}, {"noob", errSyntax}, } for _, tt := range tests { diff -Nru golang-golang-x-text-0.3.5/language/tables.go golang-golang-x-text-0.3.6/language/tables.go --- golang-golang-x-text-0.3.5/language/tables.go 2020-12-08 08:13:44.000000000 +0800 +++ golang-golang-x-text-0.3.6/language/tables.go 2021-03-30 13:48:03.000000000 +0800 @@ -47,7 +47,7 @@ _Zzzz = 251 ) -var regionToGroups = []uint8{ // 357 elements +var regionToGroups = []uint8{ // 358 elements // Entry 0 - 3F 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, @@ -98,8 +98,8 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, -} // Size: 381 bytes + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +} // Size: 382 bytes var paradigmLocales = [][3]uint16{ // 3 elements 0: [3]uint16{0x139, 0x0, 0x7b}, @@ -295,4 +295,4 @@ 14: {lang: 0x529, script: 0x3c, group: 0x80, distance: 0x5}, } // Size: 114 bytes -// Total table size 1471 bytes (1KiB); checksum: 4CB1CD46 +// Total table size 1472 bytes (1KiB); checksum: F86C669