From a68213b9c8a559db5ebc136bc6e71a47b1a13cb0 Mon Sep 17 00:00:00 2001 From: hanchao Date: Fri, 20 Jan 2023 16:56:01 +0800 Subject: [PATCH] golang: fix CVE-2022-23806,CVE-2022-23773,CVE-2022-24921,CVE-2021-44716,CVE-2022-23772,CVE-2022-41717 reference:https://go-review.googlesource.com/q/status:open+-is:wip --- ...o1.17-crypto-elliptic-make-IsOnCurve.patch | 144 ++++ ...o1.17-cmd-go-internal-modfetch-do-no.patch | 749 ++++++++++++++++++ ...o1.17-regexp-syntax-reject-very-deep.patch | 119 +++ ...o1.17-net-http-update-bundled-golang.patch | 94 +++ ...o1.17-math-big-prevent-overflow-in-R.patch | 65 ++ ...o1.18-net-http-update-bundled-golang.patch | 76 ++ golang.spec | 14 +- 7 files changed, 1260 insertions(+), 1 deletion(-) create mode 100644 0024-release-branch.go1.17-crypto-elliptic-make-IsOnCurve.patch create mode 100644 0025-release-branch.go1.17-cmd-go-internal-modfetch-do-no.patch create mode 100644 0026-release-branch.go1.17-regexp-syntax-reject-very-deep.patch create mode 100644 0027-release-branch.go1.17-net-http-update-bundled-golang.patch create mode 100644 0028-release-branch.go1.17-math-big-prevent-overflow-in-R.patch create mode 100644 0029-release-branch.go1.18-net-http-update-bundled-golang.patch diff --git a/0024-release-branch.go1.17-crypto-elliptic-make-IsOnCurve.patch b/0024-release-branch.go1.17-crypto-elliptic-make-IsOnCurve.patch new file mode 100644 index 0000000..aad114c --- /dev/null +++ b/0024-release-branch.go1.17-crypto-elliptic-make-IsOnCurve.patch @@ -0,0 +1,144 @@ +From 041fa43ad6669ac10ccdcdd8f47653897c592dfb Mon Sep 17 00:00:00 2001 +From: Filippo Valsorda +Date: Wed, 2 Feb 2022 09:14:57 -0800 +Subject: [PATCH] [release-branch.go1.17] crypto/elliptic: make IsOnCurve + return false for invalid field elements + +Updates #50974 +Fixes #50978 +Fixes CVE-2022-23806 + +Change-Id: I0201c2c88f13dd82910985a495973f1683af9259 +Reviewed-on: https://go-review.googlesource.com/c/go/+/382854 +Trust: Filippo Valsorda +Run-TryBot: Filippo Valsorda +Reviewed-by: Katie Hockman +Trust: Katie Hockman +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/382854 +--- + src/crypto/elliptic/elliptic.go | 5 +++ + src/crypto/elliptic/elliptic_test.go | 55 ++++++++++++++++++++++++++++ + src/crypto/elliptic/p224.go | 5 +++ + src/crypto/elliptic/p521.go | 5 +++ + 4 files changed, 70 insertions(+) + +diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go +index f072960bfed..b84339ec1c2 100644 +--- a/src/crypto/elliptic/elliptic.go ++++ b/src/crypto/elliptic/elliptic.go +@@ -86,6 +86,11 @@ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { + return specific.IsOnCurve(x, y) + } + ++ if x.Sign() < 0 || x.Cmp(curve.P) >= 0 || ++ y.Sign() < 0 || y.Cmp(curve.P) >= 0 { ++ return false ++ } ++ + // y² = x³ - 3x + b + y2 := new(big.Int).Mul(y, y) + y2.Mod(y2, curve.P) +diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go +index 183861a54b5..3fe53c5f332 100644 +--- a/src/crypto/elliptic/elliptic_test.go ++++ b/src/crypto/elliptic/elliptic_test.go +@@ -174,6 +174,61 @@ func testUnmarshalToLargeCoordinates(t *testing.T, curve Curve) { + } + } + ++// TestInvalidCoordinates tests big.Int values that are not valid field elements ++// (negative or bigger than P). They are expected to return false from ++// IsOnCurve, all other behavior is undefined. ++func TestInvalidCoordinates(t *testing.T) { ++ testAllCurves(t, testInvalidCoordinates) ++} ++ ++func testInvalidCoordinates(t *testing.T, curve Curve) { ++ checkIsOnCurveFalse := func(name string, x, y *big.Int) { ++ if curve.IsOnCurve(x, y) { ++ t.Errorf("IsOnCurve(%s) unexpectedly returned true", name) ++ } ++ } ++ ++ p := curve.Params().P ++ _, x, y, _ := GenerateKey(curve, rand.Reader) ++ xx, yy := new(big.Int), new(big.Int) ++ ++ // Check if the sign is getting dropped. ++ xx.Neg(x) ++ checkIsOnCurveFalse("-x, y", xx, y) ++ yy.Neg(y) ++ checkIsOnCurveFalse("x, -y", x, yy) ++ ++ // Check if negative values are reduced modulo P. ++ xx.Sub(x, p) ++ checkIsOnCurveFalse("x-P, y", xx, y) ++ yy.Sub(y, p) ++ checkIsOnCurveFalse("x, y-P", x, yy) ++ ++ // Check if positive values are reduced modulo P. ++ xx.Add(x, p) ++ checkIsOnCurveFalse("x+P, y", xx, y) ++ yy.Add(y, p) ++ checkIsOnCurveFalse("x, y+P", x, yy) ++ ++ // Check if the overflow is dropped. ++ xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535)) ++ checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y) ++ yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535)) ++ checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy) ++ ++ // Check if P is treated like zero (if possible). ++ // y^2 = x^3 - 3x + B ++ // y = mod_sqrt(x^3 - 3x + B) ++ // y = mod_sqrt(B) if x = 0 ++ // If there is no modsqrt, there is no point with x = 0, can't test x = P. ++ if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil { ++ if !curve.IsOnCurve(big.NewInt(0), yy) { ++ t.Fatal("(0, mod_sqrt(B)) is not on the curve?") ++ } ++ checkIsOnCurveFalse("P, y", p, yy) ++ } ++} ++ + func TestMarshalCompressed(t *testing.T) { + t.Run("P-256/03", func(t *testing.T) { + data, _ := hex.DecodeString("031e3987d9f9ea9d7dd7155a56a86b2009e1e0ab332f962d10d8beb6406ab1ad79") +diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go +index 8c760214642..ff5c8344522 100644 +--- a/src/crypto/elliptic/p224.go ++++ b/src/crypto/elliptic/p224.go +@@ -48,6 +48,11 @@ func (curve p224Curve) Params() *CurveParams { + } + + func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool { ++ if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 || ++ bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 { ++ return false ++ } ++ + var x, y p224FieldElement + p224FromBig(&x, bigX) + p224FromBig(&y, bigY) +diff --git a/src/crypto/elliptic/p521.go b/src/crypto/elliptic/p521.go +index 3d355943ec7..587991e31bf 100644 +--- a/src/crypto/elliptic/p521.go ++++ b/src/crypto/elliptic/p521.go +@@ -32,6 +32,11 @@ func (curve p521Curve) Params() *CurveParams { + } + + func (curve p521Curve) IsOnCurve(x, y *big.Int) bool { ++ if x.Sign() < 0 || x.Cmp(curve.P) >= 0 || ++ y.Sign() < 0 || y.Cmp(curve.P) >= 0 { ++ return false ++ } ++ + x1 := bigIntToFiatP521(x) + y1 := bigIntToFiatP521(y) + b := bigIntToFiatP521(curve.B) // TODO: precompute this value. +-- +2.30.0 + diff --git a/0025-release-branch.go1.17-cmd-go-internal-modfetch-do-no.patch b/0025-release-branch.go1.17-cmd-go-internal-modfetch-do-no.patch new file mode 100644 index 0000000..59ab52a --- /dev/null +++ b/0025-release-branch.go1.17-cmd-go-internal-modfetch-do-no.patch @@ -0,0 +1,749 @@ +From 8d5747c8fdc3d952696505562e7804e8e5fa0ab2 Mon Sep 17 00:00:00 2001 +From: "Bryan C. Mills" +Date: Thu, 13 Jan 2022 15:38:14 -0500 +Subject: [PATCH 2/6] [release-branch.go1.17] cmd/go/internal/modfetch: do not + short-circuit canonical versions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since at least CL 121857, the conversion logic in +(*modfetch).codeRepo.Stat has had a short-circuit to use the version +requested by the caller if it successfully resolves and is already +canonical. + +However, we should not use that version if it refers to a branch +instead of a tag, because branches (unlike tags) usually do not refer +to a single, stable release: a branch named "v1.0.0" may be for the +development of the v1.0.0 release, or for the development of patches +based on v1.0.0, but only one commit (perhaps at the end of that +branch — but possibly not even written yet!) can be that specific +version. + +We already have some logic to prefer tags that are semver-equivalent +to the version requested by the caller. That more general case +suffices for exact equality too — so we can eliminate the +special-case, fixing the bug and (happily!) also somewhat simplifying +the code. + +Updates #35671 +Fixes #50687 +Fixes CVE-2022-23773 + +Change-Id: I2fd290190b8a99a580deec7e26d15659b58a50b0 +Reviewed-on: https://go-review.googlesource.com/c/go/+/378400 +Trust: Bryan Mills +Run-TryBot: Bryan Mills +Reviewed-by: Russ Cox +TryBot-Result: Gopher Robot +(cherry picked from commit fa4d9b8e2bc2612960c80474fca83a4c85a974eb) +Reviewed-on: https://go-review.googlesource.com/c/go/+/382835 + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/382835 +--- + src/cmd/go/internal/modfetch/coderepo.go | 216 ++++++------- + src/cmd/go/internal/modfetch/coderepo_test.go | 301 ++++++++++-------- + .../testdata/script/mod_invalid_version.txt | 10 +- + 3 files changed, 277 insertions(+), 250 deletions(-) + +diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go +index dfef9f73c27..0ee707025d0 100644 +--- a/src/cmd/go/internal/modfetch/coderepo.go ++++ b/src/cmd/go/internal/modfetch/coderepo.go +@@ -298,16 +298,13 @@ func (r *codeRepo) Latest() (*RevInfo, error) { + // If statVers is a valid module version, it is used for the Version field. + // Otherwise, the Version is derived from the passed-in info and recent tags. + func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) { +- info2 := &RevInfo{ +- Name: info.Name, +- Short: info.Short, +- Time: info.Time, +- } +- + // If this is a plain tag (no dir/ prefix) + // and the module path is unversioned, + // and if the underlying file tree has no go.mod, + // then allow using the tag with a +incompatible suffix. ++ // ++ // (If the version is +incompatible, then the go.mod file must not exist: ++ // +incompatible is not an ongoing opt-out from semantic import versioning.) + var canUseIncompatible func() bool + canUseIncompatible = func() bool { + var ok bool +@@ -321,19 +318,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e + return ok + } + +- invalidf := func(format string, args ...interface{}) error { +- return &module.ModuleError{ +- Path: r.modPath, +- Err: &module.InvalidVersionError{ +- Version: info2.Version, +- Err: fmt.Errorf(format, args...), +- }, +- } +- } +- +- // checkGoMod verifies that the go.mod file for the module exists or does not +- // exist as required by info2.Version and the module path represented by r. +- checkGoMod := func() (*RevInfo, error) { ++ // checkCanonical verifies that the canonical version v is compatible with the ++ // module path represented by r, adding a "+incompatible" suffix if needed. ++ // ++ // If statVers is also canonical, checkCanonical also verifies that v is ++ // either statVers or statVers with the added "+incompatible" suffix. ++ checkCanonical := func(v string) (*RevInfo, error) { + // If r.codeDir is non-empty, then the go.mod file must exist: the module + // author — not the module consumer, — gets to decide how to carve up the repo + // into modules. +@@ -344,73 +334,91 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e + // r.findDir verifies both of these conditions. Execute it now so that + // r.Stat will correctly return a notExistError if the go.mod location or + // declared module path doesn't match. +- _, _, _, err := r.findDir(info2.Version) ++ _, _, _, err := r.findDir(v) + if err != nil { + // TODO: It would be nice to return an error like "not a module". + // Right now we return "missing go.mod", which is a little confusing. + return nil, &module.ModuleError{ + Path: r.modPath, + Err: &module.InvalidVersionError{ +- Version: info2.Version, ++ Version: v, + Err: notExistError{err: err}, + }, + } + } + +- // If the version is +incompatible, then the go.mod file must not exist: +- // +incompatible is not an ongoing opt-out from semantic import versioning. +- if strings.HasSuffix(info2.Version, "+incompatible") { +- if !canUseIncompatible() { ++ invalidf := func(format string, args ...interface{}) error { ++ return &module.ModuleError{ ++ Path: r.modPath, ++ Err: &module.InvalidVersionError{ ++ Version: v, ++ Err: fmt.Errorf(format, args...), ++ }, ++ } ++ } ++ ++ // Add the +incompatible suffix if needed or requested explicitly, and ++ // verify that its presence or absence is appropriate for this version ++ // (which depends on whether it has an explicit go.mod file). ++ ++ if v == strings.TrimSuffix(statVers, "+incompatible") { ++ v = statVers ++ } ++ base := strings.TrimSuffix(v, "+incompatible") ++ var errIncompatible error ++ if !module.MatchPathMajor(base, r.pathMajor) { ++ if canUseIncompatible() { ++ v = base + "+incompatible" ++ } else { + if r.pathMajor != "" { +- return nil, invalidf("+incompatible suffix not allowed: module path includes a major version suffix, so major version must match") ++ errIncompatible = invalidf("module path includes a major version suffix, so major version must match") + } else { +- return nil, invalidf("+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required") ++ errIncompatible = invalidf("module contains a go.mod file, so module path must match major version (%q)", path.Join(r.pathPrefix, semver.Major(v))) + } + } ++ } else if strings.HasSuffix(v, "+incompatible") { ++ errIncompatible = invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(v)) ++ } + +- if err := module.CheckPathMajor(strings.TrimSuffix(info2.Version, "+incompatible"), r.pathMajor); err == nil { +- return nil, invalidf("+incompatible suffix not allowed: major version %s is compatible", semver.Major(info2.Version)) ++ if statVers != "" && statVers == module.CanonicalVersion(statVers) { ++ // Since the caller-requested version is canonical, it would be very ++ // confusing to resolve it to anything but itself, possibly with a ++ // "+incompatible" suffix. Error out explicitly. ++ if statBase := strings.TrimSuffix(statVers, "+incompatible"); statBase != base { ++ return nil, &module.ModuleError{ ++ Path: r.modPath, ++ Err: &module.InvalidVersionError{ ++ Version: statVers, ++ Err: fmt.Errorf("resolves to version %v (%s is not a tag)", v, statBase), ++ }, ++ } + } + } + +- return info2, nil ++ if errIncompatible != nil { ++ return nil, errIncompatible ++ } ++ ++ return &RevInfo{ ++ Name: info.Name, ++ Short: info.Short, ++ Time: info.Time, ++ Version: v, ++ }, nil + } + + // Determine version. +- // +- // If statVers is canonical, then the original call was repo.Stat(statVers). +- // Since the version is canonical, we must not resolve it to anything but +- // itself, possibly with a '+incompatible' annotation: we do not need to do +- // the work required to look for an arbitrary pseudo-version. +- if statVers != "" && statVers == module.CanonicalVersion(statVers) { +- info2.Version = statVers +- +- if module.IsPseudoVersion(info2.Version) { +- if err := r.validatePseudoVersion(info, info2.Version); err != nil { +- return nil, err +- } +- return checkGoMod() +- } + +- if err := module.CheckPathMajor(info2.Version, r.pathMajor); err != nil { +- if canUseIncompatible() { +- info2.Version += "+incompatible" +- return checkGoMod() +- } else { +- if vErr, ok := err.(*module.InvalidVersionError); ok { +- // We're going to describe why the version is invalid in more detail, +- // so strip out the existing “invalid version” wrapper. +- err = vErr.Err +- } +- return nil, invalidf("module contains a go.mod file, so major version must be compatible: %v", err) +- } ++ if module.IsPseudoVersion(statVers) { ++ if err := r.validatePseudoVersion(info, statVers); err != nil { ++ return nil, err + } +- +- return checkGoMod() ++ return checkCanonical(statVers) + } + +- // statVers is empty or non-canonical, so we need to resolve it to a canonical +- // version or pseudo-version. ++ // statVers is not a pseudo-version, so we need to either resolve it to a ++ // canonical version or verify that it is already a canonical tag ++ // (not a branch). + + // Derive or verify a version from a code repo tag. + // Tag must have a prefix matching codeDir. +@@ -441,71 +449,62 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e + if v == "" || !strings.HasPrefix(trimmed, v) { + return "", false // Invalid or incomplete version (just vX or vX.Y). + } +- if isRetracted(v) { +- return "", false +- } + if v == trimmed { + tagIsCanonical = true + } +- +- if err := module.CheckPathMajor(v, r.pathMajor); err != nil { +- if canUseIncompatible() { +- return v + "+incompatible", tagIsCanonical +- } +- return "", false +- } +- + return v, tagIsCanonical + } + + // If the VCS gave us a valid version, use that. + if v, tagIsCanonical := tagToVersion(info.Version); tagIsCanonical { +- info2.Version = v +- return checkGoMod() ++ if info, err := checkCanonical(v); err == nil { ++ return info, err ++ } + } + + // Look through the tags on the revision for either a usable canonical version + // or an appropriate base for a pseudo-version. +- var pseudoBase string ++ var ( ++ highestCanonical string ++ pseudoBase string ++ ) + for _, pathTag := range info.Tags { + v, tagIsCanonical := tagToVersion(pathTag) +- if tagIsCanonical { +- if statVers != "" && semver.Compare(v, statVers) == 0 { +- // The user requested a non-canonical version, but the tag for the +- // canonical equivalent refers to the same revision. Use it. +- info2.Version = v +- return checkGoMod() ++ if statVers != "" && semver.Compare(v, statVers) == 0 { ++ // The tag is equivalent to the version requested by the user. ++ if tagIsCanonical { ++ // This tag is the canonical form of the requested version, ++ // not some other form with extra build metadata. ++ // Use this tag so that the resolved version will match exactly. ++ // (If it isn't actually allowed, we'll error out in checkCanonical.) ++ return checkCanonical(v) + } else { +- // Save the highest canonical tag for the revision. If we don't find a +- // better match, we'll use it as the canonical version. ++ // The user explicitly requested something equivalent to this tag. We ++ // can't use the version from the tag directly: since the tag is not ++ // canonical, it could be ambiguous. For example, tags v0.0.1+a and ++ // v0.0.1+b might both exist and refer to different revisions. + // +- // NOTE: Do not replace this with semver.Max. Despite the name, +- // semver.Max *also* canonicalizes its arguments, which uses +- // semver.Canonical instead of module.CanonicalVersion and thereby +- // strips our "+incompatible" suffix. +- if semver.Compare(info2.Version, v) < 0 { +- info2.Version = v +- } ++ // The tag is otherwise valid for the module, so we can at least use it as ++ // the base of an unambiguous pseudo-version. ++ // ++ // If multiple tags match, tagToVersion will canonicalize them to the same ++ // base version. ++ pseudoBase = v ++ } ++ } ++ // Save the highest non-retracted canonical tag for the revision. ++ // If we don't find a better match, we'll use it as the canonical version. ++ if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) { ++ if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() { ++ highestCanonical = v + } +- } else if v != "" && semver.Compare(v, statVers) == 0 { +- // The user explicitly requested something equivalent to this tag. We +- // can't use the version from the tag directly: since the tag is not +- // canonical, it could be ambiguous. For example, tags v0.0.1+a and +- // v0.0.1+b might both exist and refer to different revisions. +- // +- // The tag is otherwise valid for the module, so we can at least use it as +- // the base of an unambiguous pseudo-version. +- // +- // If multiple tags match, tagToVersion will canonicalize them to the same +- // base version. +- pseudoBase = v + } + } + +- // If we found any canonical tag for the revision, return it. ++ // If we found a valid canonical tag for the revision, return it. + // Even if we found a good pseudo-version base, a canonical version is better. +- if info2.Version != "" { +- return checkGoMod() ++ if highestCanonical != "" { ++ return checkCanonical(highestCanonical) + } + + // Find the highest tagged version in the revision's history, subject to +@@ -528,11 +527,10 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e + tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor("v0")) + } + } +- pseudoBase, _ = tagToVersion(tag) // empty if the tag is invalid ++ pseudoBase, _ = tagToVersion(tag) + } + +- info2.Version = module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short) +- return checkGoMod() ++ return checkCanonical(module.PseudoVersion(r.pseudoMajor, pseudoBase, info.Time, info.Short)) + } + + // validatePseudoVersion checks that version has a major version compatible with +@@ -556,10 +554,6 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string) + } + }() + +- if err := module.CheckPathMajor(version, r.pathMajor); err != nil { +- return err +- } +- + rev, err := module.PseudoVersionRev(version) + if err != nil { + return err +diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go +index 02e399f3525..d98ea87da2c 100644 +--- a/src/cmd/go/internal/modfetch/coderepo_test.go ++++ b/src/cmd/go/internal/modfetch/coderepo_test.go +@@ -418,171 +418,204 @@ var codeRepoTests = []codeRepoTest{ + zipSum: "h1:JItBZ+gwA5WvtZEGEbuDL4lUttGtLrs53lmdurq3bOg=", + zipFileHash: "9ea9ae1673cffcc44b7fdd3cc89953d68c102449b46c982dbf085e4f2e394da5", + }, ++ { ++ // Git branch with a semver name, +incompatible version, and no go.mod file. ++ vcs: "git", ++ path: "vcs-test.golang.org/go/mod/gitrepo1", ++ rev: "v2.3.4+incompatible", ++ err: `resolves to version v2.0.1+incompatible (v2.3.4 is not a tag)`, ++ }, ++ { ++ // Git branch with a semver name, matching go.mod file, and compatible version. ++ vcs: "git", ++ path: "vcs-test.golang.org/git/semver-branch.git", ++ rev: "v1.0.0", ++ err: `resolves to version v0.1.1-0.20220202191944-09c4d8f6938c (v1.0.0 is not a tag)`, ++ }, ++ { ++ // Git branch with a semver name, matching go.mod file, and disallowed +incompatible version. ++ // The version/tag mismatch takes precedence over the +incompatible mismatched. ++ vcs: "git", ++ path: "vcs-test.golang.org/git/semver-branch.git", ++ rev: "v2.0.0+incompatible", ++ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`, ++ }, ++ { ++ // Git branch with a semver name, matching go.mod file, and mismatched version. ++ // The version/tag mismatch takes precedence over the +incompatible mismatched. ++ vcs: "git", ++ path: "vcs-test.golang.org/git/semver-branch.git", ++ rev: "v2.0.0", ++ err: `resolves to version v0.1.0 (v2.0.0 is not a tag)`, ++ }, ++ { ++ // v3.0.0-devel is the same as tag v4.0.0-beta.1, but v4.0.0-beta.1 would ++ // not be allowed because it is incompatible and a go.mod file exists. ++ // The error message should refer to a valid pseudo-version, not the ++ // unusable semver tag. ++ vcs: "git", ++ path: "vcs-test.golang.org/git/semver-branch.git", ++ rev: "v3.0.0-devel", ++ err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`, ++ }, + } + + func TestCodeRepo(t *testing.T) { + testenv.MustHaveExternalNetwork(t) ++ tmpdir := t.TempDir() + +- tmpdir, err := os.MkdirTemp("", "modfetch-test-") +- if err != nil { +- t.Fatal(err) +- } +- defer os.RemoveAll(tmpdir) ++ for _, tt := range codeRepoTests { ++ f := func(tt codeRepoTest) func(t *testing.T) { ++ return func(t *testing.T) { ++ t.Parallel() ++ if tt.vcs != "mod" { ++ testenv.MustHaveExecPath(t, tt.vcs) ++ } + +- t.Run("parallel", func(t *testing.T) { +- for _, tt := range codeRepoTests { +- f := func(tt codeRepoTest) func(t *testing.T) { +- return func(t *testing.T) { +- t.Parallel() +- if tt.vcs != "mod" { +- testenv.MustHaveExecPath(t, tt.vcs) +- } ++ repo := Lookup("direct", tt.path) + +- repo := Lookup("direct", tt.path) ++ if tt.mpath == "" { ++ tt.mpath = tt.path ++ } ++ if mpath := repo.ModulePath(); mpath != tt.mpath { ++ t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) ++ } + +- if tt.mpath == "" { +- tt.mpath = tt.path +- } +- if mpath := repo.ModulePath(); mpath != tt.mpath { +- t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) ++ info, err := repo.Stat(tt.rev) ++ if err != nil { ++ if tt.err != "" { ++ if !strings.Contains(err.Error(), tt.err) { ++ t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) ++ } ++ return + } ++ t.Fatalf("repo.Stat(%q): %v", tt.rev, err) ++ } ++ if tt.err != "" { ++ t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) ++ } ++ if info.Version != tt.version { ++ t.Errorf("info.Version = %q, want %q", info.Version, tt.version) ++ } ++ if info.Name != tt.name { ++ t.Errorf("info.Name = %q, want %q", info.Name, tt.name) ++ } ++ if info.Short != tt.short { ++ t.Errorf("info.Short = %q, want %q", info.Short, tt.short) ++ } ++ if !info.Time.Equal(tt.time) { ++ t.Errorf("info.Time = %v, want %v", info.Time, tt.time) ++ } + +- info, err := repo.Stat(tt.rev) +- if err != nil { +- if tt.err != "" { +- if !strings.Contains(err.Error(), tt.err) { +- t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) +- } +- return ++ if tt.gomod != "" || tt.gomodErr != "" { ++ data, err := repo.GoMod(tt.version) ++ if err != nil && tt.gomodErr == "" { ++ t.Errorf("repo.GoMod(%q): %v", tt.version, err) ++ } else if err != nil && tt.gomodErr != "" { ++ if err.Error() != tt.gomodErr { ++ t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr) + } +- t.Fatalf("repo.Stat(%q): %v", tt.rev, err) +- } +- if tt.err != "" { +- t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) +- } +- if info.Version != tt.version { +- t.Errorf("info.Version = %q, want %q", info.Version, tt.version) ++ } else if tt.gomodErr != "" { ++ t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr) ++ } else if string(data) != tt.gomod { ++ t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) + } +- if info.Name != tt.name { +- t.Errorf("info.Name = %q, want %q", info.Name, tt.name) +- } +- if info.Short != tt.short { +- t.Errorf("info.Short = %q, want %q", info.Short, tt.short) ++ } ++ ++ needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") ++ if tt.zip != nil || tt.zipErr != "" || needHash { ++ f, err := os.CreateTemp(tmpdir, tt.version+".zip.") ++ if err != nil { ++ t.Fatalf("os.CreateTemp: %v", err) + } +- if !info.Time.Equal(tt.time) { +- t.Errorf("info.Time = %v, want %v", info.Time, tt.time) ++ zipfile := f.Name() ++ defer func() { ++ f.Close() ++ os.Remove(zipfile) ++ }() ++ ++ var w io.Writer ++ var h hash.Hash ++ if needHash { ++ h = sha256.New() ++ w = io.MultiWriter(f, h) ++ } else { ++ w = f + } +- +- if tt.gomod != "" || tt.gomodErr != "" { +- data, err := repo.GoMod(tt.version) +- if err != nil && tt.gomodErr == "" { +- t.Errorf("repo.GoMod(%q): %v", tt.version, err) +- } else if err != nil && tt.gomodErr != "" { +- if err.Error() != tt.gomodErr { +- t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomodErr) ++ err = repo.Zip(w, tt.version) ++ f.Close() ++ if err != nil { ++ if tt.zipErr != "" { ++ if err.Error() == tt.zipErr { ++ return + } +- } else if tt.gomodErr != "" { +- t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomodErr) +- } else if string(data) != tt.gomod { +- t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) ++ t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr) + } ++ t.Fatalf("repo.Zip(%q): %v", tt.version, err) ++ } ++ if tt.zipErr != "" { ++ t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr) + } + +- needHash := !testing.Short() && (tt.zipFileHash != "" || tt.zipSum != "") +- if tt.zip != nil || tt.zipErr != "" || needHash { +- f, err := os.CreateTemp(tmpdir, tt.version+".zip.") ++ if tt.zip != nil { ++ prefix := tt.path + "@" + tt.version + "/" ++ z, err := zip.OpenReader(zipfile) + if err != nil { +- t.Fatalf("os.CreateTemp: %v", err) ++ t.Fatalf("open zip %s: %v", zipfile, err) + } +- zipfile := f.Name() +- defer func() { +- f.Close() +- os.Remove(zipfile) +- }() +- +- var w io.Writer +- var h hash.Hash +- if needHash { +- h = sha256.New() +- w = io.MultiWriter(f, h) +- } else { +- w = f +- } +- err = repo.Zip(w, tt.version) +- f.Close() +- if err != nil { +- if tt.zipErr != "" { +- if err.Error() == tt.zipErr { +- return +- } +- t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.zipErr) ++ var names []string ++ for _, file := range z.File { ++ if !strings.HasPrefix(file.Name, prefix) { ++ t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) ++ continue + } +- t.Fatalf("repo.Zip(%q): %v", tt.version, err) +- } +- if tt.zipErr != "" { +- t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.zipErr) ++ names = append(names, file.Name[len(prefix):]) + } +- +- if tt.zip != nil { +- prefix := tt.path + "@" + tt.version + "/" +- z, err := zip.OpenReader(zipfile) +- if err != nil { +- t.Fatalf("open zip %s: %v", zipfile, err) +- } +- var names []string +- for _, file := range z.File { +- if !strings.HasPrefix(file.Name, prefix) { +- t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) +- continue +- } +- names = append(names, file.Name[len(prefix):]) +- } +- z.Close() +- if !reflect.DeepEqual(names, tt.zip) { +- t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) +- } ++ z.Close() ++ if !reflect.DeepEqual(names, tt.zip) { ++ t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) + } ++ } + +- if needHash { +- sum, err := dirhash.HashZip(zipfile, dirhash.Hash1) +- if err != nil { +- t.Errorf("repo.Zip(%q): %v", tt.version, err) +- } else if sum != tt.zipSum { +- t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum) +- } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash { +- t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash) +- } ++ if needHash { ++ sum, err := dirhash.HashZip(zipfile, dirhash.Hash1) ++ if err != nil { ++ t.Errorf("repo.Zip(%q): %v", tt.version, err) ++ } else if sum != tt.zipSum { ++ t.Errorf("repo.Zip(%q): got file with sum %q, want %q", tt.version, sum, tt.zipSum) ++ } else if zipFileHash := hex.EncodeToString(h.Sum(nil)); zipFileHash != tt.zipFileHash { ++ t.Errorf("repo.Zip(%q): got file with hash %q, want %q (but content has correct sum)", tt.version, zipFileHash, tt.zipFileHash) + } + } + } + } +- t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) +- if strings.HasPrefix(tt.path, vgotest1git) { +- for vcs, alt := range altVgotests { +- altTest := tt +- altTest.vcs = vcs +- altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git) +- if strings.HasPrefix(altTest.mpath, vgotest1git) { +- altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git) +- } +- var m map[string]string +- if alt == vgotest1hg { +- m = hgmap +- } +- altTest.version = remap(altTest.version, m) +- altTest.name = remap(altTest.name, m) +- altTest.short = remap(altTest.short, m) +- altTest.rev = remap(altTest.rev, m) +- altTest.err = remap(altTest.err, m) +- altTest.gomodErr = remap(altTest.gomodErr, m) +- altTest.zipErr = remap(altTest.zipErr, m) +- altTest.zipSum = "" +- altTest.zipFileHash = "" +- t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest)) ++ } ++ t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.rev, f(tt)) ++ if strings.HasPrefix(tt.path, vgotest1git) { ++ for vcs, alt := range altVgotests { ++ altTest := tt ++ altTest.vcs = vcs ++ altTest.path = alt + strings.TrimPrefix(altTest.path, vgotest1git) ++ if strings.HasPrefix(altTest.mpath, vgotest1git) { ++ altTest.mpath = alt + strings.TrimPrefix(altTest.mpath, vgotest1git) ++ } ++ var m map[string]string ++ if alt == vgotest1hg { ++ m = hgmap + } ++ altTest.version = remap(altTest.version, m) ++ altTest.name = remap(altTest.name, m) ++ altTest.short = remap(altTest.short, m) ++ altTest.rev = remap(altTest.rev, m) ++ altTest.err = remap(altTest.err, m) ++ altTest.gomodErr = remap(altTest.gomodErr, m) ++ altTest.zipErr = remap(altTest.zipErr, m) ++ altTest.zipSum = "" ++ altTest.zipFileHash = "" ++ t.Run(strings.ReplaceAll(altTest.path, "/", "_")+"/"+altTest.rev, f(altTest)) + } + } +- }) ++ } + } + + var hgmap = map[string]string{ +diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt +index 6846a792a5d..d16991dd416 100644 +--- a/src/cmd/go/testdata/script/mod_invalid_version.txt ++++ b/src/cmd/go/testdata/script/mod_invalid_version.txt +@@ -194,10 +194,10 @@ cp go.mod.orig go.mod + go mod edit -require github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d+incompatible + cd outside + ! go list -m github.com/pierrec/lz4 +-stderr 'go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' ++stderr '^go list -m: example.com@v0.0.0 requires\n\tgithub.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' + cd .. + ! go list -m github.com/pierrec/lz4 +-stderr 'github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' ++stderr '^go list -m: github.com/pierrec/lz4@v2.0.9-0.20190209155647-9a39efadad3d\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' + + # A +incompatible pseudo-version is valid for a revision of the module + # that lacks a go.mod file. +@@ -222,7 +222,7 @@ stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible' + # not resolve to a pseudo-version with a different major version. + cp go.mod.orig go.mod + ! go get -d github.com/pierrec/lz4@v2.0.8 +-stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' ++stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' + + # An invalid +incompatible suffix for a canonical version should error out, + # not resolve to a pseudo-version. +@@ -233,10 +233,10 @@ cp go.mod.orig go.mod + go mod edit -require github.com/pierrec/lz4@v2.0.8+incompatible + cd outside + ! go list -m github.com/pierrec/lz4 +-stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' ++stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' + cd .. + ! go list -m github.com/pierrec/lz4 +-stderr 'github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required' ++stderr '^go list -m: github.com/pierrec/lz4@v2.0.8\+incompatible: invalid version: module contains a go.mod file, so module path must match major version \("github.com/pierrec/lz4/v2"\)$' + + -- go.mod.orig -- + module example.com +-- +2.30.0 + diff --git a/0026-release-branch.go1.17-regexp-syntax-reject-very-deep.patch b/0026-release-branch.go1.17-regexp-syntax-reject-very-deep.patch new file mode 100644 index 0000000..e09e5b1 --- /dev/null +++ b/0026-release-branch.go1.17-regexp-syntax-reject-very-deep.patch @@ -0,0 +1,119 @@ +From 94fbe72e320175d2655c04bee76974941edb2491 Mon Sep 17 00:00:00 2001 +From: Russ Cox +Date: Wed, 2 Feb 2022 16:41:32 -0500 +Subject: [PATCH] regexp/syntax: reject very deeply nested regexps in Parse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The regexp code assumes it can recurse over the structure of +a regexp safely. Go's growable stacks make that reasonable +for all plausible regexps, but implausible ones can reach the +“infinite recursion?” stack limit. + +This CL limits the depth of any parsed regexp to 1000. +That is, the depth of the parse tree is required to be ≤ 1000. +Regexps that require deeper parse trees will return ErrInternalError. +A future CL will change the error to ErrInvalidDepth, +but using ErrInternalError for now avoids introducing new API +in point releases when this is backported. + +Fixes #51112. +Fixes #51118. + +Change-Id: I97d2cd82195946eb43a4ea8561f5b95f91fb14c5 +Reviewed-on: https://go-review.googlesource.com/c/go/+/384616 +Trust: Russ Cox +Run-TryBot: Russ Cox +Reviewed-by: Ian Lance Taylor +Reviewed-on: https://go-review.googlesource.com/c/go/+/384854 +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/384854/ +--- + src/regexp/syntax/parse.go | 19 ++++++------------- + src/regexp/syntax/parse_test.go | 5 +++++ + 2 files changed, 11 insertions(+), 13 deletions(-) + +diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go +index 67254d6..3792960 100644 +--- a/src/regexp/syntax/parse.go ++++ b/src/regexp/syntax/parse.go +@@ -43,7 +43,6 @@ const ( + ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator" + ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression" + ErrUnexpectedParen ErrorCode = "unexpected )" +- ErrNestingDepth ErrorCode = "expression nests too deeply" + ) + + func (e ErrorCode) String() string { +@@ -266,7 +265,7 @@ func (p *parser) checkHeight(re *Regexp) { + } + } + if p.calcHeight(re, true) > maxHeight { +- panic(ErrNestingDepth) ++ panic(ErrInternalError) + } + } + +@@ -578,16 +577,12 @@ func (p *parser) collapse(subs []*Regexp, op Op) *Regexp { + // frees (passes to p.reuse) any removed *Regexps. + // + // For example, +-// +-// ABC|ABD|AEF|BCX|BCY +-// ++// ABC|ABD|AEF|BCX|BCY + // simplifies by literal prefix extraction to +-// +-// A(B(C|D)|EF)|BC(X|Y) +-// ++// A(B(C|D)|EF)|BC(X|Y) + // which simplifies by character class introduction to ++// A(B[CD]|EF)|BC[XY] + // +-// A(B[CD]|EF)|BC[XY] + func (p *parser) factor(sub []*Regexp) []*Regexp { + if len(sub) < 2 { + return sub +@@ -897,10 +892,8 @@ func parse(s string, flags Flags) (_ *Regexp, err error) { + panic(r) + case nil: + // ok +- case ErrInternalError: // too big ++ case ErrInternalError: + err = &Error{Code: ErrInternalError, Expr: s} +- case ErrNestingDepth: +- err = &Error{Code: ErrNestingDepth, Expr: s} + } + }() + +@@ -1943,7 +1936,7 @@ func appendClass(r []rune, x []rune) []rune { + return r + } + +-// appendFoldedClass returns the result of appending the case folding of the class x to the class r. ++// appendFolded returns the result of appending the case folding of the class x to the class r. + func appendFoldedClass(r []rune, x []rune) []rune { + for i := 0; i < len(x); i += 2 { + r = appendFoldedRange(r, x[i], x[i+1]) +diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go +index 6044da6..67e3c56 100644 +--- a/src/regexp/syntax/parse_test.go ++++ b/src/regexp/syntax/parse_test.go +@@ -207,6 +207,11 @@ var parseTests = []parseTest{ + // Valid repetitions. + {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``}, + {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``}, ++ ++ // Valid nesting. ++ {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``}, ++ {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``}, ++ {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all + } + + const testFlags = MatchNL | PerlX | UnicodeGroups +-- +2.33.0 + diff --git a/0027-release-branch.go1.17-net-http-update-bundled-golang.patch b/0027-release-branch.go1.17-net-http-update-bundled-golang.patch new file mode 100644 index 0000000..4df9587 --- /dev/null +++ b/0027-release-branch.go1.17-net-http-update-bundled-golang.patch @@ -0,0 +1,94 @@ +From 9b62e5e5e979905fd53919dfa4ad53458574ee61 Mon Sep 17 00:00:00 2001 +From: Filippo Valsorda +Date: Thu, 9 Dec 2021 06:32:14 -0500 +Subject: [PATCH 4/6] [release-branch.go1.17] net/http: update bundled + golang.org/x/net/http2 + +Pull in security fix + + 84cba54 http2: cap the size of the server's canonical header cache + +Updates #50058 +Fixes CVE-2021-44716 + +Change-Id: Ia89e3d22a173c6cb83f03608d5186fcd08f2956c +Reviewed-on: https://go-review.googlesource.com/c/go/+/370574 +Trust: Filippo Valsorda +Run-TryBot: Filippo Valsorda +Reviewed-by: Alex Rakoczy +TryBot-Result: Gopher Robot + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/370574 +--- + src/go.mod | 2 +- + src/go.sum | 4 ++-- + src/net/http/h2_bundle.go | 10 +++++++++- + src/vendor/modules.txt | 2 +- + 4 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/src/go.mod b/src/go.mod +index 386b51a6569..ada50077937 100644 +--- a/src/go.mod ++++ b/src/go.mod +@@ -4,7 +4,7 @@ go 1.17 + + require ( + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e +- golang.org/x/net v0.0.0-20211101194204-95aca89e93de ++ golang.org/x/net v0.0.0-20211209100829-84cba5454caf + ) + + require ( +diff --git a/src/go.sum b/src/go.sum +index 1f328206ecb..3e181c992f5 100644 +--- a/src/go.sum ++++ b/src/go.sum +@@ -1,8 +1,8 @@ + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +-golang.org/x/net v0.0.0-20211101194204-95aca89e93de h1:dKoXPECQZ51dGVSkuiD9YzeNpLT4UPUY4d3xo0sWrkU= +-golang.org/x/net v0.0.0-20211101194204-95aca89e93de/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= ++golang.org/x/net v0.0.0-20211209100829-84cba5454caf h1:Chci/BE/+xVqrcWnObL99NS8gtXyJrhHDlygBQrggHM= ++golang.org/x/net v0.0.0-20211209100829-84cba5454caf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= + golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q= +diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go +index 9112079a224..1b73da7f219 100644 +--- a/src/net/http/h2_bundle.go ++++ b/src/net/http/h2_bundle.go +@@ -4382,7 +4382,15 @@ func (sc *http2serverConn) canonicalHeader(v string) string { + sc.canonHeader = make(map[string]string) + } + cv = CanonicalHeaderKey(v) +- sc.canonHeader[v] = cv ++ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of ++ // entries in the canonHeader cache. This should be larger than the number ++ // of unique, uncommon header keys likely to be sent by the peer, while not ++ // so high as to permit unreaasonable memory usage if the peer sends an unbounded ++ // number of unique header keys. ++ const maxCachedCanonicalHeaders = 32 ++ if len(sc.canonHeader) < maxCachedCanonicalHeaders { ++ sc.canonHeader[v] = cv ++ } + return cv + } + +diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt +index f61fc51ba82..bb0b4c561da 100644 +--- a/src/vendor/modules.txt ++++ b/src/vendor/modules.txt +@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 + golang.org/x/crypto/hkdf + golang.org/x/crypto/internal/subtle + golang.org/x/crypto/poly1305 +-# golang.org/x/net v0.0.0-20211101194204-95aca89e93de ++# golang.org/x/net v0.0.0-20211209100829-84cba5454caf + ## explicit; go 1.17 + golang.org/x/net/dns/dnsmessage + golang.org/x/net/http/httpguts +-- +2.30.0 + diff --git a/0028-release-branch.go1.17-math-big-prevent-overflow-in-R.patch b/0028-release-branch.go1.17-math-big-prevent-overflow-in-R.patch new file mode 100644 index 0000000..bff2973 --- /dev/null +++ b/0028-release-branch.go1.17-math-big-prevent-overflow-in-R.patch @@ -0,0 +1,65 @@ +From 174d5787fa52ec66aa29ee20a04b47d98d458082 Mon Sep 17 00:00:00 2001 +From: Katie Hockman +Date: Wed, 19 Jan 2022 16:54:41 -0500 +Subject: [PATCH 6/6] [release-branch.go1.17] math/big: prevent overflow in + (*Rat).SetString + +Credit to rsc@ for the original patch. + +Thanks to the OSS-Fuzz project for discovering this +issue and to Emmanuel Odeke (@odeke_et) for reporting it. + +Updates #50699 +Fixes #50701 +Fixes CVE-2022-23772 + +Change-Id: I590395a3d55689625390cf1e58f5f40623b26ee5 +Reviewed-on: https://go-review.googlesource.com/c/go/+/379537 +Trust: Katie Hockman +Run-TryBot: Katie Hockman +TryBot-Result: Gopher Robot +Reviewed-by: Emmanuel Odeke +Reviewed-by: Roland Shoemaker +Reviewed-by: Julie Qiu +(cherry picked from commit ad345c265916bbf6c646865e4642eafce6d39e78) +Reviewed-on: https://go-review.googlesource.com/c/go/+/381336 +Reviewed-by: Filippo Valsorda + +Conflict: NA +Reference: https://go-review.googlesource.com/c/go/+/381336 +--- + src/math/big/ratconv.go | 5 +++++ + src/math/big/ratconv_test.go | 1 + + 2 files changed, 6 insertions(+) + +diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go +index ac3c8bd11f8..90053a9c81d 100644 +--- a/src/math/big/ratconv.go ++++ b/src/math/big/ratconv.go +@@ -169,6 +169,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) { + n := exp5 + if n < 0 { + n = -n ++ if n < 0 { ++ // This can occur if -n overflows. -(-1 << 63) would become ++ // -1 << 63, which is still negative. ++ return nil, false ++ } + } + if n > 1e6 { + return nil, false // avoid excessively large exponents +diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go +index 15d206cb386..e55e6557189 100644 +--- a/src/math/big/ratconv_test.go ++++ b/src/math/big/ratconv_test.go +@@ -104,6 +104,7 @@ var setStringTests = []StringTest{ + {in: "4/3/"}, + {in: "4/3."}, + {in: "4/"}, ++ {in: "13e-9223372036854775808"}, // CVE-2022-23772 + + // valid + {"0", "0", true}, +-- +2.30.0 + diff --git a/0029-release-branch.go1.18-net-http-update-bundled-golang.patch b/0029-release-branch.go1.18-net-http-update-bundled-golang.patch new file mode 100644 index 0000000..c2fc895 --- /dev/null +++ b/0029-release-branch.go1.18-net-http-update-bundled-golang.patch @@ -0,0 +1,76 @@ +From 15ffef9628c700156c3149d02fd27ea3409a4eb7 Mon Sep 17 00:00:00 2001 +From: Damien Neil +Date: Wed, 30 Nov 2022 16:37:07 -0500 +Subject: [PATCH] [release-branch.go1.18] net/http: update bundled + golang.org/x/net/http2 + +Disable cmd/internal/moddeps test, since this update includes PRIVATE +track fixes. + +For #56350 +For #57008 +Fixes CVE-2022-41717 + +Change-Id: I31ebd2b9ae190ef6f7646187103ea1c8a713ff2e +Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1663833 +Reviewed-by: Tatiana Bradley +Reviewed-by: Julie Qiu +Reviewed-on: https://go-review.googlesource.com/c/go/+/455361 +Run-TryBot: Jenny Rakoczy +Reviewed-by: Michael Pratt +TryBot-Result: Gopher Robot + +Reference:https://go-review.googlesource.com/c/go/+/455361 +Conflict: NA + +--- + src/net/http/h2_bundle.go | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go +index d7e2f764c8..5433ebdc51 100644 +--- a/src/net/http/h2_bundle.go ++++ b/src/net/http/h2_bundle.go +@@ -4189,6 +4189,7 @@ type http2serverConn struct { + headerTableSize uint32 + peerMaxHeaderListSize uint32 // zero means unknown (default) + canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case ++ canonHeaderKeysSize int // canonHeader keys size in bytes + writingFrame bool // started writing a frame (on serve goroutine or separate) + writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh + needsFrameFlush bool // last frame write wasn't a flush +@@ -4368,6 +4369,13 @@ func (sc *http2serverConn) condlogf(err error, format string, args ...interface{ + } + } + ++// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size ++// of the entries in the canonHeader cache. ++// This should be larger than the size of unique, uncommon header keys likely to ++// be sent by the peer, while not so high as to permit unreasonable memory usage ++// if the peer sends an unbounded number of unique header keys. ++const http2maxCachedCanonicalHeadersKeysSize = 2048 ++ + func (sc *http2serverConn) canonicalHeader(v string) string { + sc.serveG.check() + http2buildCommonHeaderMapsOnce() +@@ -4383,14 +4391,10 @@ func (sc *http2serverConn) canonicalHeader(v string) string { + sc.canonHeader = make(map[string]string) + } + cv = CanonicalHeaderKey(v) +- // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of +- // entries in the canonHeader cache. This should be larger than the number +- // of unique, uncommon header keys likely to be sent by the peer, while not +- // so high as to permit unreaasonable memory usage if the peer sends an unbounded +- // number of unique header keys. +- const maxCachedCanonicalHeaders = 32 +- if len(sc.canonHeader) < maxCachedCanonicalHeaders { ++ size := 100 + len(v)*2 // 100 bytes of map overhead + key + value ++ if sc.canonHeaderKeysSize+size <= http2maxCachedCanonicalHeadersKeysSize { + sc.canonHeader[v] = cv ++ sc.canonHeaderKeysSize += size + } + return cv + } +-- +2.33.0 + diff --git a/golang.spec b/golang.spec index 1fab441..c13d992 100644 --- a/golang.spec +++ b/golang.spec @@ -66,7 +66,7 @@ Name: golang Version: 1.17.3 -Release: 13 +Release: 14 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -181,6 +181,12 @@ Patch6020: 0020-release-branch.go1.18-regexp-limit-size-of-parsed-re.patch Patch6021: 0021-release-branch.go1.18-net-http-httputil-avoid-query-.patch Patch6022: 0022-release-branch.go1.18-archive-tar-limit-size-of-head.patch Patch6023: 0023-syscall-os-exec-reject-environment-variables-contain.patch +Patch6024: 0024-release-branch.go1.17-crypto-elliptic-make-IsOnCurve.patch +Patch6025: 0025-release-branch.go1.17-cmd-go-internal-modfetch-do-no.patch +Patch6026: 0026-release-branch.go1.17-regexp-syntax-reject-very-deep.patch +Patch6027: 0027-release-branch.go1.17-net-http-update-bundled-golang.patch +Patch6028: 0028-release-branch.go1.17-math-big-prevent-overflow-in-R.patch +Patch6029: 0029-release-branch.go1.18-net-http-update-bundled-golang.patch ExclusiveArch: %{golang_arches} @@ -426,6 +432,12 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Fri Jan 20 2023 hanchao - 1.17.3-14 +- Type:CVE +- CVE:CVE-2022-23806,CVE-2022-23773,CVE-2022-24921,CVE-2021-44716,CVE-2022-23772,CVE-2022-41717 +- SUG:NA +- DESC: fix CVE-2022-23806,CVE-2022-23773,CVE-2022-24921,CVE-2021-44716,CVE-2022-23772,CVE-2022-41717 + * Thu Dec 15 2022 chenguoqi - 1.17.3-13 - Add loongarch64 base support -- Gitee