--- Begin Message ---
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
--- End Message ---