Package: release.debian.org Severity: normal Tags: bullseye User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: z...@debian.org, t...@security.debian.org
[ Reason ] Backport patch for CVE-2022-24921. [ Impact ] CVE-2022-24921: regexp: stack exhaustion compiling deeply nested expressions This is bug in standard library. [ Tests ] The backported patch has new regression tests in it. [ Risks ] Low, change is small. Backport from 1.16 release without modification. [ 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 (old)stable [ ] the issue is verified as fixed in unstable golang-1.15 has been removed from unstable. [ Changes ] See attachment. [ Other info ] I don't think the severity needs to rebuild other Go packages.
diff -Nru golang-1.15-1.15.15/debian/changelog golang-1.15-1.15.15/debian/changelog --- golang-1.15-1.15.15/debian/changelog 2022-02-11 23:45:44.000000000 +0800 +++ golang-1.15-1.15.15/debian/changelog 2022-03-04 21:48:18.000000000 +0800 @@ -1,3 +1,10 @@ +golang-1.15 (1.15.15-1~deb11u4) bullseye; urgency=medium + + * Backport patch for CVE-2022-24921: + regexp: stack exhaustion compiling deeply nested expressions + + -- Shengjing Zhu <z...@debian.org> Fri, 04 Mar 2022 21:48:18 +0800 + golang-1.15 (1.15.15-1~deb11u3) bullseye; urgency=medium * Backport patches for CVE-2022-23806 CVE-2022-23772 CVE-2022-23773 diff -Nru golang-1.15-1.15.15/debian/patches/0015-CVE-2022-24921.patch golang-1.15-1.15.15/debian/patches/0015-CVE-2022-24921.patch --- golang-1.15-1.15.15/debian/patches/0015-CVE-2022-24921.patch 1970-01-01 08:00:00.000000000 +0800 +++ golang-1.15-1.15.15/debian/patches/0015-CVE-2022-24921.patch 2022-03-04 21:48:18.000000000 +0800 @@ -0,0 +1,169 @@ +From: Russ Cox <r...@golang.org> +Date: Wed, 2 Feb 2022 16:41:32 -0500 +Subject: CVE-2022-24921 + +Origin: backport, https://github.com/golang/go/commit/2b65cde5 +--- + src/regexp/syntax/parse.go | 72 +++++++++++++++++++++++++++++++++++++++-- + src/regexp/syntax/parse_test.go | 7 ++++ + 2 files changed, 77 insertions(+), 2 deletions(-) + +diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go +index 7b40309..d7cf2af 100644 +--- a/src/regexp/syntax/parse.go ++++ b/src/regexp/syntax/parse.go +@@ -76,13 +76,29 @@ const ( + opVerticalBar + ) + ++// maxHeight is the maximum height of a regexp parse tree. ++// It is somewhat arbitrarily chosen, but the idea is to be large enough ++// that no one will actually hit in real use but at the same time small enough ++// that recursion on the Regexp tree will not hit the 1GB Go stack limit. ++// The maximum amount of stack for a single recursive frame is probably ++// closer to 1kB, so this could potentially be raised, but it seems unlikely ++// that people have regexps nested even this deeply. ++// We ran a test on Google's C++ code base and turned up only ++// a single use case with depth > 100; it had depth 128. ++// Using depth 1000 should be plenty of margin. ++// As an optimization, we don't even bother calculating heights ++// until we've allocated at least maxHeight Regexp structures. ++const maxHeight = 1000 ++ + type parser struct { + flags Flags // parse mode flags + stack []*Regexp // stack of parsed expressions + free *Regexp + numCap int // number of capturing groups seen + wholeRegexp string +- tmpClass []rune // temporary char class work space ++ tmpClass []rune // temporary char class work space ++ numRegexp int // number of regexps allocated ++ height map[*Regexp]int // regexp height for height limit check + } + + func (p *parser) newRegexp(op Op) *Regexp { +@@ -92,16 +108,52 @@ func (p *parser) newRegexp(op Op) *Regexp { + *re = Regexp{} + } else { + re = new(Regexp) ++ p.numRegexp++ + } + re.Op = op + return re + } + + func (p *parser) reuse(re *Regexp) { ++ if p.height != nil { ++ delete(p.height, re) ++ } + re.Sub0[0] = p.free + p.free = re + } + ++func (p *parser) checkHeight(re *Regexp) { ++ if p.numRegexp < maxHeight { ++ return ++ } ++ if p.height == nil { ++ p.height = make(map[*Regexp]int) ++ for _, re := range p.stack { ++ p.checkHeight(re) ++ } ++ } ++ if p.calcHeight(re, true) > maxHeight { ++ panic(ErrInternalError) ++ } ++} ++ ++func (p *parser) calcHeight(re *Regexp, force bool) int { ++ if !force { ++ if h, ok := p.height[re]; ok { ++ return h ++ } ++ } ++ h := 1 ++ for _, sub := range re.Sub { ++ hsub := p.calcHeight(sub, false) ++ if h < 1+hsub { ++ h = 1 + hsub ++ } ++ } ++ p.height[re] = h ++ return h ++} ++ + // Parse stack manipulation. + + // push pushes the regexp re onto the parse stack and returns the regexp. +@@ -137,6 +189,7 @@ func (p *parser) push(re *Regexp) *Regexp { + } + + p.stack = append(p.stack, re) ++ p.checkHeight(re) + return re + } + +@@ -246,6 +299,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) ( + re.Sub = re.Sub0[:1] + re.Sub[0] = sub + p.stack[n-1] = re ++ p.checkHeight(re) + + if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) { + return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]} +@@ -693,6 +747,21 @@ func literalRegexp(s string, flags Flags) *Regexp { + // Flags, and returns a regular expression parse tree. The syntax is + // described in the top-level comment. + func Parse(s string, flags Flags) (*Regexp, error) { ++ return parse(s, flags) ++} ++ ++func parse(s string, flags Flags) (_ *Regexp, err error) { ++ defer func() { ++ switch r := recover(); r { ++ default: ++ panic(r) ++ case nil: ++ // ok ++ case ErrInternalError: ++ err = &Error{Code: ErrInternalError, Expr: s} ++ } ++ }() ++ + if flags&Literal != 0 { + // Trivial parser for literal string. + if err := checkUTF8(s); err != nil { +@@ -704,7 +773,6 @@ func Parse(s string, flags Flags) (*Regexp, error) { + // Otherwise, must do real work. + var ( + p parser +- err error + c rune + op Op + lastRepeat string +diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go +index 5581ba1..1ef6d8a 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 +@@ -482,6 +487,8 @@ var invalidRegexps = []string{ + `a{100000}`, + `a{100000,}`, + "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", ++ strings.Repeat("(", 1000) + strings.Repeat(")", 1000), ++ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), + `\Q\E*`, + } + diff -Nru golang-1.15-1.15.15/debian/patches/series golang-1.15-1.15.15/debian/patches/series --- golang-1.15-1.15.15/debian/patches/series 2022-02-11 23:45:44.000000000 +0800 +++ golang-1.15-1.15.15/debian/patches/series 2022-03-04 21:48:18.000000000 +0800 @@ -12,3 +12,4 @@ 0012-CVE-2022-23806.patch 0013-CVE-2022-23772.patch 0014-CVE-2022-23773.patch +0015-CVE-2022-24921.patch