1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package zip
6
7import (
8	"bytes"
9	"io"
10	"os"
11	"path/filepath"
12	"testing"
13)
14
15func FuzzReader(f *testing.F) {
16	testdata, err := os.ReadDir("testdata")
17	if err != nil {
18		f.Fatalf("failed to read testdata directory: %s", err)
19	}
20	for _, de := range testdata {
21		if de.IsDir() {
22			continue
23		}
24		b, err := os.ReadFile(filepath.Join("testdata", de.Name()))
25		if err != nil {
26			f.Fatalf("failed to read testdata: %s", err)
27		}
28		f.Add(b)
29	}
30
31	f.Fuzz(func(t *testing.T, b []byte) {
32		r, err := NewReader(bytes.NewReader(b), int64(len(b)))
33		if err != nil {
34			return
35		}
36
37		type file struct {
38			header  *FileHeader
39			content []byte
40		}
41		files := []file{}
42
43		for _, f := range r.File {
44			fr, err := f.Open()
45			if err != nil {
46				continue
47			}
48			content, err := io.ReadAll(fr)
49			if err != nil {
50				continue
51			}
52			files = append(files, file{header: &f.FileHeader, content: content})
53			if _, err := r.Open(f.Name); err != nil {
54				continue
55			}
56		}
57
58		// If we were unable to read anything out of the archive don't
59		// bother trying to roundtrip it.
60		if len(files) == 0 {
61			return
62		}
63
64		w := NewWriter(io.Discard)
65		for _, f := range files {
66			ww, err := w.CreateHeader(f.header)
67			if err != nil {
68				t.Fatalf("unable to write previously parsed header: %s", err)
69			}
70			if _, err := ww.Write(f.content); err != nil {
71				t.Fatalf("unable to write previously parsed content: %s", err)
72			}
73		}
74
75		if err := w.Close(); err != nil {
76			t.Fatalf("Unable to write archive: %s", err)
77		}
78
79		// TODO: We may want to check if the archive roundtrips.
80	})
81}
82