fuzz.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright (C) 2015 The Protocol Authors.
  2. // +build gofuzz
  3. package protocol
  4. import (
  5. "bytes"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "fmt"
  9. "reflect"
  10. "sync"
  11. )
  12. func Fuzz(data []byte) int {
  13. // Regenerate the length, or we'll most commonly exit quickly due to an
  14. // unexpected eof which is unintestering.
  15. if len(data) > 8 {
  16. binary.BigEndian.PutUint32(data[4:], uint32(len(data))-8)
  17. }
  18. // Setup a rawConnection we'll use to parse the message.
  19. c := rawConnection{
  20. cr: &countingReader{Reader: bytes.NewReader(data)},
  21. closed: make(chan struct{}),
  22. pool: sync.Pool{
  23. New: func() interface{} {
  24. return make([]byte, BlockSize)
  25. },
  26. },
  27. }
  28. // Attempt to parse the message.
  29. hdr, msg, err := c.readMessage()
  30. if err != nil {
  31. return 0
  32. }
  33. // If parsing worked, attempt to encode it again.
  34. newBs, err := msg.AppendXDR(nil)
  35. if err != nil {
  36. panic("not encodable")
  37. }
  38. // Create an appriate header for the re-encoding.
  39. newMsg := make([]byte, 8)
  40. binary.BigEndian.PutUint32(newMsg, encodeHeader(hdr))
  41. binary.BigEndian.PutUint32(newMsg[4:], uint32(len(newBs)))
  42. newMsg = append(newMsg, newBs...)
  43. // Use the rawConnection to parse the re-encoding.
  44. c.cr = &countingReader{Reader: bytes.NewReader(newMsg)}
  45. hdr2, msg2, err := c.readMessage()
  46. if err != nil {
  47. fmt.Println("Initial:\n" + hex.Dump(data))
  48. fmt.Println("New:\n" + hex.Dump(newMsg))
  49. panic("not parseable after re-encode: " + err.Error())
  50. }
  51. // Make sure the data is the same as it was before.
  52. if hdr != hdr2 {
  53. panic("headers differ")
  54. }
  55. if !reflect.DeepEqual(msg, msg2) {
  56. panic("contents differ")
  57. }
  58. return 1
  59. }