Commit 816deacc authored by Audrey Lim's avatar Audrey Lim Committed by Joe Tsai

archive/zip: fix Writer to validate file

The ZIP format uses uint16 to contain the length of the file name and
the length of the Extra section. This change verifies that the length
of these fields fit in an uint16 prior to writing the ZIP file. If not,
an error is returned.

Fixes #17402

Change-Id: Ief9a864d2fe16b89ddb9917838283b801a2c58a4
Reviewed-on: https://go-review.googlesource.com/50250Reviewed-by: 's avatarJoe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 09ed0f68
...@@ -14,6 +14,11 @@ import ( ...@@ -14,6 +14,11 @@ import (
"unicode/utf8" "unicode/utf8"
) )
var (
errLongName = errors.New("zip: FileHeader.Name too long")
errLongExtra = errors.New("zip: FileHeader.Extra too long")
)
// Writer implements a zip file writer. // Writer implements a zip file writer.
type Writer struct { type Writer struct {
cw *countWriter cw *countWriter
...@@ -273,6 +278,14 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { ...@@ -273,6 +278,14 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
} }
func writeHeader(w io.Writer, h *FileHeader) error { func writeHeader(w io.Writer, h *FileHeader) error {
const maxUint16 = 1<<16 - 1
if len(h.Name) > maxUint16 {
return errLongName
}
if len(h.Extra) > maxUint16 {
return errLongExtra
}
var buf [fileHeaderLen]byte var buf [fileHeaderLen]byte
b := writeBuf(buf[:]) b := writeBuf(buf[:])
b.uint32(uint32(fileHeaderSignature)) b.uint32(uint32(fileHeaderSignature))
......
...@@ -650,6 +650,44 @@ func TestHeaderTooShort(t *testing.T) { ...@@ -650,6 +650,44 @@ func TestHeaderTooShort(t *testing.T) {
testValidHeader(&h, t) testValidHeader(&h, t)
} }
func TestHeaderTooLongErr(t *testing.T) {
var headerTests = []struct {
name string
extra []byte
wanterr error
}{
{
name: strings.Repeat("x", 1<<16),
extra: []byte{},
wanterr: errLongName,
},
{
name: "long_extra",
extra: bytes.Repeat([]byte{0xff}, 1<<16),
wanterr: errLongExtra,
},
}
// write a zip file
buf := new(bytes.Buffer)
w := NewWriter(buf)
for _, test := range headerTests {
h := &FileHeader{
Name: test.name,
Extra: test.extra,
}
_, err := w.CreateHeader(h)
if err != test.wanterr {
t.Errorf("error=%v, want %v", err, test.wanterr)
}
}
if err := w.Close(); err != nil {
t.Fatal(err)
}
}
func TestHeaderIgnoredSize(t *testing.T) { func TestHeaderIgnoredSize(t *testing.T) {
h := FileHeader{ h := FileHeader{
Name: "foo.txt", Name: "foo.txt",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment