[release-branch.go1.16] all: merge release-branch.go1.16-security into release-branch.go1.16

Change-Id: Icc8775f559b0125eae94ce4ffd4dcb4e7146a500
This commit is contained in:
Katie Hockman 2021-03-10 11:55:06 -05:00
commit b5c1b5aa07
5 changed files with 129 additions and 33 deletions

View File

@ -1 +1 @@
go1.16
go1.16.1

View File

@ -664,7 +664,7 @@ func toValidName(name string) string {
if strings.HasPrefix(p, "/") {
p = p[len("/"):]
}
for strings.HasPrefix(name, "../") {
for strings.HasPrefix(p, "../") {
p = p[len("../"):]
}
return p

View File

@ -1081,3 +1081,38 @@ func TestFS(t *testing.T) {
t.Fatal(err)
}
}
func TestCVE202127919(t *testing.T) {
// Archive containing only the file "../test.txt"
data := []byte{
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
}
r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
if err != nil {
t.Fatalf("Error reading the archive: %v", err)
}
_, err = r.Open("test.txt")
if err != nil {
t.Errorf("Error reading file: %v", err)
}
}

View File

@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder {
// it will return an error.
//
// Token implements XML name spaces as described by
// https://www.w3.org/TR/REC-xml-names/. Each of the
// https://www.w3.org/TR/REC-xml-names/. Each of the
// Name structures contained in the Token has the Space
// set to the URL identifying its name space when known.
// If Token encounters an unrecognized name space prefix,
@ -285,16 +285,17 @@ func (d *Decoder) Token() (Token, error) {
if d.nextToken != nil {
t = d.nextToken
d.nextToken = nil
} else if t, err = d.rawToken(); err != nil {
switch {
case err == io.EOF && d.t != nil:
err = nil
case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF:
err = d.syntaxError("unexpected EOF")
} else {
if t, err = d.rawToken(); t == nil && err != nil {
if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
err = d.syntaxError("unexpected EOF")
}
return nil, err
}
return t, err
// We still have a token to process, so clear any
// errors (e.g. EOF) and proceed.
err = nil
}
if !d.Strict {
if t1, ok := d.autoClose(t); ok {
d.nextToken = t

View File

@ -33,30 +33,90 @@ func (t *toks) Token() (Token, error) {
func TestDecodeEOF(t *testing.T) {
start := StartElement{Name: Name{Local: "test"}}
t.Run("EarlyEOF", func(t *testing.T) {
d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{
start,
start.End(),
}})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if err != nil {
t.Error(err)
tests := []struct {
name string
tokens []Token
ok bool
}{
{
name: "OK",
tokens: []Token{
start,
start.End(),
},
ok: true,
},
{
name: "Malformed",
tokens: []Token{
start,
StartElement{Name: Name{Local: "bad"}},
start.End(),
},
ok: false,
},
}
for _, tc := range tests {
for _, eof := range []bool{true, false} {
name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof)
t.Run(name, func(t *testing.T) {
d := NewTokenDecoder(&toks{
earlyEOF: eof,
t: tc.tokens,
})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if tc.ok && err != nil {
t.Fatalf("d.Decode: expected nil error, got %v", err)
}
if _, ok := err.(*SyntaxError); !tc.ok && !ok {
t.Errorf("d.Decode: expected syntax error, got %v", err)
}
})
}
})
t.Run("LateEOF", func(t *testing.T) {
d := NewTokenDecoder(&toks{t: []Token{
start,
start.End(),
}})
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if err != nil {
t.Error(err)
}
}
type toksNil struct {
returnEOF bool
t []Token
}
func (t *toksNil) Token() (Token, error) {
if len(t.t) == 0 {
if !t.returnEOF {
// Return nil, nil before returning an EOF. It's legal, but
// discouraged.
t.returnEOF = true
return nil, nil
}
})
return nil, io.EOF
}
var tok Token
tok, t.t = t.t[0], t.t[1:]
return tok, nil
}
func TestDecodeNilToken(t *testing.T) {
for _, strict := range []bool{true, false} {
name := fmt.Sprintf("Strict=%v", strict)
t.Run(name, func(t *testing.T) {
start := StartElement{Name: Name{Local: "test"}}
bad := StartElement{Name: Name{Local: "bad"}}
d := NewTokenDecoder(&toksNil{
// Malformed
t: []Token{start, bad, start.End()},
})
d.Strict = strict
err := d.Decode(&struct {
XMLName Name `xml:"test"`
}{})
if _, ok := err.(*SyntaxError); !ok {
t.Errorf("d.Decode: expected syntax error, got %v", err)
}
})
}
}
const testInput = `