fuzz.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // +build gofuzz
  2. package logfmt
  3. import (
  4. "bufio"
  5. "bytes"
  6. "fmt"
  7. "io"
  8. "reflect"
  9. kr "github.com/kr/logfmt"
  10. )
  11. // Fuzz checks reserialized data matches
  12. func Fuzz(data []byte) int {
  13. parsed, err := parse(data)
  14. if err != nil {
  15. return 0
  16. }
  17. var w1 bytes.Buffer
  18. if err = write(parsed, &w1); err != nil {
  19. panic(err)
  20. }
  21. parsed, err = parse(w1.Bytes())
  22. if err != nil {
  23. panic(err)
  24. }
  25. var w2 bytes.Buffer
  26. if err = write(parsed, &w2); err != nil {
  27. panic(err)
  28. }
  29. if !bytes.Equal(w1.Bytes(), w2.Bytes()) {
  30. panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes()))
  31. }
  32. return 1
  33. }
  34. // FuzzVsKR checks go-logfmt/logfmt against kr/logfmt
  35. func FuzzVsKR(data []byte) int {
  36. parsed, err := parse(data)
  37. parsedKR, errKR := parseKR(data)
  38. // github.com/go-logfmt/logfmt is a stricter parser. It returns errors for
  39. // more inputs than github.com/kr/logfmt. Ignore any inputs that have a
  40. // stict error.
  41. if err != nil {
  42. return 0
  43. }
  44. // Fail if the more forgiving parser finds an error not found by the
  45. // stricter parser.
  46. if errKR != nil {
  47. panic(fmt.Sprintf("unmatched error: %v", errKR))
  48. }
  49. if !reflect.DeepEqual(parsed, parsedKR) {
  50. panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR))
  51. }
  52. return 1
  53. }
  54. type kv struct {
  55. k, v []byte
  56. }
  57. func parse(data []byte) ([][]kv, error) {
  58. var got [][]kv
  59. dec := NewDecoder(bytes.NewReader(data))
  60. for dec.ScanRecord() {
  61. var kvs []kv
  62. for dec.ScanKeyval() {
  63. kvs = append(kvs, kv{dec.Key(), dec.Value()})
  64. }
  65. got = append(got, kvs)
  66. }
  67. return got, dec.Err()
  68. }
  69. func parseKR(data []byte) ([][]kv, error) {
  70. var (
  71. s = bufio.NewScanner(bytes.NewReader(data))
  72. err error
  73. h saveHandler
  74. got [][]kv
  75. )
  76. for err == nil && s.Scan() {
  77. h.kvs = nil
  78. err = kr.Unmarshal(s.Bytes(), &h)
  79. got = append(got, h.kvs)
  80. }
  81. if err == nil {
  82. err = s.Err()
  83. }
  84. return got, err
  85. }
  86. type saveHandler struct {
  87. kvs []kv
  88. }
  89. func (h *saveHandler) HandleLogfmt(key, val []byte) error {
  90. if len(key) == 0 {
  91. key = nil
  92. }
  93. if len(val) == 0 {
  94. val = nil
  95. }
  96. h.kvs = append(h.kvs, kv{key, val})
  97. return nil
  98. }
  99. func write(recs [][]kv, w io.Writer) error {
  100. enc := NewEncoder(w)
  101. for _, rec := range recs {
  102. for _, f := range rec {
  103. if err := enc.EncodeKeyval(f.k, f.v); err != nil {
  104. return err
  105. }
  106. }
  107. if err := enc.EndRecord(); err != nil {
  108. return err
  109. }
  110. }
  111. return nil
  112. }