summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch198
1 files changed, 198 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch
new file mode 100644
index 0000000000..e4270d8a75
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch
@@ -0,0 +1,198 @@
1From ba99f699d26483ea1045f47c760e9be30799e311 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Wed, 2 Feb 2022 16:41:32 -0500
4Subject: [PATCH] regexp/syntax: reject very deeply nested regexps in Parse
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Upstream-Status: Backport [https://github.com/golang/go/commit/2b65cde5868d8245ef8a0b8eba1e361440252d3b]
10CVE: CVE-2022-24921
11Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org
12
13
14The regexp code assumes it can recurse over the structure of
15a regexp safely. Go's growable stacks make that reasonable
16for all plausible regexps, but implausible ones can reach the
17“infinite recursion?” stack limit.
18
19This CL limits the depth of any parsed regexp to 1000.
20That is, the depth of the parse tree is required to be ≤ 1000.
21Regexps that require deeper parse trees will return ErrInternalError.
22A future CL will change the error to ErrInvalidDepth,
23but using ErrInternalError for now avoids introducing new API
24in point releases when this is backported.
25
26Fixes #51112.
27Fixes #51117.
28
29Change-Id: I97d2cd82195946eb43a4ea8561f5b95f91fb14c5
30Reviewed-on: https://go-review.googlesource.com/c/go/+/384616
31Trust: Russ Cox <rsc@golang.org>
32Run-TryBot: Russ Cox <rsc@golang.org>
33Reviewed-by: Ian Lance Taylor <iant@golang.org>
34Reviewed-on: https://go-review.googlesource.com/c/go/+/384855
35---
36 src/regexp/syntax/parse.go | 72 ++++++++++++++++++++++++++++++++-
37 src/regexp/syntax/parse_test.go | 7 ++++
38 2 files changed, 77 insertions(+), 2 deletions(-)
39
40diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
41index 8c6d43a..55bd20d 100644
42--- a/src/regexp/syntax/parse.go
43+++ b/src/regexp/syntax/parse.go
44@@ -76,13 +76,29 @@ const (
45 opVerticalBar
46 )
47
48+// maxHeight is the maximum height of a regexp parse tree.
49+// It is somewhat arbitrarily chosen, but the idea is to be large enough
50+// that no one will actually hit in real use but at the same time small enough
51+// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
52+// The maximum amount of stack for a single recursive frame is probably
53+// closer to 1kB, so this could potentially be raised, but it seems unlikely
54+// that people have regexps nested even this deeply.
55+// We ran a test on Google's C++ code base and turned up only
56+// a single use case with depth > 100; it had depth 128.
57+// Using depth 1000 should be plenty of margin.
58+// As an optimization, we don't even bother calculating heights
59+// until we've allocated at least maxHeight Regexp structures.
60+const maxHeight = 1000
61+
62 type parser struct {
63 flags Flags // parse mode flags
64 stack []*Regexp // stack of parsed expressions
65 free *Regexp
66 numCap int // number of capturing groups seen
67 wholeRegexp string
68- tmpClass []rune // temporary char class work space
69+ tmpClass []rune // temporary char class work space
70+ numRegexp int // number of regexps allocated
71+ height map[*Regexp]int // regexp height for height limit check
72 }
73
74 func (p *parser) newRegexp(op Op) *Regexp {
75@@ -92,16 +108,52 @@ func (p *parser) newRegexp(op Op) *Regexp {
76 *re = Regexp{}
77 } else {
78 re = new(Regexp)
79+ p.numRegexp++
80 }
81 re.Op = op
82 return re
83 }
84
85 func (p *parser) reuse(re *Regexp) {
86+ if p.height != nil {
87+ delete(p.height, re)
88+ }
89 re.Sub0[0] = p.free
90 p.free = re
91 }
92
93+func (p *parser) checkHeight(re *Regexp) {
94+ if p.numRegexp < maxHeight {
95+ return
96+ }
97+ if p.height == nil {
98+ p.height = make(map[*Regexp]int)
99+ for _, re := range p.stack {
100+ p.checkHeight(re)
101+ }
102+ }
103+ if p.calcHeight(re, true) > maxHeight {
104+ panic(ErrInternalError)
105+ }
106+}
107+
108+func (p *parser) calcHeight(re *Regexp, force bool) int {
109+ if !force {
110+ if h, ok := p.height[re]; ok {
111+ return h
112+ }
113+ }
114+ h := 1
115+ for _, sub := range re.Sub {
116+ hsub := p.calcHeight(sub, false)
117+ if h < 1+hsub {
118+ h = 1 + hsub
119+ }
120+ }
121+ p.height[re] = h
122+ return h
123+}
124+
125 // Parse stack manipulation.
126
127 // push pushes the regexp re onto the parse stack and returns the regexp.
128@@ -137,6 +189,7 @@ func (p *parser) push(re *Regexp) *Regexp {
129 }
130
131 p.stack = append(p.stack, re)
132+ p.checkHeight(re)
133 return re
134 }
135
136@@ -252,6 +305,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
137 re.Sub = re.Sub0[:1]
138 re.Sub[0] = sub
139 p.stack[n-1] = re
140+ p.checkHeight(re)
141
142 if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
143 return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
144@@ -699,6 +753,21 @@ func literalRegexp(s string, flags Flags) *Regexp {
145 // Flags, and returns a regular expression parse tree. The syntax is
146 // described in the top-level comment.
147 func Parse(s string, flags Flags) (*Regexp, error) {
148+ return parse(s, flags)
149+}
150+
151+func parse(s string, flags Flags) (_ *Regexp, err error) {
152+ defer func() {
153+ switch r := recover(); r {
154+ default:
155+ panic(r)
156+ case nil:
157+ // ok
158+ case ErrInternalError:
159+ err = &Error{Code: ErrInternalError, Expr: s}
160+ }
161+ }()
162+
163 if flags&Literal != 0 {
164 // Trivial parser for literal string.
165 if err := checkUTF8(s); err != nil {
166@@ -710,7 +779,6 @@ func Parse(s string, flags Flags) (*Regexp, error) {
167 // Otherwise, must do real work.
168 var (
169 p parser
170- err error
171 c rune
172 op Op
173 lastRepeat string
174diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
175index 5581ba1..1ef6d8a 100644
176--- a/src/regexp/syntax/parse_test.go
177+++ b/src/regexp/syntax/parse_test.go
178@@ -207,6 +207,11 @@ var parseTests = []parseTest{
179 // Valid repetitions.
180 {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
181 {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
182+
183+ // Valid nesting.
184+ {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``},
185+ {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``},
186+ {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all
187 }
188
189 const testFlags = MatchNL | PerlX | UnicodeGroups
190@@ -482,6 +487,8 @@ var invalidRegexps = []string{
191 `a{100000}`,
192 `a{100000,}`,
193 "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
194+ strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
195+ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
196 `\Q\E*`,
197 }
198