...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package main
21
22 import (
23 "crypto/sha256"
24 "errors"
25 "flag"
26 "fmt"
27 "io"
28 "log"
29 "os"
30 "path/filepath"
31 )
32
33
34 var encVersion1 = "go test fuzz v1"
35
36 func encodeByteSlice(b []byte) []byte {
37 return []byte(fmt.Sprintf("%s\n[]byte(%q)", encVersion1, b))
38 }
39
40 func usage() {
41 fmt.Fprintf(os.Stderr, "usage: file2fuzz [-o output] [input...]\nconverts files to Go fuzzer corpus format\n")
42 fmt.Fprintf(os.Stderr, "\tinput: files to convert\n")
43 fmt.Fprintf(os.Stderr, "\t-o: where to write converted file(s)\n")
44 os.Exit(2)
45 }
46 func dirWriter(dir string) func([]byte) error {
47 return func(b []byte) error {
48 sum := fmt.Sprintf("%x", sha256.Sum256(b))
49 name := filepath.Join(dir, sum)
50 if err := os.MkdirAll(dir, 0777); err != nil {
51 return err
52 }
53 if err := os.WriteFile(name, b, 0666); err != nil {
54 os.Remove(name)
55 return err
56 }
57 return nil
58 }
59 }
60
61 func convert(inputArgs []string, outputArg string) error {
62 var input []io.Reader
63 if args := inputArgs; len(args) == 0 {
64 input = []io.Reader{os.Stdin}
65 } else {
66 for _, a := range args {
67 f, err := os.Open(a)
68 if err != nil {
69 return fmt.Errorf("unable to open %q: %s", a, err)
70 }
71 defer f.Close()
72 if fi, err := f.Stat(); err != nil {
73 return fmt.Errorf("unable to open %q: %s", a, err)
74 } else if fi.IsDir() {
75 return fmt.Errorf("%q is a directory, not a file", a)
76 }
77 input = append(input, f)
78 }
79 }
80
81 var output func([]byte) error
82 if outputArg == "" {
83 if len(inputArgs) > 1 {
84 return errors.New("-o required with multiple input files")
85 }
86 output = func(b []byte) error {
87 _, err := os.Stdout.Write(b)
88 return err
89 }
90 } else {
91 if len(inputArgs) > 1 {
92 output = dirWriter(outputArg)
93 } else {
94 if fi, err := os.Stat(outputArg); err != nil && !os.IsNotExist(err) {
95 return fmt.Errorf("unable to open %q for writing: %s", outputArg, err)
96 } else if err == nil && fi.IsDir() {
97 output = dirWriter(outputArg)
98 } else {
99 output = func(b []byte) error {
100 return os.WriteFile(outputArg, b, 0666)
101 }
102 }
103 }
104 }
105
106 for _, f := range input {
107 b, err := io.ReadAll(f)
108 if err != nil {
109 return fmt.Errorf("unable to read input: %s", err)
110 }
111 if err := output(encodeByteSlice(b)); err != nil {
112 return fmt.Errorf("unable to write output: %s", err)
113 }
114 }
115
116 return nil
117 }
118
119 func main() {
120 log.SetFlags(0)
121 log.SetPrefix("file2fuzz: ")
122
123 output := flag.String("o", "", "where to write converted file(s)")
124 flag.Usage = usage
125 flag.Parse()
126
127 if err := convert(flag.Args(), *output); err != nil {
128 log.Fatal(err)
129 }
130 }
131
View as plain text