golang: fix CVE-2022-32148,CVE-2022-1962,CVE-2022-1705,CVE-2022-30633,
CVE-2022-30635,CVE-2022-30632,CVE-2022-28131, CVE-2022-30631,CVE-2022-30629,CVE-2022-30634 Conflict: CVE-2022-1962: src/go/parser/parser.go CVE-2022-1705: src/net/http/transfer.go CVE-2022-30634: src/crypto/rand/rand.go, src/crypto/rand/rand_windows.go Score: CVE-2022-32148: 5.3 CVE-2022-1962: 6.2 CVE-2022-1705: 5.3 CVE-2022-30633: 6.2 CVE-2022-30635: 5.5 CVE-2022-30632: 6.2 CVE-2022-28131: 6.2 CVE-2022-30631: 7.5 CVE-2022-30629: 2.6 CVE-2022-30634: 7.5 Reference: CVE-2022-32148: https://go-review.googlesource.com/c/go/+/415221 CVE-2022-1962: https://go-review.googlesource.com/c/go/+/417070 CVE-2022-1705: https://go-review.googlesource.com/c/go/+/415217 CVE-2022-30633: https://go-review.googlesource.com/c/go/+/417069 CVE-2022-30635: https://go-review.googlesource.com/c/go/+/417074 CVE-2022-30632: https://go-review.googlesource.com/c/go/+/417073 CVE-2022-28131: https://go-review.googlesource.com/c/go/+/417068 CVE-2022-30631: https://go-review.googlesource.com/c/go/+/417071 CVE-2022-30629: https://go-review.googlesource.com/c/go/+/408574 CVE-2022-30634: https://go-review.googlesource.com/c/go/+/406635 Reason: fix CVE CVE-2022-32148: 0064-release-branch.go1.17-net-http-preserve-nil-values-i.patch CVE-2022-1962: 0065-release-branch.go1.17-go-parser-limit-recursion-dept.patch CVE-2022-1705: 0066-release-branch.go1.17-net-http-don-t-strip-whitespac.patch CVE-2022-30633: 0067-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch CVE-2022-30635: 0068-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch CVE-2022-30632: 0069-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch CVE-2022-28131: 0070-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch CVE-2022-30631: 0071-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch CVE-2022-30629: 0072-release-branch.go1.17-crypto-tls-randomly-generate-t.patch CVE-2022-30634: 0073-release-branch.go1.17-crypto-rand-properly-handle-la.patch
This commit is contained in:
parent
d4f214f4dc
commit
4eff8aee0d
@ -0,0 +1,70 @@
|
||||
From a6115663a62fb5559d023e32058f2219dd466095 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Fri, 17 Jun 2022 10:09:45 -0700
|
||||
Subject: [PATCH 01/10] [release-branch.go1.17] net/http: preserve nil values
|
||||
in Header.Clone
|
||||
|
||||
ReverseProxy makes a distinction between nil and zero-length header values.
|
||||
Avoid losing nil-ness when cloning a request.
|
||||
|
||||
Thanks to Christian Mehlmauer for discovering this.
|
||||
|
||||
For #53423
|
||||
For CVE-2022-32148
|
||||
Fixes #53620
|
||||
|
||||
Change-Id: Ice369cdb4712e2d62e25bb881b080847aa4801f5
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/412857
|
||||
Reviewed-by: Ian Lance Taylor <iant@google.com>
|
||||
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
(cherry picked from commit b2cc0fecc2ccd80e6d5d16542cc684f97b3a9c8a)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/415221
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
Run-TryBot: Heschi Kreinick <heschi@google.com>
|
||||
Reviewed-by: Michael Knyszek <mknyszek@google.com>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/415221
|
||||
---
|
||||
src/net/http/header.go | 6 ++++++
|
||||
src/net/http/header_test.go | 5 +++++
|
||||
2 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/src/net/http/header.go b/src/net/http/header.go
|
||||
index b9b53911f38..221f613f642 100644
|
||||
--- a/src/net/http/header.go
|
||||
+++ b/src/net/http/header.go
|
||||
@@ -100,6 +100,12 @@ func (h Header) Clone() Header {
|
||||
sv := make([]string, nv) // shared backing array for headers' values
|
||||
h2 := make(Header, len(h))
|
||||
for k, vv := range h {
|
||||
+ if vv == nil {
|
||||
+ // Preserve nil values. ReverseProxy distinguishes
|
||||
+ // between nil and zero-length header values.
|
||||
+ h2[k] = nil
|
||||
+ continue
|
||||
+ }
|
||||
n := copy(sv, vv)
|
||||
h2[k] = sv[:n:n]
|
||||
sv = sv[n:]
|
||||
diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go
|
||||
index 47893629194..80c003551db 100644
|
||||
--- a/src/net/http/header_test.go
|
||||
+++ b/src/net/http/header_test.go
|
||||
@@ -235,6 +235,11 @@ func TestCloneOrMakeHeader(t *testing.T) {
|
||||
in: Header{"foo": {"bar"}},
|
||||
want: Header{"foo": {"bar"}},
|
||||
},
|
||||
+ {
|
||||
+ name: "nil value",
|
||||
+ in: Header{"foo": nil},
|
||||
+ want: Header{"foo": nil},
|
||||
+ },
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
--
|
||||
2.30.2
|
||||
|
||||
418
0065-release-branch.go1.17-go-parser-limit-recursion-dept.patch
Normal file
418
0065-release-branch.go1.17-go-parser-limit-recursion-dept.patch
Normal file
@ -0,0 +1,418 @@
|
||||
From ef7049cb34d5e2d3b4afbd37d3964cd8baf07282 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Wed, 15 Jun 2022 10:43:05 -0700
|
||||
Subject: [PATCH] go/parser: limit recursion depth
|
||||
|
||||
Limit nested parsing to 100,000, which prevents stack exhaustion when
|
||||
parsing deeply nested statements, types, and expressions. Also limit
|
||||
the scope depth to 1,000 during object resolution.
|
||||
|
||||
Thanks to Juho Nurminen of Mattermost for reporting this issue.
|
||||
|
||||
Fixes #53707
|
||||
Updates #53616
|
||||
Fixes CVE-2022-1962
|
||||
|
||||
Change-Id: I4d7b86c1d75d0bf3c7af1fdea91582aa74272c64
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1491025
|
||||
Reviewed-by: Russ Cox <rsc@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit 6a856f08d58e4b6705c0c337d461c540c1235c83)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417070
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
|
||||
Conflict: src/go/parser/parser.go
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417070
|
||||
---
|
||||
src/go/parser/interface.go | 25 +++--
|
||||
src/go/parser/parser.go | 64 ++++++++++---
|
||||
src/go/parser/parser_test.go | 171 +++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 240 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go
|
||||
index 54f9d7b..9fc9f7a 100644
|
||||
--- a/src/go/parser/interface.go
|
||||
+++ b/src/go/parser/interface.go
|
||||
@@ -49,13 +49,14 @@ func readSource(filename string, src interface{}) ([]byte, error) {
|
||||
type Mode uint
|
||||
|
||||
const (
|
||||
- PackageClauseOnly Mode = 1 << iota // stop parsing after package clause
|
||||
- ImportsOnly // stop parsing after import declarations
|
||||
- ParseComments // parse comments and add them to AST
|
||||
- Trace // print a trace of parsed productions
|
||||
- DeclarationErrors // report declaration errors
|
||||
- SpuriousErrors // same as AllErrors, for backward-compatibility
|
||||
- AllErrors = SpuriousErrors // report all errors (not just the first 10 on different lines)
|
||||
+ PackageClauseOnly Mode = 1 << iota // stop parsing after package clause
|
||||
+ ImportsOnly // stop parsing after import declarations
|
||||
+ ParseComments // parse comments and add them to AST
|
||||
+ Trace // print a trace of parsed productions
|
||||
+ DeclarationErrors // report declaration errors
|
||||
+ SpuriousErrors // same as AllErrors, for backward-compatibility
|
||||
+ SkipObjectResolution // don't resolve identifiers to objects - see ParseFile
|
||||
+ AllErrors = SpuriousErrors // report all errors (not just the first 10 on different lines)
|
||||
)
|
||||
|
||||
// ParseFile parses the source code of a single Go source file and returns
|
||||
@@ -92,8 +93,11 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// resume same panic if it's not a bailout
|
||||
- if _, ok := e.(bailout); !ok {
|
||||
+ bail, ok := e.(bailout)
|
||||
+ if !ok {
|
||||
panic(e)
|
||||
+ } else if bail.msg != "" {
|
||||
+ p.errors.Add(p.file.Position(bail.pos), bail.msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,8 +192,11 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
// resume same panic if it's not a bailout
|
||||
- if _, ok := e.(bailout); !ok {
|
||||
+ bail, ok := e.(bailout)
|
||||
+ if !ok {
|
||||
panic(e)
|
||||
+ } else if bail.msg != "" {
|
||||
+ p.errors.Add(p.file.Position(bail.pos), bail.msg)
|
||||
}
|
||||
}
|
||||
p.errors.Sort()
|
||||
diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
|
||||
index 31a7398..29bf774 100644
|
||||
--- a/src/go/parser/parser.go
|
||||
+++ b/src/go/parser/parser.go
|
||||
@@ -68,6 +68,10 @@ type parser struct {
|
||||
// (maintained by open/close LabelScope)
|
||||
labelScope *ast.Scope // label scope for current function
|
||||
targetStack [][]*ast.Ident // stack of unresolved labels
|
||||
+
|
||||
+ // nestLev is used to track and limit the recursion depth
|
||||
+ // during parsing.
|
||||
+ nestLev int
|
||||
}
|
||||
|
||||
func (p *parser) init(fset *token.FileSet, filename string, src []byte, mode Mode) {
|
||||
@@ -236,6 +240,24 @@ func un(p *parser) {
|
||||
p.printTrace(")")
|
||||
}
|
||||
|
||||
+// maxNestLev is the deepest we're willing to recurse during parsing
|
||||
+const maxNestLev int = 1e5
|
||||
+
|
||||
+func incNestLev(p *parser) *parser {
|
||||
+ p.nestLev++
|
||||
+ if p.nestLev > maxNestLev {
|
||||
+ p.error(p.pos, "exceeded max nesting depth")
|
||||
+ panic(bailout{})
|
||||
+ }
|
||||
+ return p
|
||||
+}
|
||||
+
|
||||
+// decNestLev is used to track nesting depth during parsing to prevent stack exhaustion.
|
||||
+// It is used along with incNestLev in a similar fashion to how un and trace are used.
|
||||
+func decNestLev(p *parser) {
|
||||
+ p.nestLev--
|
||||
+}
|
||||
+
|
||||
// Advance to the next token.
|
||||
func (p *parser) next0() {
|
||||
// Because of one-token look-ahead, print the previous token
|
||||
@@ -348,8 +370,12 @@ func (p *parser) next() {
|
||||
}
|
||||
}
|
||||
|
||||
-// A bailout panic is raised to indicate early termination.
|
||||
-type bailout struct{}
|
||||
+// A bailout panic is raised to indicate early termination. pos and msg are
|
||||
+// only populated when bailing out of object resolution.
|
||||
+type bailout struct {
|
||||
+ pos token.Pos
|
||||
+ msg string
|
||||
+}
|
||||
|
||||
func (p *parser) error(pos token.Pos, msg string) {
|
||||
epos := p.file.Position(pos)
|
||||
@@ -1030,6 +1056,8 @@ func (p *parser) parseChanType() *ast.ChanType {
|
||||
|
||||
// If the result is an identifier, it is not resolved.
|
||||
func (p *parser) tryIdentOrType() ast.Expr {
|
||||
+ defer decNestLev(incNestLev(p))
|
||||
+
|
||||
switch p.tok {
|
||||
case token.IDENT:
|
||||
return p.parseTypeName()
|
||||
@@ -1470,14 +1498,19 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
|
||||
}
|
||||
|
||||
// If lhs is set and the result is an identifier, it is not resolved.
|
||||
-func (p *parser) parsePrimaryExpr(lhs bool) ast.Expr {
|
||||
+func (p *parser) parsePrimaryExpr(lhs bool) (x ast.Expr) {
|
||||
if p.trace {
|
||||
defer un(trace(p, "PrimaryExpr"))
|
||||
}
|
||||
|
||||
- x := p.parseOperand(lhs)
|
||||
-L:
|
||||
- for {
|
||||
+ x = p.parseOperand(lhs)
|
||||
+ // We track the nesting here rather than at the entry for the function,
|
||||
+ // since it can iteratively produce a nested output, and we want to
|
||||
+ // limit how deep a structure we generate.
|
||||
+ var n int
|
||||
+ defer func() { p.nestLev -= n }()
|
||||
+ for n = 1; ; n++ {
|
||||
+ incNestLev(p)
|
||||
switch p.tok {
|
||||
case token.PERIOD:
|
||||
p.next()
|
||||
@@ -1513,19 +1546,18 @@ L:
|
||||
}
|
||||
x = p.parseLiteralValue(x)
|
||||
} else {
|
||||
- break L
|
||||
+ return
|
||||
}
|
||||
default:
|
||||
- break L
|
||||
+ return
|
||||
}
|
||||
lhs = false // no need to try to resolve again
|
||||
}
|
||||
-
|
||||
- return x
|
||||
}
|
||||
|
||||
// If lhs is set and the result is an identifier, it is not resolved.
|
||||
func (p *parser) parseUnaryExpr(lhs bool) ast.Expr {
|
||||
+ defer decNestLev(incNestLev(p))
|
||||
if p.trace {
|
||||
defer un(trace(p, "UnaryExpr"))
|
||||
}
|
||||
@@ -1609,7 +1641,13 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
|
||||
}
|
||||
|
||||
x := p.parseUnaryExpr(lhs)
|
||||
- for {
|
||||
+ // We track the nesting here rather than at the entry for the function,
|
||||
+ // since it can iteratively produce a nested output, and we want to
|
||||
+ // limit how deep a structure we generate.
|
||||
+ var n int
|
||||
+ defer func() { p.nestLev -= n }()
|
||||
+ for n = 1; ; n++ {
|
||||
+ incNestLev(p)
|
||||
op, oprec := p.tokPrec()
|
||||
if oprec < prec1 {
|
||||
return x
|
||||
@@ -1899,6 +1937,8 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
|
||||
}
|
||||
|
||||
func (p *parser) parseIfStmt() *ast.IfStmt {
|
||||
+ defer decNestLev(incNestLev(p))
|
||||
+
|
||||
if p.trace {
|
||||
defer un(trace(p, "IfStmt"))
|
||||
}
|
||||
@@ -2214,6 +2254,8 @@ func (p *parser) parseForStmt() ast.Stmt {
|
||||
}
|
||||
|
||||
func (p *parser) parseStmt() (s ast.Stmt) {
|
||||
+ defer decNestLev(incNestLev(p))
|
||||
+
|
||||
if p.trace {
|
||||
defer un(trace(p, "Statement"))
|
||||
}
|
||||
diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
|
||||
index 25a374e..344597d 100644
|
||||
--- a/src/go/parser/parser_test.go
|
||||
+++ b/src/go/parser/parser_test.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"os"
|
||||
+ "runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -569,3 +570,173 @@ type x int // comment
|
||||
t.Errorf("got %q, want %q", comment, "// comment")
|
||||
}
|
||||
}
|
||||
+
|
||||
+var parseDepthTests = []struct {
|
||||
+ name string
|
||||
+ format string
|
||||
+ // multipler is used when a single statement may result in more than one
|
||||
+ // change in the depth level, for instance "1+(..." produces a BinaryExpr
|
||||
+ // followed by a UnaryExpr, which increments the depth twice. The test
|
||||
+ // case comment explains which nodes are triggering the multiple depth
|
||||
+ // changes.
|
||||
+ parseMultiplier int
|
||||
+ // scope is true if we should also test the statement for the resolver scope
|
||||
+ // depth limit.
|
||||
+ scope bool
|
||||
+ // scopeMultiplier does the same as parseMultiplier, but for the scope
|
||||
+ // depths.
|
||||
+ scopeMultiplier int
|
||||
+}{
|
||||
+ // The format expands the part inside « » many times.
|
||||
+ // A second set of brackets nested inside the first stops the repetition,
|
||||
+ // so that for example «(«1»)» expands to (((...((((1))))...))).
|
||||
+ {name: "array", format: "package main; var x «[1]»int"},
|
||||
+ {name: "slice", format: "package main; var x «[]»int"},
|
||||
+ {name: "struct", format: "package main; var x «struct { X «int» }»", scope: true},
|
||||
+ {name: "pointer", format: "package main; var x «*»int"},
|
||||
+ {name: "func", format: "package main; var x «func()»int", scope: true},
|
||||
+ {name: "chan", format: "package main; var x «chan »int"},
|
||||
+ {name: "chan2", format: "package main; var x «<-chan »int"},
|
||||
+ {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType
|
||||
+ {name: "map", format: "package main; var x «map[int]»int"},
|
||||
+ {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
+ {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
+ {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
+ {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr
|
||||
+ {name: "dot", format: "package main; var x = «x.»x"},
|
||||
+ {name: "index", format: "package main; var x = x«[1]»"},
|
||||
+ {name: "slice", format: "package main; var x = x«[1:2]»"},
|
||||
+ {name: "slice3", format: "package main; var x = x«[1:2:3]»"},
|
||||
+ {name: "dottype", format: "package main; var x = x«.(any)»"},
|
||||
+ {name: "callseq", format: "package main; var x = x«()»"},
|
||||
+ {name: "methseq", format: "package main; var x = x«.m()»", parseMultiplier: 2}, // Parser nodes: SelectorExpr, CallExpr
|
||||
+ {name: "binary", format: "package main; var x = «1+»1"},
|
||||
+ {name: "binaryparen", format: "package main; var x = «1+(«1»)»", parseMultiplier: 2}, // Parser nodes: BinaryExpr, ParenExpr
|
||||
+ {name: "unary", format: "package main; var x = «^»1"},
|
||||
+ {name: "addr", format: "package main; var x = «& »x"},
|
||||
+ {name: "star", format: "package main; var x = «*»x"},
|
||||
+ {name: "recv", format: "package main; var x = «<-»x"},
|
||||
+ {name: "call", format: "package main; var x = «f(«1»)»", parseMultiplier: 2}, // Parser nodes: Ident, CallExpr
|
||||
+ {name: "conv", format: "package main; var x = «(*T)(«1»)»", parseMultiplier: 2}, // Parser nodes: ParenExpr, CallExpr
|
||||
+ {name: "label", format: "package main; func main() { «Label:» }"},
|
||||
+ {name: "if", format: "package main; func main() { «if true { «» }»}", parseMultiplier: 2, scope: true, scopeMultiplier: 2}, // Parser nodes: IfStmt, BlockStmt. Scopes: IfStmt, BlockStmt
|
||||
+ {name: "ifelse", format: "package main; func main() { «if true {} else » {} }", scope: true},
|
||||
+ {name: "switch", format: "package main; func main() { «switch { default: «» }»}", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
|
||||
+ {name: "typeswitch", format: "package main; func main() { «switch x.(type) { default: «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
|
||||
+ {name: "for0", format: "package main; func main() { «for { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
|
||||
+ {name: "for1", format: "package main; func main() { «for x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
|
||||
+ {name: "for3", format: "package main; func main() { «for f(); g(); h() { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
|
||||
+ {name: "forrange0", format: "package main; func main() { «for range x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
|
||||
+ {name: "forrange1", format: "package main; func main() { «for x = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
|
||||
+ {name: "forrange2", format: "package main; func main() { «for x, y = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
|
||||
+ {name: "go", format: "package main; func main() { «go func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: GoStmt, FuncLit
|
||||
+ {name: "defer", format: "package main; func main() { «defer func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: DeferStmt, FuncLit
|
||||
+ {name: "select", format: "package main; func main() { «select { default: «» }» }", scope: true},
|
||||
+}
|
||||
+
|
||||
+// split splits pre«mid»post into pre, mid, post.
|
||||
+// If the string does not have that form, split returns x, "", "".
|
||||
+func split(x string) (pre, mid, post string) {
|
||||
+ start, end := strings.Index(x, "«"), strings.LastIndex(x, "»")
|
||||
+ if start < 0 || end < 0 {
|
||||
+ return x, "", ""
|
||||
+ }
|
||||
+ return x[:start], x[start+len("«") : end], x[end+len("»"):]
|
||||
+}
|
||||
+
|
||||
+func TestParseDepthLimit(t *testing.T) {
|
||||
+ if runtime.GOARCH == "wasm" {
|
||||
+ t.Skip("causes call stack exhaustion on js/wasm")
|
||||
+ }
|
||||
+ for _, tt := range parseDepthTests {
|
||||
+ for _, size := range []string{"small", "big"} {
|
||||
+ t.Run(tt.name+"/"+size, func(t *testing.T) {
|
||||
+ n := maxNestLev + 1
|
||||
+ if tt.parseMultiplier > 0 {
|
||||
+ n /= tt.parseMultiplier
|
||||
+ }
|
||||
+ if size == "small" {
|
||||
+ // Decrease the number of statements by 10, in order to check
|
||||
+ // that we do not fail when under the limit. 10 is used to
|
||||
+ // provide some wiggle room for cases where the surrounding
|
||||
+ // scaffolding syntax adds some noise to the depth that changes
|
||||
+ // on a per testcase basis.
|
||||
+ n -= 10
|
||||
+ }
|
||||
+
|
||||
+ pre, mid, post := split(tt.format)
|
||||
+ if strings.Contains(mid, "«") {
|
||||
+ left, base, right := split(mid)
|
||||
+ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
|
||||
+ } else {
|
||||
+ mid = strings.Repeat(mid, n)
|
||||
+ }
|
||||
+ input := pre + mid + post
|
||||
+
|
||||
+ fset := token.NewFileSet()
|
||||
+ _, err := ParseFile(fset, "", input, ParseComments|SkipObjectResolution)
|
||||
+ if size == "small" {
|
||||
+ if err != nil {
|
||||
+ t.Errorf("ParseFile(...): %v (want success)", err)
|
||||
+ }
|
||||
+ } else {
|
||||
+ expected := "exceeded max nesting depth"
|
||||
+ if err == nil || !strings.HasSuffix(err.Error(), expected) {
|
||||
+ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
|
||||
+ }
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+const maxScopeDepth int = 1e3
|
||||
+
|
||||
+func TestScopeDepthLimit(t *testing.T) {
|
||||
+ if runtime.GOARCH == "wasm" {
|
||||
+ t.Skip("causes call stack exhaustion on js/wasm")
|
||||
+ }
|
||||
+ for _, tt := range parseDepthTests {
|
||||
+ if !tt.scope {
|
||||
+ continue
|
||||
+ }
|
||||
+ for _, size := range []string{"small", "big"} {
|
||||
+ t.Run(tt.name+"/"+size, func(t *testing.T) {
|
||||
+ n := maxScopeDepth + 1
|
||||
+ if tt.scopeMultiplier > 0 {
|
||||
+ n /= tt.scopeMultiplier
|
||||
+ }
|
||||
+ if size == "small" {
|
||||
+ // Decrease the number of statements by 10, in order to check
|
||||
+ // that we do not fail when under the limit. 10 is used to
|
||||
+ // provide some wiggle room for cases where the surrounding
|
||||
+ // scaffolding syntax adds some noise to the depth that changes
|
||||
+ // on a per testcase basis.
|
||||
+ n -= 10
|
||||
+ }
|
||||
+
|
||||
+ pre, mid, post := split(tt.format)
|
||||
+ if strings.Contains(mid, "«") {
|
||||
+ left, base, right := split(mid)
|
||||
+ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
|
||||
+ } else {
|
||||
+ mid = strings.Repeat(mid, n)
|
||||
+ }
|
||||
+ input := pre + mid + post
|
||||
+
|
||||
+ fset := token.NewFileSet()
|
||||
+ _, err := ParseFile(fset, "", input, DeclarationErrors)
|
||||
+ if size == "small" {
|
||||
+ if err != nil {
|
||||
+ t.Errorf("ParseFile(...): %v (want success)", err)
|
||||
+ }
|
||||
+ } else {
|
||||
+ expected := "exceeded max scope depth during object resolution"
|
||||
+ if err == nil || !strings.HasSuffix(err.Error(), expected) {
|
||||
+ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
|
||||
+ }
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
From f1da2608e141b54e7c1791220c3493a36863c651 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Wed, 1 Jun 2022 11:17:07 -0700
|
||||
Subject: [PATCH 03/10] [release-branch.go1.17] net/http: don't strip
|
||||
whitespace from Transfer-Encoding headers
|
||||
|
||||
Do not accept "Transfer-Encoding: \rchunked" as a valid TE header
|
||||
setting chunked encoding.
|
||||
|
||||
Thanks to Zeyu Zhang (https://www.zeyu2001.com/) for identifying
|
||||
the issue.
|
||||
|
||||
For #53188
|
||||
For CVE-2022-1705
|
||||
Fixes #53432
|
||||
|
||||
Change-Id: I1a16631425159267f2eca68056b057192a7edf6c
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/409874
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
(cherry picked from commit e5017a93fcde94f09836200bca55324af037ee5f)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/415217
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
|
||||
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
|
||||
Conflict: src/net/http/transfer.go
|
||||
Reference: https://go-review.googlesource.com/c/go/+/415217
|
||||
---
|
||||
src/net/http/serve_test.go | 1 +
|
||||
src/net/http/transfer.go | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
|
||||
index 5f569327782..c3f33a5e403 100644
|
||||
--- a/src/net/http/serve_test.go
|
||||
+++ b/src/net/http/serve_test.go
|
||||
@@ -6151,6 +6151,7 @@ func TestUnsupportedTransferEncodingsReturn501(t *testing.T) {
|
||||
"fugazi",
|
||||
"foo-bar",
|
||||
"unknown",
|
||||
+ "\rchunked",
|
||||
}
|
||||
|
||||
for _, badTE := range unsupportedTEs {
|
||||
diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go
|
||||
index 50d434b1fb0..75ca7eda294 100644
|
||||
--- a/src/net/http/transfer.go
|
||||
+++ b/src/net/http/transfer.go
|
||||
@@ -629,7 +629,7 @@ func (t *transferReader) parseTransferEncoding() error {
|
||||
if len(raw) != 1 {
|
||||
return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)}
|
||||
}
|
||||
- if strings.ToLower(textproto.TrimString(raw[0])) != "chunked" {
|
||||
+ if strings.ToLower(raw[0]) != "chunked" {
|
||||
return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])}
|
||||
}
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
||||
168
0067-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch
Normal file
168
0067-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From ae32eafe7dad2b437e38cf65b60abf4971342569 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Tue, 29 Mar 2022 15:52:09 -0700
|
||||
Subject: [PATCH 04/10] [release-branch.go1.17] encoding/xml: limit depth of
|
||||
nesting in unmarshal
|
||||
|
||||
Prevent exhausting the stack limit when unmarshalling extremely deeply
|
||||
nested structures into nested types.
|
||||
|
||||
Fixes #53715
|
||||
Updates #53611
|
||||
Fixes CVE-2022-30633
|
||||
|
||||
Change-Id: Ic6c5d41674c93cfc9a316135a408db9156d39c59
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1421319
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Julie Qiu <julieqiu@google.com>
|
||||
(cherry picked from commit ebee00a55e28931b2cad0e76207a73712b000432)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417069
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417069
|
||||
---
|
||||
src/encoding/xml/read.go | 27 +++++++++++++++++++--------
|
||||
src/encoding/xml/read_test.go | 32 ++++++++++++++++++++++++++++++++
|
||||
2 files changed, 51 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
|
||||
index ef5df3f7f6a..e0ed8b527ce 100644
|
||||
--- a/src/encoding/xml/read.go
|
||||
+++ b/src/encoding/xml/read.go
|
||||
@@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
|
||||
if val.Kind() != reflect.Ptr {
|
||||
return errors.New("non-pointer passed to Unmarshal")
|
||||
}
|
||||
- return d.unmarshal(val.Elem(), start)
|
||||
+ return d.unmarshal(val.Elem(), start, 0)
|
||||
}
|
||||
|
||||
// An UnmarshalError represents an error in the unmarshaling process.
|
||||
@@ -304,8 +304,15 @@ var (
|
||||
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
+const maxUnmarshalDepth = 10000
|
||||
+
|
||||
+var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth")
|
||||
+
|
||||
// Unmarshal a single XML element into val.
|
||||
-func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
|
||||
+func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error {
|
||||
+ if depth >= maxUnmarshalDepth {
|
||||
+ return errExeceededMaxUnmarshalDepth
|
||||
+ }
|
||||
// Find start element if we need it.
|
||||
if start == nil {
|
||||
for {
|
||||
@@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
|
||||
v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
|
||||
|
||||
// Recur to read element into slice.
|
||||
- if err := d.unmarshal(v.Index(n), start); err != nil {
|
||||
+ if err := d.unmarshal(v.Index(n), start, depth+1); err != nil {
|
||||
v.SetLen(n)
|
||||
return err
|
||||
}
|
||||
@@ -521,13 +528,15 @@ Loop:
|
||||
case StartElement:
|
||||
consumed := false
|
||||
if sv.IsValid() {
|
||||
- consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
|
||||
+ // unmarshalPath can call unmarshal, so we need to pass the depth through so that
|
||||
+ // we can continue to enforce the maximum recusion limit.
|
||||
+ consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !consumed && saveAny.IsValid() {
|
||||
consumed = true
|
||||
- if err := d.unmarshal(saveAny, &t); err != nil {
|
||||
+ if err := d.unmarshal(saveAny, &t, depth+1); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
|
||||
// The consumed result tells whether XML elements have been consumed
|
||||
// from the Decoder until start's matching end element, or if it's
|
||||
// still untouched because start is uninteresting for sv's fields.
|
||||
-func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
|
||||
+func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) {
|
||||
recurse := false
|
||||
Loop:
|
||||
for i := range tinfo.fields {
|
||||
@@ -687,7 +696,7 @@ Loop:
|
||||
}
|
||||
if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
|
||||
// It's a perfect match, unmarshal the field.
|
||||
- return true, d.unmarshal(finfo.value(sv, initNilPointers), start)
|
||||
+ return true, d.unmarshal(finfo.value(sv, initNilPointers), start, depth+1)
|
||||
}
|
||||
if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
|
||||
// It's a prefix for the field. Break and recurse
|
||||
@@ -716,7 +725,9 @@ Loop:
|
||||
}
|
||||
switch t := tok.(type) {
|
||||
case StartElement:
|
||||
- consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
|
||||
+ // the recursion depth of unmarshalPath is limited to the path length specified
|
||||
+ // by the struct field tag, so we don't increment the depth here.
|
||||
+ consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
|
||||
index 8c2e70fa22e..8c940aefb81 100644
|
||||
--- a/src/encoding/xml/read_test.go
|
||||
+++ b/src/encoding/xml/read_test.go
|
||||
@@ -5,8 +5,11 @@
|
||||
package xml
|
||||
|
||||
import (
|
||||
+ "bytes"
|
||||
+ "errors"
|
||||
"io"
|
||||
"reflect"
|
||||
+ "runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -1079,3 +1082,32 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
|
||||
t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestCVE202230633(t *testing.T) {
|
||||
+ if runtime.GOARCH == "wasm" {
|
||||
+ t.Skip("causes memory exhaustion on js/wasm")
|
||||
+ }
|
||||
+ defer func() {
|
||||
+ p := recover()
|
||||
+ if p != nil {
|
||||
+ t.Fatal("Unmarshal panicked")
|
||||
+ }
|
||||
+ }()
|
||||
+ var example struct {
|
||||
+ Things []string
|
||||
+ }
|
||||
+ Unmarshal(bytes.Repeat([]byte("<a>"), 17_000_000), &example)
|
||||
+}
|
||||
+
|
||||
+func TestCVE202228131(t *testing.T) {
|
||||
+ type nested struct {
|
||||
+ Parent *nested `xml:",any"`
|
||||
+ }
|
||||
+ var n nested
|
||||
+ err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n)
|
||||
+ if err == nil {
|
||||
+ t.Fatal("Unmarshal did not fail")
|
||||
+ } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) {
|
||||
+ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
138
0068-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch
Normal file
138
0068-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From 30b474a6578f25ce4e065362bea06f61abe8b7df Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Tue, 7 Jun 2022 13:00:43 -0700
|
||||
Subject: [PATCH 05/10] [release-branch.go1.17] encoding/gob: add a depth limit
|
||||
for ignored fields
|
||||
|
||||
Enforce a nesting limit of 10,000 for ignored fields during decoding
|
||||
of messages. This prevents the possibility of triggering stack
|
||||
exhaustion.
|
||||
|
||||
Fixes #53709
|
||||
Updates #53615
|
||||
Fixes CVE-2022-30635
|
||||
|
||||
Change-Id: I05103d06dd5ca3945fcba3c1f5d3b5a645e8fb0f
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1484771
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
(cherry picked from commit 55e8f938d22bfec29cc9dc9671044c5a41d1ea9c)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417074
|
||||
Run-TryBot: Heschi Kreinick <heschi@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417074
|
||||
---
|
||||
src/encoding/gob/decode.go | 19 ++++++++++++-------
|
||||
src/encoding/gob/gobencdec_test.go | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 36 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
|
||||
index d2f6c749b1b..0e0ec75cccc 100644
|
||||
--- a/src/encoding/gob/decode.go
|
||||
+++ b/src/encoding/gob/decode.go
|
||||
@@ -871,8 +871,13 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
||||
return &op
|
||||
}
|
||||
|
||||
+var maxIgnoreNestingDepth = 10000
|
||||
+
|
||||
// decIgnoreOpFor returns the decoding op for a field that has no destination.
|
||||
-func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
|
||||
+func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp {
|
||||
+ if depth > maxIgnoreNestingDepth {
|
||||
+ error_(errors.New("invalid nesting depth"))
|
||||
+ }
|
||||
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
|
||||
// Return the pointer to the op we're already building.
|
||||
if opPtr := inProgress[wireId]; opPtr != nil {
|
||||
@@ -896,7 +901,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
|
||||
errorf("bad data: undefined type %s", wireId.string())
|
||||
case wire.ArrayT != nil:
|
||||
elemId := wire.ArrayT.Elem
|
||||
- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
|
||||
}
|
||||
@@ -904,15 +909,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
|
||||
case wire.MapT != nil:
|
||||
keyId := dec.wireType[wireId].MapT.Key
|
||||
elemId := dec.wireType[wireId].MapT.Elem
|
||||
- keyOp := dec.decIgnoreOpFor(keyId, inProgress)
|
||||
- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
+ keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
|
||||
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreMap(state, *keyOp, *elemOp)
|
||||
}
|
||||
|
||||
case wire.SliceT != nil:
|
||||
elemId := wire.SliceT.Elem
|
||||
- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreSlice(state, *elemOp)
|
||||
}
|
||||
@@ -1073,7 +1078,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
|
||||
func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
|
||||
engine := new(decEngine)
|
||||
engine.instr = make([]decInstr, 1) // one item
|
||||
- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp))
|
||||
+ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0)
|
||||
ovfl := overflow(dec.typeString(remoteId))
|
||||
engine.instr[0] = decInstr{*op, 0, nil, ovfl}
|
||||
engine.numInstr = 1
|
||||
@@ -1118,7 +1123,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
|
||||
localField, present := srt.FieldByName(wireField.Name)
|
||||
// TODO(r): anonymous names
|
||||
if !present || !isExported(wireField.Name) {
|
||||
- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp))
|
||||
+ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0)
|
||||
engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
|
||||
continue
|
||||
}
|
||||
diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
|
||||
index 6d2c8db42d0..1b52ecc6c84 100644
|
||||
--- a/src/encoding/gob/gobencdec_test.go
|
||||
+++ b/src/encoding/gob/gobencdec_test.go
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
+ "reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -796,3 +797,26 @@ func TestNetIP(t *testing.T) {
|
||||
t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestIngoreDepthLimit(t *testing.T) {
|
||||
+ // We don't test the actual depth limit because it requires building an
|
||||
+ // extremely large message, which takes quite a while.
|
||||
+ oldNestingDepth := maxIgnoreNestingDepth
|
||||
+ maxIgnoreNestingDepth = 100
|
||||
+ defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
|
||||
+ b := new(bytes.Buffer)
|
||||
+ enc := NewEncoder(b)
|
||||
+ typ := reflect.TypeOf(int(0))
|
||||
+ nested := reflect.ArrayOf(1, typ)
|
||||
+ for i := 0; i < 100; i++ {
|
||||
+ nested = reflect.ArrayOf(1, nested)
|
||||
+ }
|
||||
+ badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}))
|
||||
+ enc.Encode(badStruct.Interface())
|
||||
+ dec := NewDecoder(b)
|
||||
+ var output struct{ Hello int }
|
||||
+ expectedErr := "invalid nesting depth"
|
||||
+ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
|
||||
+ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
From 472c7e454d5d2a6afbc5494d55e0955c4f2a6990 Mon Sep 17 00:00:00 2001
|
||||
From: Julie Qiu <julieqiu@google.com>
|
||||
Date: Thu, 23 Jun 2022 23:18:56 +0000
|
||||
Subject: [PATCH 06/10] [release-branch.go1.17] path/filepath: fix stack
|
||||
exhaustion in Glob
|
||||
|
||||
A limit is added to the number of path separators allowed by an input to
|
||||
Glob, to prevent stack exhaustion issues.
|
||||
|
||||
Thanks to Juho Nurminen of Mattermost who reported the issue.
|
||||
|
||||
Fixes #53713
|
||||
Updates #53416
|
||||
Fixes CVE-2022-30632
|
||||
|
||||
Change-Id: I1b9fd4faa85411a05dbc91dceae1c0c8eb021f07
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1498176
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
(cherry picked from commit d182a6d1217fd0d04c9babfa9a7ccd3515435c39)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417073
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417073
|
||||
---
|
||||
src/path/filepath/match.go | 16 +++++++++++++++-
|
||||
src/path/filepath/match_test.go | 10 ++++++++++
|
||||
2 files changed, 25 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go
|
||||
index 20a334805ba..b6a3b450fe8 100644
|
||||
--- a/src/path/filepath/match.go
|
||||
+++ b/src/path/filepath/match.go
|
||||
@@ -232,6 +232,20 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
|
||||
// The only possible returned error is ErrBadPattern, when pattern
|
||||
// is malformed.
|
||||
func Glob(pattern string) (matches []string, err error) {
|
||||
+ return globWithLimit(pattern, 0)
|
||||
+}
|
||||
+
|
||||
+func globWithLimit(pattern string, depth int) (matches []string, err error) {
|
||||
+ // This limit is used prevent stack exhaustion issues. See CVE-2022-30632.
|
||||
+ const pathSeparatorsLimit = 10000
|
||||
+ if depth == pathSeparatorsLimit {
|
||||
+ return nil, ErrBadPattern
|
||||
+ }
|
||||
+
|
||||
+ // Check pattern is well-formed.
|
||||
+ if _, err := Match(pattern, ""); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
if !hasMeta(pattern) {
|
||||
if _, err = os.Lstat(pattern); err != nil {
|
||||
return nil, nil
|
||||
@@ -257,7 +271,7 @@ func Glob(pattern string) (matches []string, err error) {
|
||||
}
|
||||
|
||||
var m []string
|
||||
- m, err = Glob(dir)
|
||||
+ m, err = globWithLimit(dir, depth+1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
|
||||
index b8657626bc7..c37c812181f 100644
|
||||
--- a/src/path/filepath/match_test.go
|
||||
+++ b/src/path/filepath/match_test.go
|
||||
@@ -154,6 +154,16 @@ func TestGlob(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+func TestCVE202230632(t *testing.T) {
|
||||
+ // Prior to CVE-2022-30632, this would cause a stack exhaustion given a
|
||||
+ // large number of separators (more than 4,000,000). There is now a limit
|
||||
+ // of 10,000.
|
||||
+ _, err := Glob("/*" + strings.Repeat("/", 10001))
|
||||
+ if err != ErrBadPattern {
|
||||
+ t.Fatalf("Glob returned err=%v, want ErrBadPattern", err)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func TestGlobError(t *testing.T) {
|
||||
_, err := Glob("[]")
|
||||
if err == nil {
|
||||
--
|
||||
2.30.2
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
From a63efc45c908bfd46c60e95956cce499a2c92e44 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 28 Mar 2022 18:41:26 -0700
|
||||
Subject: [PATCH 07/10] [release-branch.go1.17] encoding/xml: use iterative
|
||||
Skip, rather than recursive
|
||||
|
||||
Prevents exhausting the stack limit in _incredibly_ deeply nested
|
||||
structures.
|
||||
|
||||
Fixes #53711
|
||||
Updates #53614
|
||||
Fixes CVE-2022-28131
|
||||
|
||||
Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912
|
||||
Reviewed-by: Julie Qiu <julieqiu@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417068
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417068
|
||||
---
|
||||
src/encoding/xml/read.go | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
|
||||
index e0ed8b527ce..c77579880cb 100644
|
||||
--- a/src/encoding/xml/read.go
|
||||
+++ b/src/encoding/xml/read.go
|
||||
@@ -743,12 +743,12 @@ Loop:
|
||||
}
|
||||
|
||||
// Skip reads tokens until it has consumed the end element
|
||||
-// matching the most recent start element already consumed.
|
||||
-// It recurs if it encounters a start element, so it can be used to
|
||||
-// skip nested structures.
|
||||
+// matching the most recent start element already consumed,
|
||||
+// skipping nested structures.
|
||||
// It returns nil if it finds an end element matching the start
|
||||
// element; otherwise it returns an error describing the problem.
|
||||
func (d *Decoder) Skip() error {
|
||||
+ var depth int64
|
||||
for {
|
||||
tok, err := d.Token()
|
||||
if err != nil {
|
||||
@@ -756,11 +756,12 @@ func (d *Decoder) Skip() error {
|
||||
}
|
||||
switch tok.(type) {
|
||||
case StartElement:
|
||||
- if err := d.Skip(); err != nil {
|
||||
- return err
|
||||
- }
|
||||
+ depth++
|
||||
case EndElement:
|
||||
- return nil
|
||||
+ if depth == 0 {
|
||||
+ return nil
|
||||
+ }
|
||||
+ depth--
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
133
0071-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch
Normal file
133
0071-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch
Normal file
@ -0,0 +1,133 @@
|
||||
From 10531e040d8ed73f51032a7d75c708ca07b638ff Mon Sep 17 00:00:00 2001
|
||||
From: Tatiana Bradley <tatiana@golang.org>
|
||||
Date: Fri, 6 May 2022 11:25:06 -0400
|
||||
Subject: [PATCH 08/10] [release-branch.go1.17] compress/gzip: fix stack
|
||||
exhaustion bug in Reader.Read
|
||||
|
||||
Replace recursion with iteration in Reader.Read to avoid stack
|
||||
exhaustion when there are a large number of files.
|
||||
|
||||
Fixes CVE-2022-30631
|
||||
Fixes #53717
|
||||
Updates #53168
|
||||
|
||||
Change-Id: I47d8afe3f2d40b0213ab61431df9b221794dbfe0
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1455673
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Julie Qiu <julieqiu@google.com>
|
||||
(cherry picked from commit cf498969c8a0bae9d7a24b98fc1f66c824a4775d)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/417071
|
||||
Reviewed-by: Heschi Kreinick <heschi@google.com>
|
||||
Run-TryBot: Michael Knyszek <mknyszek@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/417071
|
||||
---
|
||||
src/compress/gzip/gunzip.go | 60 +++++++++++++++-----------------
|
||||
src/compress/gzip/gunzip_test.go | 16 +++++++++
|
||||
2 files changed, 45 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
|
||||
index 924bce10b7c..237b2b928bf 100644
|
||||
--- a/src/compress/gzip/gunzip.go
|
||||
+++ b/src/compress/gzip/gunzip.go
|
||||
@@ -248,42 +248,40 @@ func (z *Reader) Read(p []byte) (n int, err error) {
|
||||
return 0, z.err
|
||||
}
|
||||
|
||||
- n, z.err = z.decompressor.Read(p)
|
||||
- z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
|
||||
- z.size += uint32(n)
|
||||
- if z.err != io.EOF {
|
||||
- // In the normal case we return here.
|
||||
- return n, z.err
|
||||
- }
|
||||
+ for n == 0 {
|
||||
+ n, z.err = z.decompressor.Read(p)
|
||||
+ z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
|
||||
+ z.size += uint32(n)
|
||||
+ if z.err != io.EOF {
|
||||
+ // In the normal case we return here.
|
||||
+ return n, z.err
|
||||
+ }
|
||||
|
||||
- // Finished file; check checksum and size.
|
||||
- if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
|
||||
- z.err = noEOF(err)
|
||||
- return n, z.err
|
||||
- }
|
||||
- digest := le.Uint32(z.buf[:4])
|
||||
- size := le.Uint32(z.buf[4:8])
|
||||
- if digest != z.digest || size != z.size {
|
||||
- z.err = ErrChecksum
|
||||
- return n, z.err
|
||||
- }
|
||||
- z.digest, z.size = 0, 0
|
||||
+ // Finished file; check checksum and size.
|
||||
+ if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
|
||||
+ z.err = noEOF(err)
|
||||
+ return n, z.err
|
||||
+ }
|
||||
+ digest := le.Uint32(z.buf[:4])
|
||||
+ size := le.Uint32(z.buf[4:8])
|
||||
+ if digest != z.digest || size != z.size {
|
||||
+ z.err = ErrChecksum
|
||||
+ return n, z.err
|
||||
+ }
|
||||
+ z.digest, z.size = 0, 0
|
||||
|
||||
- // File is ok; check if there is another.
|
||||
- if !z.multistream {
|
||||
- return n, io.EOF
|
||||
- }
|
||||
- z.err = nil // Remove io.EOF
|
||||
+ // File is ok; check if there is another.
|
||||
+ if !z.multistream {
|
||||
+ return n, io.EOF
|
||||
+ }
|
||||
+ z.err = nil // Remove io.EOF
|
||||
|
||||
- if _, z.err = z.readHeader(); z.err != nil {
|
||||
- return n, z.err
|
||||
+ if _, z.err = z.readHeader(); z.err != nil {
|
||||
+ return n, z.err
|
||||
+ }
|
||||
}
|
||||
|
||||
- // Read from next file, if necessary.
|
||||
- if n > 0 {
|
||||
- return n, nil
|
||||
- }
|
||||
- return z.Read(p)
|
||||
+ return n, nil
|
||||
}
|
||||
|
||||
// Close closes the Reader. It does not close the underlying io.Reader.
|
||||
diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
|
||||
index 1b014041692..95220ae82d9 100644
|
||||
--- a/src/compress/gzip/gunzip_test.go
|
||||
+++ b/src/compress/gzip/gunzip_test.go
|
||||
@@ -516,3 +516,19 @@ func TestTruncatedStreams(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestCVE202230631(t *testing.T) {
|
||||
+ var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00,
|
||||
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
+ r := bytes.NewReader(bytes.Repeat(empty, 4e6))
|
||||
+ z, err := NewReader(r)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("NewReader: got %v, want nil", err)
|
||||
+ }
|
||||
+ // Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due
|
||||
+ // to stack exhaustion.
|
||||
+ _, err = z.Read(make([]byte, 10))
|
||||
+ if err != io.EOF {
|
||||
+ t.Errorf("Reader.Read: got %v, want %v", err, io.EOF)
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
From 251fa2dcc814ef51816245336fd1884239dd002a Mon Sep 17 00:00:00 2001
|
||||
From: Tatiana Bradley <tatiana@golang.org>
|
||||
Date: Thu, 12 May 2022 14:58:29 -0400
|
||||
Subject: [PATCH 09/10] [release-branch.go1.17] crypto/tls: randomly generate
|
||||
ticket_age_add
|
||||
|
||||
As required by RFC 8446, section 4.6.1, ticket_age_add now holds a
|
||||
random 32-bit value. Before this change, this value was always set
|
||||
to 0.
|
||||
|
||||
This change also documents the reasoning for always setting
|
||||
ticket_nonce to 0. The value ticket_nonce must be unique per
|
||||
connection, but we only ever send one ticket per connection.
|
||||
|
||||
Updates #52814
|
||||
Fixes #52832
|
||||
Fixes CVE-2022-30629
|
||||
|
||||
Change-Id: I6c2fc6ca0376b7b968abd59d6d3d3854c1ab68bb
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/405994
|
||||
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
Run-TryBot: Tatiana Bradley <tatiana@golang.org>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
(cherry picked from commit fe4de36198794c447fbd9d7cc2d7199a506c76a5)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/408574
|
||||
Run-TryBot: Roland Shoemaker <roland@golang.org>
|
||||
|
||||
Conflict: NA
|
||||
Reference: https://go-review.googlesource.com/c/go/+/408574
|
||||
---
|
||||
src/crypto/tls/handshake_server_tls13.go | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
|
||||
index 92d55e0293a..fcea739b9a9 100644
|
||||
--- a/src/crypto/tls/handshake_server_tls13.go
|
||||
+++ b/src/crypto/tls/handshake_server_tls13.go
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"crypto"
|
||||
"crypto/hmac"
|
||||
"crypto/rsa"
|
||||
+ "encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
@@ -742,6 +743,19 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
|
||||
}
|
||||
m.lifetime = uint32(maxSessionTicketLifetime / time.Second)
|
||||
|
||||
+ // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1
|
||||
+ // The value is not stored anywhere; we never need to check the ticket age
|
||||
+ // because 0-RTT is not supported.
|
||||
+ ageAdd := make([]byte, 4)
|
||||
+ _, err = hs.c.config.rand().Read(ageAdd)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ m.ageAdd = binary.LittleEndian.Uint32(ageAdd)
|
||||
+
|
||||
+ // ticket_nonce, which must be unique per connection, is always left at
|
||||
+ // zero because we only ever send one ticket per connection.
|
||||
+
|
||||
if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
|
||||
return err
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
239
0073-release-branch.go1.17-crypto-rand-properly-handle-la.patch
Normal file
239
0073-release-branch.go1.17-crypto-rand-properly-handle-la.patch
Normal file
@ -0,0 +1,239 @@
|
||||
From 4dfd37e5c41d531b9e5eb9618a0683d67ef3e594 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 25 Apr 2022 19:02:35 -0700
|
||||
Subject: [PATCH 10/10] [release-branch.go1.17] crypto/rand: properly handle
|
||||
large Read on windows
|
||||
|
||||
Use the batched reader to chunk large Read calls on windows to a max of
|
||||
1 << 31 - 1 bytes. This prevents an infinite loop when trying to read
|
||||
more than 1 << 32 -1 bytes, due to how RtlGenRandom works.
|
||||
|
||||
This change moves the batched function from rand_unix.go to rand.go,
|
||||
since it is now needed for both windows and unix implementations.
|
||||
|
||||
Updates #52561
|
||||
Fixes #52932
|
||||
Fixes CVE-2022-30634
|
||||
|
||||
Change-Id: Id98fc4b1427e5cb2132762a445b2aed646a37473
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/402257
|
||||
Run-TryBot: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Filippo Valsorda <filippo@golang.org>
|
||||
Reviewed-by: Filippo Valsorda <valsorda@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
(cherry picked from commit bb1f4416180511231de6d17a1f2f55c82aafc863)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/406635
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
|
||||
Conflict: src/crypto/rand/rand.go, src/crypto/rand/rand_windows.go
|
||||
Reference: https://go-review.googlesource.com/c/go/+/406635
|
||||
---
|
||||
src/crypto/rand/rand.go | 18 +++++++++++++++
|
||||
src/crypto/rand/rand_batched.go | 22 +++++--------------
|
||||
src/crypto/rand/rand_batched_test.go | 21 +++++++++---------
|
||||
src/crypto/rand/rand_unix.go | 4 ++--
|
||||
src/crypto/rand/rand_windows.go | 33 +++++-----------------------
|
||||
5 files changed, 43 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
|
||||
index a5ccd19de32..5606f248f02 100644
|
||||
--- a/src/crypto/rand/rand.go
|
||||
+++ b/src/crypto/rand/rand.go
|
||||
@@ -27,3 +27,21 @@ func Read(b []byte) (n int, err error) {
|
||||
func warnBlocked() {
|
||||
println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
|
||||
}
|
||||
+
|
||||
+// batched returns a function that calls f to populate a []byte by chunking it
|
||||
+// into subslices of, at most, readMax bytes.
|
||||
+func batched(f func([]byte) error, readMax int) func([]byte) error {
|
||||
+ return func(out []byte) error {
|
||||
+ for len(out) > 0 {
|
||||
+ read := len(out)
|
||||
+ if read > readMax {
|
||||
+ read = readMax
|
||||
+ }
|
||||
+ if err := f(out[:read]); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ out = out[read:]
|
||||
+ }
|
||||
+ return nil
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/crypto/rand/rand_batched.go b/src/crypto/rand/rand_batched.go
|
||||
index 60267fd4bc2..cad958d79c0 100644
|
||||
--- a/src/crypto/rand/rand_batched.go
|
||||
+++ b/src/crypto/rand/rand_batched.go
|
||||
@@ -7,6 +7,7 @@
|
||||
package rand
|
||||
|
||||
import (
|
||||
+ "errors"
|
||||
"internal/syscall/unix"
|
||||
)
|
||||
|
||||
@@ -15,20 +16,6 @@ func init() {
|
||||
altGetRandom = batched(getRandomBatch, maxGetRandomRead)
|
||||
}
|
||||
|
||||
-// batched returns a function that calls f to populate a []byte by chunking it
|
||||
-// into subslices of, at most, readMax bytes.
|
||||
-func batched(f func([]byte) bool, readMax int) func([]byte) bool {
|
||||
- return func(buf []byte) bool {
|
||||
- for len(buf) > readMax {
|
||||
- if !f(buf[:readMax]) {
|
||||
- return false
|
||||
- }
|
||||
- buf = buf[readMax:]
|
||||
- }
|
||||
- return len(buf) == 0 || f(buf)
|
||||
- }
|
||||
-}
|
||||
-
|
||||
// If the kernel is too old to support the getrandom syscall(),
|
||||
// unix.GetRandom will immediately return ENOSYS and we will then fall back to
|
||||
// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS
|
||||
@@ -36,7 +23,10 @@ func batched(f func([]byte) bool, readMax int) func([]byte) bool {
|
||||
// If the kernel supports the getrandom() syscall, unix.GetRandom will block
|
||||
// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK).
|
||||
// In this case, unix.GetRandom will not return an error.
|
||||
-func getRandomBatch(p []byte) (ok bool) {
|
||||
+func getRandomBatch(p []byte) error {
|
||||
n, err := unix.GetRandom(p, 0)
|
||||
- return n == len(p) && err == nil
|
||||
+ if n != len(p) {
|
||||
+ return errors.New("short read")
|
||||
+ }
|
||||
+ return err
|
||||
}
|
||||
diff --git a/src/crypto/rand/rand_batched_test.go b/src/crypto/rand/rand_batched_test.go
|
||||
index 837db83f770..8122bceba4b 100644
|
||||
--- a/src/crypto/rand/rand_batched_test.go
|
||||
+++ b/src/crypto/rand/rand_batched_test.go
|
||||
@@ -8,20 +8,21 @@ package rand
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
+ "errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBatched(t *testing.T) {
|
||||
- fillBatched := batched(func(p []byte) bool {
|
||||
+ fillBatched := batched(func(p []byte) error {
|
||||
for i := range p {
|
||||
p[i] = byte(i)
|
||||
}
|
||||
- return true
|
||||
+ return nil
|
||||
}, 5)
|
||||
|
||||
p := make([]byte, 13)
|
||||
- if !fillBatched(p) {
|
||||
- t.Fatal("batched function returned false")
|
||||
+ if err := fillBatched(p); err != nil {
|
||||
+ t.Fatalf("batched function returned error: %s", err)
|
||||
}
|
||||
expected := []byte{0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2}
|
||||
if !bytes.Equal(expected, p) {
|
||||
@@ -30,15 +31,15 @@ func TestBatched(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBatchedError(t *testing.T) {
|
||||
- b := batched(func(p []byte) bool { return false }, 5)
|
||||
- if b(make([]byte, 13)) {
|
||||
- t.Fatal("batched function should have returned false")
|
||||
+ b := batched(func(p []byte) error { return errors.New("") }, 5)
|
||||
+ if b(make([]byte, 13)) == nil {
|
||||
+ t.Fatal("batched function should have returned an error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBatchedEmpty(t *testing.T) {
|
||||
- b := batched(func(p []byte) bool { return false }, 5)
|
||||
- if !b(make([]byte, 0)) {
|
||||
- t.Fatal("empty slice should always return true")
|
||||
+ b := batched(func(p []byte) error { return errors.New("") }, 5)
|
||||
+ if err := b(make([]byte, 0)); err != nil {
|
||||
+ t.Fatalf("empty slice should always return nil: %s", err)
|
||||
}
|
||||
}
|
||||
diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
|
||||
index 0610f691b0d..5ddc76be266 100644
|
||||
--- a/src/crypto/rand/rand_unix.go
|
||||
+++ b/src/crypto/rand/rand_unix.go
|
||||
@@ -45,7 +45,7 @@ type devReader struct {
|
||||
|
||||
// altGetRandom if non-nil specifies an OS-specific function to get
|
||||
// urandom-style randomness.
|
||||
-var altGetRandom func([]byte) (ok bool)
|
||||
+var altGetRandom func([]byte) (err error)
|
||||
|
||||
func (r *devReader) Read(b []byte) (n int, err error) {
|
||||
if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
|
||||
@@ -54,7 +54,7 @@ func (r *devReader) Read(b []byte) (n int, err error) {
|
||||
t := time.AfterFunc(60*time.Second, warnBlocked)
|
||||
defer t.Stop()
|
||||
}
|
||||
- if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
|
||||
+ if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) == nil {
|
||||
return len(b), nil
|
||||
}
|
||||
r.mu.Lock()
|
||||
diff --git a/src/crypto/rand/rand_windows.go b/src/crypto/rand/rand_windows.go
|
||||
index 78a4ed6d67b..b5036ba9713 100644
|
||||
--- a/src/crypto/rand/rand_windows.go
|
||||
+++ b/src/crypto/rand/rand_windows.go
|
||||
@@ -8,11 +8,9 @@
|
||||
package rand
|
||||
|
||||
import (
|
||||
- "os"
|
||||
+ "internal/syscall/windows"
|
||||
"sync"
|
||||
- "sync/atomic"
|
||||
"syscall"
|
||||
- "time"
|
||||
)
|
||||
|
||||
// Implemented by using Windows CryptoAPI 2.0.
|
||||
@@ -27,30 +25,11 @@ type rngReader struct {
|
||||
}
|
||||
|
||||
func (r *rngReader) Read(b []byte) (n int, err error) {
|
||||
- if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
|
||||
- // First use of randomness. Start timer to warn about
|
||||
- // being blocked on entropy not being available.
|
||||
- t := time.AfterFunc(60*time.Second, warnBlocked)
|
||||
- defer t.Stop()
|
||||
- }
|
||||
- r.mu.Lock()
|
||||
- if r.prov == 0 {
|
||||
- const provType = syscall.PROV_RSA_FULL
|
||||
- const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
|
||||
- err := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
|
||||
- if err != nil {
|
||||
- r.mu.Unlock()
|
||||
- return 0, os.NewSyscallError("CryptAcquireContext", err)
|
||||
- }
|
||||
- }
|
||||
- r.mu.Unlock()
|
||||
-
|
||||
- if len(b) == 0 {
|
||||
- return 0, nil
|
||||
- }
|
||||
- err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
|
||||
- if err != nil {
|
||||
- return 0, os.NewSyscallError("CryptGenRandom", err)
|
||||
+ // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at
|
||||
+ // most 1<<31-1 bytes at a time so that this works the same on 32-bit
|
||||
+ // and 64-bit systems.
|
||||
+ if err := batched(windows.RtlGenRandom, 1<<31-1)(b); err != nil {
|
||||
+ return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
||||
19
golang.spec
19
golang.spec
@ -62,7 +62,7 @@
|
||||
|
||||
Name: golang
|
||||
Version: 1.15.7
|
||||
Release: 13
|
||||
Release: 14
|
||||
Summary: The Go Programming Language
|
||||
License: BSD and Public Domain
|
||||
URL: https://golang.org/
|
||||
@ -209,12 +209,21 @@ Patch6060: 0060-cmd-go-internal-modfetch-do-not-short-circuit-canoni.patch
|
||||
Patch6061: 0061-release-branch.go1.17-crypto-elliptic-tolerate-zero-.patch
|
||||
Patch6062: 0062-release-branch.go1.17-encoding-pem-fix-stack-overflo.patch
|
||||
Patch6063: 0063-release-branch.go1.16-syscall-fix-ForkLock-spurious-.patch
|
||||
Patch6064: 0064-release-branch.go1.17-net-http-preserve-nil-values-i.patch
|
||||
Patch6065: 0065-release-branch.go1.17-go-parser-limit-recursion-dept.patch
|
||||
Patch6066: 0066-release-branch.go1.17-net-http-don-t-strip-whitespac.patch
|
||||
Patch6067: 0067-release-branch.go1.17-encoding-xml-limit-depth-of-ne.patch
|
||||
Patch6068: 0068-release-branch.go1.17-encoding-gob-add-a-depth-limit.patch
|
||||
Patch6069: 0069-release-branch.go1.17-path-filepath-fix-stack-exhaus.patch
|
||||
Patch6070: 0070-release-branch.go1.17-encoding-xml-use-iterative-Ski.patch
|
||||
Patch6071: 0071-release-branch.go1.17-compress-gzip-fix-stack-exhaus.patch
|
||||
Patch6072: 0072-release-branch.go1.17-crypto-tls-randomly-generate-t.patch
|
||||
Patch6073: 0073-release-branch.go1.17-crypto-rand-properly-handle-la.patch
|
||||
|
||||
|
||||
Patch9001: 0001-drop-hard-code-cert.patch
|
||||
Patch9002: 0002-fix-patch-cmd-go-internal-modfetch-do-not-sho.patch
|
||||
|
||||
|
||||
%description
|
||||
%{summary}.
|
||||
|
||||
@ -444,6 +453,12 @@ fi
|
||||
%files devel -f go-tests.list -f go-misc.list -f go-src.list
|
||||
|
||||
%changelog
|
||||
|
||||
* Thu Jul 26 2022 hanchao<hanchao47@huawei.com> - 1.15.7-14
|
||||
- fix CVE-2022-32148,CVE-2022-1962,CVE-2022-1705,CVE-2022-30633,
|
||||
CVE-2022-30635,CVE-2022-30632,CVE-2022-28131,
|
||||
CVE-2022-30631,CVE-2022-30629,CVE-2022-30634
|
||||
|
||||
* Thu May 12 2022 hanchao<hanchao47@huawei.com> - 1.15.7-13
|
||||
- fix CVE-2021-44717
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user