| // Copyright 2019 syzkaller project authors. All rights reserved. |
| // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "encoding/hex" |
| "flag" |
| "fmt" |
| "io/ioutil" |
| "os" |
| "regexp" |
| "sort" |
| |
| "github.com/google/syzkaller/pkg/osutil" |
| ) |
| |
| func main() { |
| flag.Parse() |
| args := flag.Args() |
| if len(args) != 2 { |
| usage() |
| } |
| |
| syslog, err := ioutil.ReadFile(args[0]) |
| if err != nil { |
| failf("failed to read file %v: %v", args[0], err) |
| } |
| |
| usbIds := extractIds(syslog, "USBID", 34) |
| hidIds := extractIds(syslog, "HIDID", 24) |
| |
| output := make([]byte, 0) |
| output = append(output, []byte("// AUTOGENERATED FILE\n")...) |
| output = append(output, []byte("// See docs/linux/external_fuzzing_usb.md\n")...) |
| output = append(output, []byte("\n")...) |
| output = append(output, []byte("package linux\n")...) |
| output = append(output, []byte("\n")...) |
| output = append(output, generateIdsVar(usbIds, "usbIds")...) |
| output = append(output, []byte("\n")...) |
| output = append(output, generateIdsVar(hidIds, "hidIds")...) |
| |
| if err := osutil.WriteFile(args[1], output); err != nil { |
| failf("failed to output file %v: %v", args[1], err) |
| } |
| } |
| |
| func extractIds(syslog []byte, prefix string, size int) []string { |
| re := fmt.Sprintf("%s: [0-9a-f]{%d}", prefix, size) |
| r := regexp.MustCompile(re) |
| matches := r.FindAll(syslog, -1) |
| uniqueMatches := make(map[string]bool) |
| for _, match := range matches { |
| uniqueMatches[string(match)] = true |
| } |
| sortedMatches := make([]string, 0) |
| for match := range uniqueMatches { |
| match = match[len(prefix+": "):] |
| match = match[:size] |
| sortedMatches = append(sortedMatches, match) |
| } |
| sort.Strings(sortedMatches) |
| return sortedMatches |
| } |
| |
| func generateIdsVar(ids []string, name string) []byte { |
| output := []byte(fmt.Sprintf("var %s = ", name)) |
| for i, id := range ids { |
| decodedID, err := hex.DecodeString(id) |
| if err != nil { |
| failf("failed to decode hex string %v: %v", id, err) |
| } |
| prefix := "\t" |
| suffix := " +" |
| if i == 0 { |
| prefix = "" |
| } |
| if i == len(ids)-1 { |
| suffix = "" |
| } |
| outputID := fmt.Sprintf("%v%#v%v\n", prefix, string(decodedID), suffix) |
| output = append(output, []byte(outputID)...) |
| } |
| |
| fmt.Printf("%v %s ids written\n", len(ids), name) |
| |
| return output |
| } |
| |
| func usage() { |
| fmt.Fprintf(os.Stderr, "usage:\n") |
| fmt.Fprintf(os.Stderr, " syz-usbgen syslog.txt sys/linux/init_vusb_ids.go\n") |
| os.Exit(1) |
| } |
| |
| func failf(msg string, args ...interface{}) { |
| fmt.Fprintf(os.Stderr, msg+"\n", args...) |
| os.Exit(1) |
| } |