Skip to content

Commit 816deac

Browse files
audreylimdsnet
authored andcommitted
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/50250 Reviewed-by: Joe Tsai <[email protected]> Run-TryBot: Joe Tsai <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 09ed0f6 commit 816deac

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/archive/zip/writer.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ import (
1414
"unicode/utf8"
1515
)
1616

17+
var (
18+
errLongName = errors.New("zip: FileHeader.Name too long")
19+
errLongExtra = errors.New("zip: FileHeader.Extra too long")
20+
)
21+
1722
// Writer implements a zip file writer.
1823
type Writer struct {
1924
cw *countWriter
@@ -273,6 +278,14 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
273278
}
274279

275280
func writeHeader(w io.Writer, h *FileHeader) error {
281+
const maxUint16 = 1<<16 - 1
282+
if len(h.Name) > maxUint16 {
283+
return errLongName
284+
}
285+
if len(h.Extra) > maxUint16 {
286+
return errLongExtra
287+
}
288+
276289
var buf [fileHeaderLen]byte
277290
b := writeBuf(buf[:])
278291
b.uint32(uint32(fileHeaderSignature))

src/archive/zip/zip_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,44 @@ func TestHeaderTooShort(t *testing.T) {
650650
testValidHeader(&h, t)
651651
}
652652

653+
func TestHeaderTooLongErr(t *testing.T) {
654+
var headerTests = []struct {
655+
name string
656+
extra []byte
657+
wanterr error
658+
}{
659+
{
660+
name: strings.Repeat("x", 1<<16),
661+
extra: []byte{},
662+
wanterr: errLongName,
663+
},
664+
{
665+
name: "long_extra",
666+
extra: bytes.Repeat([]byte{0xff}, 1<<16),
667+
wanterr: errLongExtra,
668+
},
669+
}
670+
671+
// write a zip file
672+
buf := new(bytes.Buffer)
673+
w := NewWriter(buf)
674+
675+
for _, test := range headerTests {
676+
h := &FileHeader{
677+
Name: test.name,
678+
Extra: test.extra,
679+
}
680+
_, err := w.CreateHeader(h)
681+
if err != test.wanterr {
682+
t.Errorf("error=%v, want %v", err, test.wanterr)
683+
}
684+
}
685+
686+
if err := w.Close(); err != nil {
687+
t.Fatal(err)
688+
}
689+
}
690+
653691
func TestHeaderIgnoredSize(t *testing.T) {
654692
h := FileHeader{
655693
Name: "foo.txt",

0 commit comments

Comments
 (0)