github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/archive/tar/fuzz_test.go (about)

     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  
     5  //go:build !android
     6  // +build !android
     7  
     8  package tar
     9  
    10  import (
    11  	"bytes"
    12  	"internal/testenv"
    13  	"io"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  	"testing"
    18  )
    19  
    20  var constrainedBuilders = map[string]bool{
    21  	"windows-386-2012":  true,
    22  	"windows-386-2008":  true,
    23  	"js-wasm":           true,
    24  	"android-amd64-emu": true,
    25  }
    26  
    27  func FuzzReader(f *testing.F) {
    28  	if constrainedBuilders[testenv.Builder()] {
    29  		f.Skip("builder is memory constrained")
    30  	}
    31  	testdata, err := os.ReadDir("testdata")
    32  	if err != nil {
    33  		f.Fatalf("failed to read testdata directory: %s", err)
    34  	}
    35  	for _, de := range testdata {
    36  		if de.IsDir() {
    37  			continue
    38  		}
    39  		if strings.Contains(de.Name(), "big") {
    40  			// skip large archives so we don't kill builders with restricted
    41  			// memory
    42  			continue
    43  		}
    44  		b, err := os.ReadFile(filepath.Join("testdata", de.Name()))
    45  		if err != nil {
    46  			f.Fatalf("failed to read testdata: %s", err)
    47  		}
    48  		f.Add(b)
    49  	}
    50  
    51  	f.Fuzz(func(t *testing.T, b []byte) {
    52  		r := NewReader(bytes.NewReader(b))
    53  		type file struct {
    54  			header  *Header
    55  			content []byte
    56  		}
    57  		files := []file{}
    58  		for {
    59  			hdr, err := r.Next()
    60  			if err == io.EOF {
    61  				break
    62  			}
    63  			if err != nil {
    64  				return
    65  			}
    66  			buf := bytes.NewBuffer(nil)
    67  			if _, err := io.Copy(buf, r); err != nil {
    68  				continue
    69  			}
    70  			files = append(files, file{header: hdr, content: buf.Bytes()})
    71  		}
    72  
    73  		// If we were unable to read anything out of the archive don't
    74  		// bother trying to roundtrip it.
    75  		if len(files) == 0 {
    76  			return
    77  		}
    78  
    79  		out := bytes.NewBuffer(nil)
    80  		w := NewWriter(out)
    81  		for _, f := range files {
    82  			if err := w.WriteHeader(f.header); err != nil {
    83  				t.Fatalf("unable to write previously parsed header: %s", err)
    84  			}
    85  			if _, err := w.Write(f.content); err != nil {
    86  				t.Fatalf("unable to write previously parsed content: %s", err)
    87  			}
    88  		}
    89  		if err := w.Close(); err != nil {
    90  			t.Fatalf("Unable to write archive: %s", err)
    91  		}
    92  
    93  		// TODO: We may want to check if the archive roundtrips. This would require
    94  		// taking into account addition of the two zero trailer blocks that Writer.Close
    95  		// appends.
    96  	})
    97  }