On 2023-04-05 19:10:42 +0800, Shengjing Zhu wrote: > Package: release.debian.org > Severity: normal > User: release.debian....@packages.debian.org > Usertags: unblock > X-Debbugs-Cc: golang-1...@packages.debian.org, z...@debian.org > Control: affects -1 + src:golang-1.19 > > Please unblock package golang-1.19
Please go ahead with upload to unstable Cheers > > [ Reason ] > Two upstream minor versions, fixing 5 CVEs > > + CVE-2023-24532: crypto/elliptic: incorrect P-256 ScalarMult and > ScalarBaseMult results > + CVE-2023-24537: go/parser: infinite loop in parsing > + CVE-2023-24538: html/template: backticks not treated as string delimiters > + CVE-2023-24534: net/http, net/textproto: denial of service from excessive > memory allocation > + CVE-2023-24536: net/http, net/textproto, mime/multipart: denial of > service from excessive resource consumption > > [ Impact ] > > Several security issues in the Go standard libraries. > > [ Tests ] > Besise the unittests upstream added in the new release, I have use the new > version to build some Go packages. And the result is good. > > [ Risks ] > Toolchain package and no autopkgtest. > > [ 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 > > I attached the debdiff with > filterdiff --exclude '*_test.go' --exclude '*_windows*' --exclude > '*/testdata/*' \ > --exclude '*/go.mod' --exclude '*/go.sum' --exclude '*/modules.txt' > > [ Other info ] > It may be the last golang-1.19 version to be uploaded during freeze. > The next release is expected (if no urgent CVE happens) to be May, which > is probably hard-freeze time. > > unblock golang-1.19/1.19.8-2 > diff -Nru golang-1.19-1.19.6/debian/changelog > golang-1.19-1.19.8/debian/changelog > --- golang-1.19-1.19.6/debian/changelog 2023-02-17 17:56:44.000000000 > +0800 > +++ golang-1.19-1.19.8/debian/changelog 2023-04-05 02:15:56.000000000 > +0800 > @@ -1,3 +1,25 @@ > +golang-1.19 (1.19.8-1) experimental; urgency=medium > + > + * Team upload > + * New upstream version 1.19.8 > + + CVE-2023-24537: go/parser: infinite loop in parsing > + + CVE-2023-24538: html/template: backticks not treated as string > delimiters > + + CVE-2023-24534: net/http, net/textproto: denial of service from > excessive > + memory allocation > + + CVE-2023-24536: net/http, net/textproto, mime/multipart: denial of > + service from excessive resource consumption > + > + -- Shengjing Zhu <z...@debian.org> Wed, 05 Apr 2023 02:15:56 +0800 > + > +golang-1.19 (1.19.7-1) experimental; urgency=medium > + > + * Team upload > + * New upstream version 1.19.7 > + + CVE-2023-24532: crypto/elliptic: incorrect P-256 ScalarMult and > + ScalarBaseMult results > + > + -- Shengjing Zhu <z...@debian.org> Wed, 08 Mar 2023 13:54:08 +0800 > + > golang-1.19 (1.19.6-2) unstable; urgency=medium > > * Team upload > diff -Nru golang-1.19-1.19.6/src/cmd/go/internal/work/exec.go > golang-1.19-1.19.8/src/cmd/go/internal/work/exec.go > --- golang-1.19-1.19.6/src/cmd/go/internal/work/exec.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/go/internal/work/exec.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -2764,6 +2764,36 @@ > } > } > > + // Scrutinize CFLAGS and related for flags that might cause > + // problems if we are using internal linking (for example, use of > + // plugins, LTO, etc) by calling a helper routine that builds on > + // the existing CGO flags allow-lists. If we see anything > + // suspicious, emit a special token file "preferlinkext" (known to > + // the linker) in the object file to signal the that it should not > + // try to link internally and should revert to external linking. > + // The token we pass is a suggestion, not a mandate; if a user is > + // explicitly asking for a specific linkmode via the "-linkmode" > + // flag, the token will be ignored. NB: in theory we could ditch > + // the token approach and just pass a flag to the linker when we > + // eventually invoke it, and the linker flag could then be > + // documented (although coming up with a simple explanation of the > + // flag might be challenging). For more context see issues #58619, > + // #58620, and #58848. > + flagSources := []string{"CGO_CFLAGS", "CGO_CXXFLAGS", "CGO_FFLAGS"} > + flagLists := [][]string{cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS} > + if flagsNotCompatibleWithInternalLinking(flagSources, flagLists) { > + tokenFile := objdir + "preferlinkext" > + if cfg.BuildN || cfg.BuildX { > + b.Showcmd("", "echo > %s", tokenFile) > + } > + if !cfg.BuildN { > + if err := os.WriteFile(tokenFile, nil, 0666); err != > nil { > + return nil, nil, err > + } > + } > + outObj = append(outObj, tokenFile) > + } > + > if cfg.BuildMSan { > cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...) > cgoLDFLAGS = append([]string{"-fsanitize=memory"}, > cgoLDFLAGS...) > @@ -3012,6 +3042,24 @@ > return outGo, outObj, nil > } > > +// flagsNotCompatibleWithInternalLinking scans the list of cgo > +// compiler flags (C/C++/Fortran) looking for flags that might cause > +// problems if the build in question uses internal linking. The > +// primary culprits are use of plugins or use of LTO, but we err on > +// the side of caution, supporting only those flags that are on the > +// allow-list for safe flags from security perspective. Return is TRUE > +// if a sensitive flag is found, FALSE otherwise. > +func flagsNotCompatibleWithInternalLinking(sourceList []string, flagListList > [][]string) bool { > + for i := range sourceList { > + sn := sourceList[i] > + fll := flagListList[i] > + if err := checkCompilerFlagsForInternalLink(sn, sn, fll); err > != nil { > + return true > + } > + } > + return false > +} > + > // dynimport creates a Go source file named importGo containing > // //go:cgo_import_dynamic directives for each symbol or library > // dynamically imported by the object files outObj. > diff -Nru golang-1.19-1.19.6/src/cmd/go/internal/work/security.go > golang-1.19-1.19.8/src/cmd/go/internal/work/security.go > --- golang-1.19-1.19.6/src/cmd/go/internal/work/security.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/go/internal/work/security.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -230,32 +230,55 @@ > } > > func checkCompilerFlags(name, source string, list []string) error { > - return checkFlags(name, source, list, validCompilerFlags, > validCompilerFlagsWithNextArg) > + checkOverrides := true > + return checkFlags(name, source, list, validCompilerFlags, > validCompilerFlagsWithNextArg, checkOverrides) > } > > func checkLinkerFlags(name, source string, list []string) error { > - return checkFlags(name, source, list, validLinkerFlags, > validLinkerFlagsWithNextArg) > + checkOverrides := true > + return checkFlags(name, source, list, validLinkerFlags, > validLinkerFlagsWithNextArg, checkOverrides) > } > > -func checkFlags(name, source string, list []string, valid > []*lazyregexp.Regexp, validNext []string) error { > +// checkCompilerFlagsForInternalLink returns an error if 'list' > +// contains a flag or flags that may not be fully supported by > +// internal linking (meaning that we should punt the link to the > +// external linker). > +func checkCompilerFlagsForInternalLink(name, source string, list []string) > error { > + checkOverrides := false > + if err := checkFlags(name, source, list, validCompilerFlags, > validCompilerFlagsWithNextArg, checkOverrides); err != nil { > + return err > + } > + // Currently the only flag on the allow list that causes problems > + // for the linker is "-flto"; check for it manually here. > + for _, fl := range list { > + if strings.HasPrefix(fl, "-flto") { > + return fmt.Errorf("flag %q triggers external linking", > fl) > + } > + } > + return nil > +} > + > +func checkFlags(name, source string, list []string, valid > []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error { > // Let users override rules with $CGO_CFLAGS_ALLOW, > $CGO_CFLAGS_DISALLOW, etc. > var ( > allow *regexp.Regexp > disallow *regexp.Regexp > ) > - if env := cfg.Getenv("CGO_" + name + "_ALLOW"); env != "" { > - r, err := regexp.Compile(env) > - if err != nil { > - return fmt.Errorf("parsing $CGO_%s_ALLOW: %v", name, > err) > + if checkOverrides { > + if env := cfg.Getenv("CGO_" + name + "_ALLOW"); env != "" { > + r, err := regexp.Compile(env) > + if err != nil { > + return fmt.Errorf("parsing $CGO_%s_ALLOW: %v", > name, err) > + } > + allow = r > } > - allow = r > - } > - if env := cfg.Getenv("CGO_" + name + "_DISALLOW"); env != "" { > - r, err := regexp.Compile(env) > - if err != nil { > - return fmt.Errorf("parsing $CGO_%s_DISALLOW: %v", name, > err) > + if env := cfg.Getenv("CGO_" + name + "_DISALLOW"); env != "" { > + r, err := regexp.Compile(env) > + if err != nil { > + return fmt.Errorf("parsing $CGO_%s_DISALLOW: > %v", name, err) > + } > + disallow = r > } > - disallow = r > } > > Args: > diff -Nru golang-1.19-1.19.6/src/cmd/internal/obj/ppc64/asm9.go > golang-1.19-1.19.8/src/cmd/internal/obj/ppc64/asm9.go > --- golang-1.19-1.19.6/src/cmd/internal/obj/ppc64/asm9.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/internal/obj/ppc64/asm9.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -3136,8 +3136,13 @@ > if r == 0 { > r = c.getimpliedreg(&p.From, p) > } > - o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), uint32(r), > uint32(high16adjusted(v))) > - o2 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), > uint32(p.To.Reg), uint32(v)) > + if o.a6 == C_REG { > + o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), uint32(r), > uint32(high16adjusted(v))) > + o2 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), > uint32(p.To.Reg), uint32(v)) > + } else { > + o1 = AOP_IRR(OP_ADDIS, uint32(REGTMP), uint32(r), > uint32(high16adjusted(v))) > + o2 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), > uint32(REGTMP), uint32(v)) > + } > > // Sign extend MOVB if needed > o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0) > @@ -3516,8 +3521,8 @@ > rel.Type = objabi.R_ADDRPOWER_TOCREL_DS > } > default: > - reuseBaseReg := p.As != AFMOVD && p.As != AFMOVS > - // Reuse To.Reg as base register if not FP move. > + reuseBaseReg := o.a6 == C_REG > + // Reuse To.Reg as base register if it is a GPR. > o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, inst, > reuseBaseReg) > } > > diff -Nru golang-1.19-1.19.6/src/cmd/link/internal/arm/asm.go > golang-1.19-1.19.8/src/cmd/link/internal/arm/asm.go > --- golang-1.19-1.19.6/src/cmd/link/internal/arm/asm.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/link/internal/arm/asm.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -396,11 +396,28 @@ > // laid out. Conservatively use a trampoline. This should be > rare, as we lay out packages > // in dependency order. > if ldr.SymValue(rs) != 0 { > - // r.Add is the instruction > - // low 24-bit encodes the target address > - t = (ldr.SymValue(rs) + > int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4 > + // Workaround for issue #58425: it appears that the > + // external linker doesn't always take into account the > + // relocation addend when doing reachability checks. > This > + // means that if you have a call from function XYZ at > + // offset 8 to runtime.duffzero with addend 800 (for > + // example), where the distance between the start of XYZ > + // and the start of runtime.duffzero is just over the > + // limit (by 100 bytes, say), you can get "relocation > + // doesn't fit" errors from the external linker. To deal > + // with this, ignore the addend when performing the > + // distance calculation (this assumes that we're only > + // handling backward jumps; ideally we might want to > check > + // both with and without the addend). > + if ctxt.IsExternal() { > + t = (ldr.SymValue(rs) - (ldr.SymValue(s) + > int64(r.Off()))) / 4 > + } else { > + // r.Add is the instruction > + // low 24-bit encodes the target address > + t = (ldr.SymValue(rs) + > int64(signext24(r.Add()&0xffffff)*4) - (ldr.SymValue(s) + int64(r.Off()))) / 4 > + } > } > - if t > 0x7fffff || t < -0x800000 || ldr.SymValue(rs) == 0 || > (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { > + if t > 0x7fffff || t <= -0x800000 || ldr.SymValue(rs) == 0 || > (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { > // direct call too far, need to insert trampoline. > // look up existing trampolines first. if we found one > within the range > // of direct call, we can reuse it. otherwise create a > new one. > diff -Nru golang-1.19-1.19.6/src/cmd/link/internal/ld/config.go > golang-1.19-1.19.8/src/cmd/link/internal/ld/config.go > --- golang-1.19-1.19.6/src/cmd/link/internal/ld/config.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/link/internal/ld/config.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -280,7 +280,11 @@ > ctxt.LinkMode = LinkExternal > via = "via GO_EXTLINK_ENABLED " > default: > - if extNeeded || (iscgo && externalobj) { > + preferExternal := len(preferlinkext) != 0 > + if preferExternal && ctxt.Debugvlog > 0 { > + ctxt.Logf("external linking prefer list is > %v\n", preferlinkext) > + } > + if extNeeded || (iscgo && (externalobj || > preferExternal)) { > ctxt.LinkMode = LinkExternal > } else { > ctxt.LinkMode = LinkInternal > diff -Nru golang-1.19-1.19.6/src/cmd/link/internal/ld/lib.go > golang-1.19-1.19.8/src/cmd/link/internal/ld/lib.go > --- golang-1.19-1.19.6/src/cmd/link/internal/ld/lib.go 2023-02-14 > 01:38:43.000000000 +0800 > +++ golang-1.19-1.19.8/src/cmd/link/internal/ld/lib.go 2023-03-30 > 05:15:17.000000000 +0800 > @@ -349,6 +349,12 @@ > // any of these objects, we must link externally. Issue 52863. > dynimportfail []string > > + // preferlinkext is a list of packages for which the Go command > + // noticed use of peculiar C flags. If we see any of these, > + // default to linking externally unless overridden by the > + // user. See issues #58619, #58620, and #58848. > + preferlinkext []string > + > // unknownObjFormat is set to true if we see an object whose > // format we don't recognize. > unknownObjFormat = false > @@ -1043,6 +1049,13 @@ > if arhdr.name == "dynimportfail" { > dynimportfail = append(dynimportfail, lib.Pkg) > } > + if arhdr.name == "preferlinkext" { > + // Ignore this directive if -linkmode has been > + // set explicitly. > + if ctxt.LinkMode == LinkAuto { > + preferlinkext = append(preferlinkext, lib.Pkg) > + } > + } > > // Skip other special (non-object-file) sections that > // build tools may have added. Such sections must have > diff -Nru golang-1.19-1.19.6/src/crypto/internal/nistec/p256_asm.go > golang-1.19-1.19.8/src/crypto/internal/nistec/p256_asm.go > --- golang-1.19-1.19.6/src/crypto/internal/nistec/p256_asm.go 2023-02-14 > 01:38:45.000000000 +0800 > +++ golang-1.19-1.19.8/src/crypto/internal/nistec/p256_asm.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -365,6 +365,21 @@ > // Montgomery domain (with R 2²⁵⁶) as four uint64 limbs in little-endian > order. > type p256OrdElement [4]uint64 > > +// p256OrdReduce ensures s is in the range [0, ord(G)-1]. > +func p256OrdReduce(s *p256OrdElement) { > + // Since 2 * ord(G) > 2²⁵⁶, we can just conditionally subtract ord(G), > + // keeping the result if it doesn't underflow. > + t0, b := bits.Sub64(s[0], 0xf3b9cac2fc632551, 0) > + t1, b := bits.Sub64(s[1], 0xbce6faada7179e84, b) > + t2, b := bits.Sub64(s[2], 0xffffffffffffffff, b) > + t3, b := bits.Sub64(s[3], 0xffffffff00000000, b) > + tMask := b - 1 // zero if subtraction underflowed > + s[0] ^= (t0 ^ s[0]) & tMask > + s[1] ^= (t1 ^ s[1]) & tMask > + s[2] ^= (t2 ^ s[2]) & tMask > + s[3] ^= (t3 ^ s[3]) & tMask > +} > + > // Add sets q = p1 + p2, and returns q. The points may overlap. > func (q *P256Point) Add(r1, r2 *P256Point) *P256Point { > var sum, double P256Point > @@ -394,6 +409,7 @@ > } > scalarReversed := new(p256OrdElement) > p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar)) > + p256OrdReduce(scalarReversed) > > r.p256BaseMult(scalarReversed) > return r, nil > @@ -408,6 +424,7 @@ > } > scalarReversed := new(p256OrdElement) > p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar)) > + p256OrdReduce(scalarReversed) > > r.Set(q).p256ScalarMult(scalarReversed) > return r, nil > diff -Nru golang-1.19-1.19.6/src/crypto/internal/nistec/p256_asm_ordinv.go > golang-1.19-1.19.8/src/crypto/internal/nistec/p256_asm_ordinv.go > --- golang-1.19-1.19.6/src/crypto/internal/nistec/p256_asm_ordinv.go > 2023-02-14 01:38:45.000000000 +0800 > +++ golang-1.19-1.19.8/src/crypto/internal/nistec/p256_asm_ordinv.go > 2023-03-30 05:15:20.000000000 +0800 > @@ -25,6 +25,7 @@ > > x := new(p256OrdElement) > p256OrdBigToLittle(x, (*[32]byte)(k)) > + p256OrdReduce(x) > > // Inversion is implemented as exponentiation by n - 2, per Fermat's > little theorem. > // > diff -Nru golang-1.19-1.19.6/src/crypto/x509/root_darwin.go > golang-1.19-1.19.8/src/crypto/x509/root_darwin.go > --- golang-1.19-1.19.6/src/crypto/x509/root_darwin.go 2023-02-14 > 01:38:45.000000000 +0800 > +++ golang-1.19-1.19.8/src/crypto/x509/root_darwin.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -25,9 +25,10 @@ > return nil, err > } > sc, err := macOS.SecCertificateCreateWithData(c.Raw) > - if err == nil { > - macOS.CFArrayAppendValue(certs, sc) > + if err != nil { > + return nil, err > } > + macOS.CFArrayAppendValue(certs, sc) > } > } > > diff -Nru golang-1.19-1.19.6/src/go/scanner/scanner.go > golang-1.19-1.19.8/src/go/scanner/scanner.go > --- golang-1.19-1.19.6/src/go/scanner/scanner.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/go/scanner/scanner.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -246,13 +246,16 @@ > return > } > > + // Put a cap on the maximum size of line and column numbers. > + // 30 bits allows for some additional space before wrapping an int32. > + const maxLineCol = 1<<30 - 1 > var line, col int > i2, n2, ok2 := trailingDigits(text[:i-1]) > if ok2 { > //line filename:line:col > i, i2 = i2, i > line, col = n2, n > - if col == 0 { > + if col == 0 || col > maxLineCol { > s.error(offs+i2, "invalid column number: > "+string(text[i2:])) > return > } > @@ -262,7 +265,7 @@ > line = n > } > > - if line == 0 { > + if line == 0 || line > maxLineCol { > s.error(offs+i, "invalid line number: "+string(text[i:])) > return > } > diff -Nru golang-1.19-1.19.6/src/html/template/context.go > golang-1.19-1.19.8/src/html/template/context.go > --- golang-1.19-1.19.6/src/html/template/context.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/context.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -120,6 +120,8 @@ > stateJSDqStr > // stateJSSqStr occurs inside a JavaScript single quoted string. > stateJSSqStr > + // stateJSBqStr occurs inside a JavaScript back quoted string. > + stateJSBqStr > // stateJSRegexp occurs inside a JavaScript regexp literal. > stateJSRegexp > // stateJSBlockCmt occurs inside a JavaScript /* block comment */. > diff -Nru golang-1.19-1.19.6/src/html/template/error.go > golang-1.19-1.19.8/src/html/template/error.go > --- golang-1.19-1.19.6/src/html/template/error.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/error.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -214,6 +214,19 @@ > // pipeline occurs in an unquoted attribute value context, "html" is > // disallowed. Avoid using "html" and "urlquery" entirely in new > templates. > ErrPredefinedEscaper > + > + // errJSTmplLit: "... appears in a JS template literal" > + // Example: > + // <script>var tmpl = `{{.Interp}`</script> > + // Discussion: > + // Package html/template does not support actions inside of JS > template > + // literals. > + // > + // TODO(rolandshoemaker): we cannot add this as an exported error in a > minor > + // release, since it is backwards incompatible with the other minor > + // releases. As such we need to leave it unexported, and then we'll add > it > + // in the next major release. > + errJSTmplLit > ) > > func (e *Error) Error() string { > diff -Nru golang-1.19-1.19.6/src/html/template/escape.go > golang-1.19-1.19.8/src/html/template/escape.go > --- golang-1.19-1.19.6/src/html/template/escape.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/escape.go 2023-03-30 > 05:15:20.000000000 +0800 > @@ -8,6 +8,7 @@ > "bytes" > "fmt" > "html" > + "internal/godebug" > "io" > "text/template" > "text/template/parse" > @@ -223,6 +224,16 @@ > c.jsCtx = jsCtxDivOp > case stateJSDqStr, stateJSSqStr: > s = append(s, "_html_template_jsstrescaper") > + case stateJSBqStr: > + debugAllowActionJSTmpl := godebug.Get("jstmpllitinterp") > + if debugAllowActionJSTmpl == "1" { > + s = append(s, "_html_template_jsstrescaper") > + } else { > + return context{ > + state: stateError, > + err: errorf(errJSTmplLit, n, n.Line, "%s > appears in a JS template literal", n), > + } > + } > case stateJSRegexp: > s = append(s, "_html_template_jsregexpescaper") > case stateCSS: > diff -Nru golang-1.19-1.19.6/src/html/template/jsctx_string.go > golang-1.19-1.19.8/src/html/template/jsctx_string.go > --- golang-1.19-1.19.6/src/html/template/jsctx_string.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/jsctx_string.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -4,6 +4,15 @@ > > import "strconv" > > +func _() { > + // An "invalid array index" compiler error signifies that the constant > values have changed. > + // Re-run the stringer command to generate them again. > + var x [1]struct{} > + _ = x[jsCtxRegexp-0] > + _ = x[jsCtxDivOp-1] > + _ = x[jsCtxUnknown-2] > +} > + > const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown" > > var _jsCtx_index = [...]uint8{0, 11, 21, 33} > diff -Nru golang-1.19-1.19.6/src/html/template/js.go > golang-1.19-1.19.8/src/html/template/js.go > --- golang-1.19-1.19.6/src/html/template/js.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/js.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -308,6 +308,7 @@ > // Encode HTML specials as hex so the output can be embedded > // in HTML attributes without further encoding. > '"': `\u0022`, > + '`': `\u0060`, > '&': `\u0026`, > '\'': `\u0027`, > '+': `\u002b`, > @@ -331,6 +332,7 @@ > '"': `\u0022`, > '&': `\u0026`, > '\'': `\u0027`, > + '`': `\u0060`, > '+': `\u002b`, > '/': `\/`, > '<': `\u003c`, > diff -Nru golang-1.19-1.19.6/src/html/template/state_string.go > golang-1.19-1.19.8/src/html/template/state_string.go > --- golang-1.19-1.19.6/src/html/template/state_string.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/state_string.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -4,9 +4,42 @@ > > import "strconv" > > -const _state_name = > "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError" > +func _() { > + // An "invalid array index" compiler error signifies that the constant > values have changed. > + // Re-run the stringer command to generate them again. > + var x [1]struct{} > + _ = x[stateText-0] > + _ = x[stateTag-1] > + _ = x[stateAttrName-2] > + _ = x[stateAfterName-3] > + _ = x[stateBeforeValue-4] > + _ = x[stateHTMLCmt-5] > + _ = x[stateRCDATA-6] > + _ = x[stateAttr-7] > + _ = x[stateURL-8] > + _ = x[stateSrcset-9] > + _ = x[stateJS-10] > + _ = x[stateJSDqStr-11] > + _ = x[stateJSSqStr-12] > + _ = x[stateJSBqStr-13] > + _ = x[stateJSRegexp-14] > + _ = x[stateJSBlockCmt-15] > + _ = x[stateJSLineCmt-16] > + _ = x[stateCSS-17] > + _ = x[stateCSSDqStr-18] > + _ = x[stateCSSSqStr-19] > + _ = x[stateCSSDqURL-20] > + _ = x[stateCSSSqURL-21] > + _ = x[stateCSSURL-22] > + _ = x[stateCSSBlockCmt-23] > + _ = x[stateCSSLineCmt-24] > + _ = x[stateError-25] > + _ = x[stateDead-26] > +} > > -var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, > 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296} > +const _state_name = > "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" > + > +var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, > 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, > 308, 317} > > func (i state) String() string { > if i >= state(len(_state_index)-1) { > diff -Nru golang-1.19-1.19.6/src/html/template/transition.go > golang-1.19-1.19.8/src/html/template/transition.go > --- golang-1.19-1.19.6/src/html/template/transition.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/html/template/transition.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -27,6 +27,7 @@ > stateJS: tJS, > stateJSDqStr: tJSDelimited, > stateJSSqStr: tJSDelimited, > + stateJSBqStr: tJSDelimited, > stateJSRegexp: tJSDelimited, > stateJSBlockCmt: tBlockCmt, > stateJSLineCmt: tLineCmt, > @@ -262,7 +263,7 @@ > > // tJS is the context transition function for the JS state. > func tJS(c context, s []byte) (context, int) { > - i := bytes.IndexAny(s, `"'/`) > + i := bytes.IndexAny(s, "\"`'/") > if i == -1 { > // Entire input is non string, comment, regexp tokens. > c.jsCtx = nextJSCtx(s, c.jsCtx) > @@ -274,6 +275,8 @@ > c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp > case '\'': > c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp > + case '`': > + c.state, c.jsCtx = stateJSBqStr, jsCtxRegexp > case '/': > switch { > case i+1 < len(s) && s[i+1] == '/': > @@ -303,6 +306,8 @@ > switch c.state { > case stateJSSqStr: > specials = `\'` > + case stateJSBqStr: > + specials = "`\\" > case stateJSRegexp: > specials = `\/[]` > } > diff -Nru golang-1.19-1.19.6/src/internal/poll/fd_poll_runtime.go > golang-1.19-1.19.8/src/internal/poll/fd_poll_runtime.go > --- golang-1.19-1.19.6/src/internal/poll/fd_poll_runtime.go 2023-02-14 > 01:38:46.000000000 +0800 > +++ golang-1.19-1.19.8/src/internal/poll/fd_poll_runtime.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -23,7 +23,7 @@ > func runtime_pollOpen(fd uintptr) (uintptr, int) > func runtime_pollClose(ctx uintptr) > func runtime_pollWait(ctx uintptr, mode int) int > -func runtime_pollWaitCanceled(ctx uintptr, mode int) int > +func runtime_pollWaitCanceled(ctx uintptr, mode int) > func runtime_pollReset(ctx uintptr, mode int) int > func runtime_pollSetDeadline(ctx uintptr, d int64, mode int) > func runtime_pollUnblock(ctx uintptr) > diff -Nru golang-1.19-1.19.6/src/mime/multipart/formdata.go > golang-1.19-1.19.8/src/mime/multipart/formdata.go > --- golang-1.19-1.19.6/src/mime/multipart/formdata.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/mime/multipart/formdata.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -12,6 +12,7 @@ > "math" > "net/textproto" > "os" > + "strconv" > ) > > // ErrMessageTooLarge is returned by ReadForm if the message form > @@ -41,6 +42,15 @@ > numDiskFiles := 0 > multipartFiles := godebug.Get("multipartfiles") > combineFiles := multipartFiles != "distinct" > + maxParts := 1000 > + multipartMaxParts := godebug.Get("multipartmaxparts") > + if multipartMaxParts != "" { > + if v, err := strconv.Atoi(multipartMaxParts); err == nil && v > >= 0 { > + maxParts = v > + } > + } > + maxHeaders := maxMIMEHeaders() > + > defer func() { > if file != nil { > if cerr := file.Close(); err == nil { > @@ -84,14 +94,19 @@ > maxMemoryBytes = math.MaxInt64 > } > } > + var copyBuf []byte > for { > - p, err := r.nextPart(false, maxMemoryBytes) > + p, err := r.nextPart(false, maxMemoryBytes, maxHeaders) > if err == io.EOF { > break > } > if err != nil { > return nil, err > } > + if maxParts <= 0 { > + return nil, ErrMessageTooLarge > + } > + maxParts-- > > name := p.FormName() > if name == "" { > @@ -102,8 +117,9 @@ > // Multiple values for the same key (one map entry, longer > slice) are cheaper > // than the same number of values for different keys (many map > entries), but > // using a consistent per-value cost for overhead is simpler. > + const mapEntryOverhead = 200 > maxMemoryBytes -= int64(len(name)) > - maxMemoryBytes -= 100 // map overhead > + maxMemoryBytes -= mapEntryOverhead > if maxMemoryBytes < 0 { > // We can't actually take this path, since nextPart > would already have > // rejected the MIME headers for being too large. Check > anyway. > @@ -127,10 +143,16 @@ > } > > // file, store in memory or on disk > + const fileHeaderSize = 100 > maxMemoryBytes -= mimeHeaderSize(p.Header) > + maxMemoryBytes -= mapEntryOverhead > + maxMemoryBytes -= fileHeaderSize > if maxMemoryBytes < 0 { > return nil, ErrMessageTooLarge > } > + for _, v := range p.Header { > + maxHeaders -= int64(len(v)) > + } > fh := &FileHeader{ > Filename: filename, > Header: p.Header, > @@ -147,14 +169,22 @@ > } > } > numDiskFiles++ > - size, err := io.Copy(file, io.MultiReader(&b, p)) > + if _, err := file.Write(b.Bytes()); err != nil { > + return nil, err > + } > + if copyBuf == nil { > + copyBuf = make([]byte, 32*1024) // same buffer > size as io.Copy uses > + } > + // os.File.ReadFrom will allocate its own copy buffer > if we let io.Copy use it. > + type writerOnly struct{ io.Writer } > + remainingSize, err := io.CopyBuffer(writerOnly{file}, > p, copyBuf) > if err != nil { > return nil, err > } > fh.tmpfile = file.Name() > - fh.Size = size > + fh.Size = int64(b.Len()) + remainingSize > fh.tmpoff = fileOff > - fileOff += size > + fileOff += fh.Size > if !combineFiles { > if err := file.Close(); err != nil { > return nil, err > @@ -174,9 +204,10 @@ > } > > func mimeHeaderSize(h textproto.MIMEHeader) (size int64) { > + size = 400 > for k, vs := range h { > size += int64(len(k)) > - size += 100 // map entry overhead > + size += 200 // map entry overhead > for _, v := range vs { > size += int64(len(v)) > } > diff -Nru golang-1.19-1.19.6/src/mime/multipart/multipart.go > golang-1.19-1.19.8/src/mime/multipart/multipart.go > --- golang-1.19-1.19.6/src/mime/multipart/multipart.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/mime/multipart/multipart.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -16,11 +16,13 @@ > "bufio" > "bytes" > "fmt" > + "internal/godebug" > "io" > "mime" > "mime/quotedprintable" > "net/textproto" > "path/filepath" > + "strconv" > "strings" > ) > > @@ -128,12 +130,12 @@ > return n, r.err > } > > -func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, > error) { > +func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders > int64) (*Part, error) { > bp := &Part{ > Header: make(map[string][]string), > mr: mr, > } > - if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil { > + if err := bp.populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders); err != > nil { > return nil, err > } > bp.r = partReader{bp} > @@ -149,9 +151,9 @@ > return bp, nil > } > > -func (p *Part) populateHeaders(maxMIMEHeaderSize int64) error { > +func (p *Part) populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders int64) > error { > r := textproto.NewReader(p.mr.bufReader) > - header, err := readMIMEHeader(r, maxMIMEHeaderSize) > + header, err := readMIMEHeader(r, maxMIMEHeaderSize, maxMIMEHeaders) > if err == nil { > p.Header = header > } > @@ -330,6 +332,19 @@ > // including header keys, values, and map overhead. > const maxMIMEHeaderSize = 10 << 20 > > +func maxMIMEHeaders() int64 { > + // multipartMaxHeaders is the maximum number of header entries NextPart > will return, > + // as well as the maximum combined total of header entries > Reader.ReadForm will return > + // in FileHeaders. > + multipartMaxHeaders := godebug.Get("multipartmaxheaders") > + if multipartMaxHeaders != "" { > + if v, err := strconv.ParseInt(multipartMaxHeaders, 10, 64); err > == nil && v >= 0 { > + return v > + } > + } > + return 10000 > +} > + > // NextPart returns the next part in the multipart or an error. > // When there are no more parts, the error io.EOF is returned. > // > @@ -337,7 +352,7 @@ > // has a value of "quoted-printable", that header is instead > // hidden and the body is transparently decoded during Read calls. > func (r *Reader) NextPart() (*Part, error) { > - return r.nextPart(false, maxMIMEHeaderSize) > + return r.nextPart(false, maxMIMEHeaderSize, maxMIMEHeaders()) > } > > // NextRawPart returns the next part in the multipart or an error. > @@ -346,10 +361,10 @@ > // Unlike NextPart, it does not have special handling for > // "Content-Transfer-Encoding: quoted-printable". > func (r *Reader) NextRawPart() (*Part, error) { > - return r.nextPart(true, maxMIMEHeaderSize) > + return r.nextPart(true, maxMIMEHeaderSize, maxMIMEHeaders()) > } > > -func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, > error) { > +func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders > int64) (*Part, error) { > if r.currentPart != nil { > r.currentPart.Close() > } > @@ -374,7 +389,7 @@ > > if r.isBoundaryDelimiterLine(line) { > r.partsRead++ > - bp, err := newPart(r, rawPart, maxMIMEHeaderSize) > + bp, err := newPart(r, rawPart, maxMIMEHeaderSize, > maxMIMEHeaders) > if err != nil { > return nil, err > } > diff -Nru golang-1.19-1.19.6/src/mime/multipart/readmimeheader.go > golang-1.19-1.19.8/src/mime/multipart/readmimeheader.go > --- golang-1.19-1.19.6/src/mime/multipart/readmimeheader.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/mime/multipart/readmimeheader.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -11,4 +11,4 @@ > // readMIMEHeader is defined in package net/textproto. > // > //go:linkname readMIMEHeader net/textproto.readMIMEHeader > -func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, > error) > +func readMIMEHeader(r *textproto.Reader, maxMemory, maxHeaders int64) > (textproto.MIMEHeader, error) > diff -Nru golang-1.19-1.19.6/src/net/textproto/reader.go > golang-1.19-1.19.8/src/net/textproto/reader.go > --- golang-1.19-1.19.6/src/net/textproto/reader.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/net/textproto/reader.go 2023-03-30 > 05:15:21.000000000 +0800 > @@ -483,23 +483,32 @@ > // "Long-Key": {"Even Longer Value"}, > // } > func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) { > - return readMIMEHeader(r, math.MaxInt64) > + return readMIMEHeader(r, math.MaxInt64, math.MaxInt64) > } > > // readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the > header size. > // It is called by the mime/multipart package. > -func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) { > +func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, > error) { > // Avoid lots of small slice allocations later by allocating one > // large one ahead of time which we'll cut up into smaller > // slices. If this isn't big enough later, we allocate small ones. > var strs []string > - hint := r.upcomingHeaderNewlines() > + hint := r.upcomingHeaderKeys() > if hint > 0 { > + if hint > 1000 { > + hint = 1000 // set a cap to avoid overallocation > + } > strs = make([]string, hint) > } > > m := make(MIMEHeader, hint) > > + // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes > per entry. > + // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is > 416 bytes and large > + // MIMEHeaders average about 200 bytes per entry. > + maxMemory -= 400 > + const mapEntryOverhead = 200 > + > // The first line cannot start with a leading space. > if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == > '\t') { > line, err := r.readLineSlice() > @@ -529,16 +538,21 @@ > continue > } > > + maxHeaders-- > + if maxHeaders < 0 { > + return nil, errors.New("message too large") > + } > + > // Skip initial spaces in value. > value := string(bytes.TrimLeft(v, " \t")) > > vv := m[key] > if vv == nil { > - lim -= int64(len(key)) > - lim -= 100 // map entry overhead > + maxMemory -= int64(len(key)) > + maxMemory -= mapEntryOverhead > } > - lim -= int64(len(value)) > - if lim < 0 { > + maxMemory -= int64(len(value)) > + if maxMemory < 0 { > // TODO: This should be a distinguishable error > (ErrMessageTooLarge) > // to allow mime/multipart to detect it. > return m, errors.New("message too large") > @@ -577,9 +591,9 @@ > > var nl = []byte("\n") > > -// upcomingHeaderNewlines returns an approximation of the number of newlines > +// upcomingHeaderKeys returns an approximation of the number of keys > // that will be in this header. If it gets confused, it returns 0. > -func (r *Reader) upcomingHeaderNewlines() (n int) { > +func (r *Reader) upcomingHeaderKeys() (n int) { > // Try to determine the 'hint' size. > r.R.Peek(1) // force a buffer load if empty > s := r.R.Buffered() > @@ -587,7 +601,20 @@ > return > } > peek, _ := r.R.Peek(s) > - return bytes.Count(peek, nl) > + for len(peek) > 0 && n < 1000 { > + var line []byte > + line, peek, _ = bytes.Cut(peek, nl) > + if len(line) == 0 || (len(line) == 1 && line[0] == '\r') { > + // Blank line separating headers from the body. > + break > + } > + if line[0] == ' ' || line[0] == '\t' { > + // Folded continuation of the previous line. > + continue > + } > + n++ > + } > + return n > } > > // CanonicalMIMEHeaderKey returns the canonical format of the > diff -Nru golang-1.19-1.19.6/src/os/signal/internal/pty/pty.go > golang-1.19-1.19.8/src/os/signal/internal/pty/pty.go > --- golang-1.19-1.19.6/src/os/signal/internal/pty/pty.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/os/signal/internal/pty/pty.go 2023-03-30 > 05:15:22.000000000 +0800 > @@ -42,14 +42,14 @@ > // Open returns a control pty and the name of the linked process tty. > func Open() (pty *os.File, processTTY string, err error) { > m, err := C.posix_openpt(C.O_RDWR) > - if err != nil { > + if m < 0 { > return nil, "", ptyError("posix_openpt", err) > } > - if _, err := C.grantpt(m); err != nil { > + if res, err := C.grantpt(m); res < 0 { > C.close(m) > return nil, "", ptyError("grantpt", err) > } > - if _, err := C.unlockpt(m); err != nil { > + if res, err := C.unlockpt(m); res < 0 { > C.close(m) > return nil, "", ptyError("unlockpt", err) > } > diff -Nru golang-1.19-1.19.6/src/runtime/mgcsweep.go > golang-1.19-1.19.8/src/runtime/mgcsweep.go > --- golang-1.19-1.19.6/src/runtime/mgcsweep.go 2023-02-14 > 01:38:47.000000000 +0800 > +++ golang-1.19-1.19.8/src/runtime/mgcsweep.go 2023-03-30 > 05:15:22.000000000 +0800 > @@ -815,11 +815,30 @@ > traceGCSweepStart() > } > > + // Fix debt if necessary. > retry: > sweptBasis := mheap_.pagesSweptBasis.Load() > - > - // Fix debt if necessary. > - newHeapLive := > uintptr(atomic.Load64(&gcController.heapLive)-mheap_.sweepHeapLiveBasis) + > spanBytes > + live := atomic.Load64(&gcController.heapLive) > + liveBasis := mheap_.sweepHeapLiveBasis > + newHeapLive := spanBytes > + if liveBasis < live { > + // Only do this subtraction when we don't overflow. Otherwise, > pagesTarget > + // might be computed as something really huge, causing us to > get stuck > + // sweeping here until the next mark phase. > + // > + // Overflow can happen here if gcPaceSweeper is called > concurrently with > + // sweeping (i.e. not during a STW, like it usually is) because > this code > + // is intentionally racy. A concurrent call to gcPaceSweeper > can happen > + // if a GC tuning parameter is modified and we read an older > value of > + // heapLive than what was used to set the basis. > + // > + // This state should be transient, so it's fine to just let > newHeapLive > + // be a relatively small number. We'll probably just skip this > attempt to > + // sweep. > + // > + // See issue #57523. > + newHeapLive += uintptr(live - liveBasis) > + } > pagesTarget := int64(mheap_.sweepPagesPerByte*float64(newHeapLive)) - > int64(callerSweepPages) > for pagesTarget > int64(mheap_.pagesSwept.Load()-sweptBasis) { > if sweepone() == ^uintptr(0) { > diff -Nru golang-1.19-1.19.6/src/sync/atomic/value.go > golang-1.19-1.19.8/src/sync/atomic/value.go > --- golang-1.19-1.19.6/src/sync/atomic/value.go 2023-02-14 > 01:38:48.000000000 +0800 > +++ golang-1.19-1.19.8/src/sync/atomic/value.go 2023-03-30 > 05:15:23.000000000 +0800 > @@ -190,5 +190,5 @@ > } > > // Disable/enable preemption, implemented in runtime. > -func runtime_procPin() > +func runtime_procPin() int > func runtime_procUnpin() > diff -Nru golang-1.19-1.19.6/src/time/zoneinfo.go > golang-1.19-1.19.8/src/time/zoneinfo.go > --- golang-1.19-1.19.6/src/time/zoneinfo.go 2023-02-14 01:38:48.000000000 > +0800 > +++ golang-1.19-1.19.8/src/time/zoneinfo.go 2023-03-30 05:15:24.000000000 > +0800 > @@ -182,7 +182,7 @@ > // If we're at the end of the known zone transitions, > // try the extend string. > if lo == len(tx)-1 && l.extend != "" { > - if ename, eoffset, estart, eend, eisDST, ok := tzset(l.extend, > end, sec); ok { > + if ename, eoffset, estart, eend, eisDST, ok := tzset(l.extend, > start, sec); ok { > return ename, eoffset, estart, eend, eisDST > } > } > @@ -243,12 +243,12 @@ > } > > // tzset takes a timezone string like the one found in the TZ environment > -// variable, the end of the last time zone transition expressed as seconds > +// variable, the time of the last time zone transition expressed as seconds > // since January 1, 1970 00:00:00 UTC, and a time expressed the same way. > // We call this a tzset string since in C the function tzset reads TZ. > // The return values are as for lookup, plus ok which reports whether the > // parse succeeded. > -func tzset(s string, initEnd, sec int64) (name string, offset int, start, > end int64, isDST, ok bool) { > +func tzset(s string, lastTxSec, sec int64) (name string, offset int, start, > end int64, isDST, ok bool) { > var ( > stdName, dstName string > stdOffset, dstOffset int > @@ -269,7 +269,7 @@ > > if len(s) == 0 || s[0] == ',' { > // No daylight savings time. > - return stdName, stdOffset, initEnd, omega, false, true > + return stdName, stdOffset, lastTxSec, omega, false, true > } > > dstName, s, ok = tzsetName(s) > diff -Nru golang-1.19-1.19.6/src/time/zoneinfo_read.go > golang-1.19-1.19.8/src/time/zoneinfo_read.go > --- golang-1.19-1.19.6/src/time/zoneinfo_read.go 2023-02-14 > 01:38:48.000000000 +0800 > +++ golang-1.19-1.19.8/src/time/zoneinfo_read.go 2023-03-30 > 05:15:24.000000000 +0800 > @@ -329,7 +329,7 @@ > } else if l.extend != "" { > // If we're at the end of the known zone > transitions, > // try the extend string. > - if name, offset, estart, eend, isDST, ok := > tzset(l.extend, l.cacheEnd, sec); ok { > + if name, offset, estart, eend, isDST, ok := > tzset(l.extend, l.cacheStart, sec); ok { > l.cacheStart = estart > l.cacheEnd = eend > // Find the zone that is returned by > tzset to avoid allocation if possible. > diff -Nru golang-1.19-1.19.6/VERSION golang-1.19-1.19.8/VERSION > --- golang-1.19-1.19.6/VERSION 2023-02-14 01:38:41.000000000 +0800 > +++ golang-1.19-1.19.8/VERSION 2023-03-30 05:15:14.000000000 +0800 > @@ -1 +1 @@ > -go1.19.6 > \ No newline at end of file > +go1.19.8 > \ No newline at end of file -- Sebastian Ramacher