fuzz_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. //go:build ignore_due_to_generics
  5. package netip_test
  6. import (
  7. "bytes"
  8. "encoding"
  9. "fmt"
  10. "net"
  11. . "net/netip"
  12. "reflect"
  13. "strings"
  14. "testing"
  15. )
  16. var corpus = []string{
  17. // Basic zero IPv4 address.
  18. "0.0.0.0",
  19. // Basic non-zero IPv4 address.
  20. "192.168.140.255",
  21. // IPv4 address in windows-style "print all the digits" form.
  22. "010.000.015.001",
  23. // IPv4 address with a silly amount of leading zeros.
  24. "000001.00000002.00000003.000000004",
  25. // 4-in-6 with octet with leading zero
  26. "::ffff:1.2.03.4",
  27. // Basic zero IPv6 address.
  28. "::",
  29. // Localhost IPv6.
  30. "::1",
  31. // Fully expanded IPv6 address.
  32. "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b",
  33. // IPv6 with elided fields in the middle.
  34. "fd7a:115c::626b:430b",
  35. // IPv6 with elided fields at the end.
  36. "fd7a:115c:a1e0:ab12:4843:cd96::",
  37. // IPv6 with single elided field at the end.
  38. "fd7a:115c:a1e0:ab12:4843:cd96:626b::",
  39. "fd7a:115c:a1e0:ab12:4843:cd96:626b:0",
  40. // IPv6 with single elided field in the middle.
  41. "fd7a:115c:a1e0::4843:cd96:626b:430b",
  42. "fd7a:115c:a1e0:0:4843:cd96:626b:430b",
  43. // IPv6 with the trailing 32 bits written as IPv4 dotted decimal. (4in6)
  44. "::ffff:192.168.140.255",
  45. "::ffff:192.168.140.255",
  46. // IPv6 with a zone specifier.
  47. "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0",
  48. // IPv6 with dotted decimal and zone specifier.
  49. "1:2::ffff:192.168.140.255%eth1",
  50. "1:2::ffff:c0a8:8cff%eth1",
  51. // IPv6 with capital letters.
  52. "FD9E:1A04:F01D::1",
  53. "fd9e:1a04:f01d::1",
  54. // Empty string.
  55. "",
  56. // Garbage non-IP.
  57. "bad",
  58. // Single number. Some parsers accept this as an IPv4 address in
  59. // big-endian uint32 form, but we don't.
  60. "1234",
  61. // IPv4 with a zone specifier.
  62. "1.2.3.4%eth0",
  63. // IPv4 field must have at least one digit.
  64. ".1.2.3",
  65. "1.2.3.",
  66. "1..2.3",
  67. // IPv4 address too long.
  68. "1.2.3.4.5",
  69. // IPv4 in dotted octal form.
  70. "0300.0250.0214.0377",
  71. // IPv4 in dotted hex form.
  72. "0xc0.0xa8.0x8c.0xff",
  73. // IPv4 in class B form.
  74. "192.168.12345",
  75. // IPv4 in class B form, with a small enough number to be
  76. // parseable as a regular dotted decimal field.
  77. "127.0.1",
  78. // IPv4 in class A form.
  79. "192.1234567",
  80. // IPv4 in class A form, with a small enough number to be
  81. // parseable as a regular dotted decimal field.
  82. "127.1",
  83. // IPv4 field has value >255.
  84. "192.168.300.1",
  85. // IPv4 with too many fields.
  86. "192.168.0.1.5.6",
  87. // IPv6 with not enough fields.
  88. "1:2:3:4:5:6:7",
  89. // IPv6 with too many fields.
  90. "1:2:3:4:5:6:7:8:9",
  91. // IPv6 with 8 fields and a :: expander.
  92. "1:2:3:4::5:6:7:8",
  93. // IPv6 with a field bigger than 2b.
  94. "fe801::1",
  95. // IPv6 with non-hex values in field.
  96. "fe80:tail:scal:e::",
  97. // IPv6 with a zone delimiter but no zone.
  98. "fe80::1%",
  99. // IPv6 with a zone specifier of zero.
  100. "::ffff:0:0%0",
  101. // IPv6 (without ellipsis) with too many fields for trailing embedded IPv4.
  102. "ffff:ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255",
  103. // IPv6 (with ellipsis) with too many fields for trailing embedded IPv4.
  104. "ffff::ffff:ffff:ffff:ffff:ffff:ffff:192.168.140.255",
  105. // IPv6 with invalid embedded IPv4.
  106. "::ffff:192.168.140.bad",
  107. // IPv6 with multiple ellipsis ::.
  108. "fe80::1::1",
  109. // IPv6 with invalid non hex/colon character.
  110. "fe80:1?:1",
  111. // IPv6 with truncated bytes after single colon.
  112. "fe80:",
  113. // AddrPort strings.
  114. "1.2.3.4:51820",
  115. "[fd7a:115c:a1e0:ab12:4843:cd96:626b:430b]:80",
  116. "[::ffff:c000:0280]:65535",
  117. "[::ffff:c000:0280%eth0]:1",
  118. // Prefix strings.
  119. "1.2.3.4/24",
  120. "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b/118",
  121. "::ffff:c000:0280/96",
  122. "::ffff:c000:0280%eth0/37",
  123. }
  124. func FuzzParse(f *testing.F) {
  125. for _, seed := range corpus {
  126. f.Add(seed)
  127. }
  128. f.Fuzz(func(t *testing.T, s string) {
  129. ip, _ := ParseAddr(s)
  130. checkStringParseRoundTrip(t, ip, ParseAddr)
  131. checkEncoding(t, ip)
  132. // Check that we match the net's IP parser, modulo zones.
  133. if !strings.Contains(s, "%") {
  134. stdip := net.ParseIP(s)
  135. if !ip.IsValid() != (stdip == nil) {
  136. t.Errorf("ParseAddr zero != net.ParseIP nil: ip=%q stdip=%q", ip, stdip)
  137. }
  138. if ip.IsValid() && !ip.Is4In6() {
  139. buf, err := ip.MarshalText()
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. buf2, err := stdip.MarshalText()
  144. if err != nil {
  145. t.Fatal(err)
  146. }
  147. if !bytes.Equal(buf, buf2) {
  148. t.Errorf("Addr.MarshalText() != net.IP.MarshalText(): ip=%q stdip=%q", ip, stdip)
  149. }
  150. if ip.String() != stdip.String() {
  151. t.Errorf("Addr.String() != net.IP.String(): ip=%q stdip=%q", ip, stdip)
  152. }
  153. if ip.IsGlobalUnicast() != stdip.IsGlobalUnicast() {
  154. t.Errorf("Addr.IsGlobalUnicast() != net.IP.IsGlobalUnicast(): ip=%q stdip=%q", ip, stdip)
  155. }
  156. if ip.IsInterfaceLocalMulticast() != stdip.IsInterfaceLocalMulticast() {
  157. t.Errorf("Addr.IsInterfaceLocalMulticast() != net.IP.IsInterfaceLocalMulticast(): ip=%q stdip=%q", ip, stdip)
  158. }
  159. if ip.IsLinkLocalMulticast() != stdip.IsLinkLocalMulticast() {
  160. t.Errorf("Addr.IsLinkLocalMulticast() != net.IP.IsLinkLocalMulticast(): ip=%q stdip=%q", ip, stdip)
  161. }
  162. if ip.IsLinkLocalUnicast() != stdip.IsLinkLocalUnicast() {
  163. t.Errorf("Addr.IsLinkLocalUnicast() != net.IP.IsLinkLocalUnicast(): ip=%q stdip=%q", ip, stdip)
  164. }
  165. if ip.IsLoopback() != stdip.IsLoopback() {
  166. t.Errorf("Addr.IsLoopback() != net.IP.IsLoopback(): ip=%q stdip=%q", ip, stdip)
  167. }
  168. if ip.IsMulticast() != stdip.IsMulticast() {
  169. t.Errorf("Addr.IsMulticast() != net.IP.IsMulticast(): ip=%q stdip=%q", ip, stdip)
  170. }
  171. if ip.IsPrivate() != stdip.IsPrivate() {
  172. t.Errorf("Addr.IsPrivate() != net.IP.IsPrivate(): ip=%q stdip=%q", ip, stdip)
  173. }
  174. if ip.IsUnspecified() != stdip.IsUnspecified() {
  175. t.Errorf("Addr.IsUnspecified() != net.IP.IsUnspecified(): ip=%q stdip=%q", ip, stdip)
  176. }
  177. }
  178. }
  179. // Check that .Next().Prev() and .Prev().Next() preserve the IP.
  180. if ip.IsValid() && ip.Next().IsValid() && ip.Next().Prev() != ip {
  181. t.Errorf(".Next.Prev did not round trip: ip=%q .next=%q .next.prev=%q", ip, ip.Next(), ip.Next().Prev())
  182. }
  183. if ip.IsValid() && ip.Prev().IsValid() && ip.Prev().Next() != ip {
  184. t.Errorf(".Prev.Next did not round trip: ip=%q .prev=%q .prev.next=%q", ip, ip.Prev(), ip.Prev().Next())
  185. }
  186. port, err := ParseAddrPort(s)
  187. if err == nil {
  188. checkStringParseRoundTrip(t, port, ParseAddrPort)
  189. checkEncoding(t, port)
  190. }
  191. port = AddrPortFrom(ip, 80)
  192. checkStringParseRoundTrip(t, port, ParseAddrPort)
  193. checkEncoding(t, port)
  194. ipp, err := ParsePrefix(s)
  195. if err == nil {
  196. checkStringParseRoundTrip(t, ipp, ParsePrefix)
  197. checkEncoding(t, ipp)
  198. }
  199. ipp = PrefixFrom(ip, 8)
  200. checkStringParseRoundTrip(t, ipp, ParsePrefix)
  201. checkEncoding(t, ipp)
  202. })
  203. }
  204. // checkTextMarshaler checks that x's MarshalText and UnmarshalText functions round trip correctly.
  205. func checkTextMarshaler(t *testing.T, x encoding.TextMarshaler) {
  206. buf, err := x.MarshalText()
  207. if err != nil {
  208. t.Fatal(err)
  209. }
  210. y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.TextUnmarshaler)
  211. err = y.UnmarshalText(buf)
  212. if err != nil {
  213. t.Logf("(%v).MarshalText() = %q", x, buf)
  214. t.Fatalf("(%T).UnmarshalText(%q) = %v", y, buf, err)
  215. }
  216. e := reflect.ValueOf(y).Elem().Interface()
  217. if !reflect.DeepEqual(x, e) {
  218. t.Logf("(%v).MarshalText() = %q", x, buf)
  219. t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
  220. t.Fatalf("MarshalText/UnmarshalText failed to round trip: %#v != %#v", x, e)
  221. }
  222. buf2, err := y.(encoding.TextMarshaler).MarshalText()
  223. if err != nil {
  224. t.Logf("(%v).MarshalText() = %q", x, buf)
  225. t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
  226. t.Fatalf("failed to MarshalText a second time: %v", err)
  227. }
  228. if !bytes.Equal(buf, buf2) {
  229. t.Logf("(%v).MarshalText() = %q", x, buf)
  230. t.Logf("(%T).UnmarshalText(%q) = %v", y, buf, y)
  231. t.Logf("(%v).MarshalText() = %q", y, buf2)
  232. t.Fatalf("second MarshalText differs from first: %q != %q", buf, buf2)
  233. }
  234. }
  235. // checkBinaryMarshaler checks that x's MarshalText and UnmarshalText functions round trip correctly.
  236. func checkBinaryMarshaler(t *testing.T, x encoding.BinaryMarshaler) {
  237. buf, err := x.MarshalBinary()
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. y := reflect.New(reflect.TypeOf(x)).Interface().(encoding.BinaryUnmarshaler)
  242. err = y.UnmarshalBinary(buf)
  243. if err != nil {
  244. t.Logf("(%v).MarshalBinary() = %q", x, buf)
  245. t.Fatalf("(%T).UnmarshalBinary(%q) = %v", y, buf, err)
  246. }
  247. e := reflect.ValueOf(y).Elem().Interface()
  248. if !reflect.DeepEqual(x, e) {
  249. t.Logf("(%v).MarshalBinary() = %q", x, buf)
  250. t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
  251. t.Fatalf("MarshalBinary/UnmarshalBinary failed to round trip: %#v != %#v", x, e)
  252. }
  253. buf2, err := y.(encoding.BinaryMarshaler).MarshalBinary()
  254. if err != nil {
  255. t.Logf("(%v).MarshalBinary() = %q", x, buf)
  256. t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
  257. t.Fatalf("failed to MarshalBinary a second time: %v", err)
  258. }
  259. if !bytes.Equal(buf, buf2) {
  260. t.Logf("(%v).MarshalBinary() = %q", x, buf)
  261. t.Logf("(%T).UnmarshalBinary(%q) = %v", y, buf, y)
  262. t.Logf("(%v).MarshalBinary() = %q", y, buf2)
  263. t.Fatalf("second MarshalBinary differs from first: %q != %q", buf, buf2)
  264. }
  265. }
  266. func checkTextMarshalMatchesString(t *testing.T, x netipType) {
  267. buf, err := x.MarshalText()
  268. if err != nil {
  269. t.Fatal(err)
  270. }
  271. str := x.String()
  272. if string(buf) != str {
  273. t.Fatalf("%v: MarshalText = %q, String = %q", x, buf, str)
  274. }
  275. }
  276. type appendMarshaler interface {
  277. encoding.TextMarshaler
  278. AppendTo([]byte) []byte
  279. }
  280. // checkTextMarshalMatchesAppendTo checks that x's MarshalText matches x's AppendTo.
  281. func checkTextMarshalMatchesAppendTo(t *testing.T, x appendMarshaler) {
  282. buf, err := x.MarshalText()
  283. if err != nil {
  284. t.Fatal(err)
  285. }
  286. buf2 := make([]byte, 0, len(buf))
  287. buf2 = x.AppendTo(buf2)
  288. if !bytes.Equal(buf, buf2) {
  289. t.Fatalf("%v: MarshalText = %q, AppendTo = %q", x, buf, buf2)
  290. }
  291. }
  292. type netipType interface {
  293. encoding.BinaryMarshaler
  294. encoding.TextMarshaler
  295. fmt.Stringer
  296. IsValid() bool
  297. }
  298. type netipTypeCmp interface {
  299. comparable
  300. netipType
  301. }
  302. // checkStringParseRoundTrip checks that x's String method and the provided parse function can round trip correctly.
  303. func checkStringParseRoundTrip[P netipTypeCmp](t *testing.T, x P, parse func(string) (P, error)) {
  304. if !x.IsValid() {
  305. // Ignore invalid values.
  306. return
  307. }
  308. s := x.String()
  309. y, err := parse(s)
  310. if err != nil {
  311. t.Fatalf("s=%q err=%v", s, err)
  312. }
  313. if x != y {
  314. t.Fatalf("%T round trip identity failure: s=%q x=%#v y=%#v", x, s, x, y)
  315. }
  316. s2 := y.String()
  317. if s != s2 {
  318. t.Fatalf("%T String round trip identity failure: s=%#v s2=%#v", x, s, s2)
  319. }
  320. }
  321. func checkEncoding(t *testing.T, x netipType) {
  322. if x.IsValid() {
  323. checkTextMarshaler(t, x)
  324. checkBinaryMarshaler(t, x)
  325. checkTextMarshalMatchesString(t, x)
  326. }
  327. if am, ok := x.(appendMarshaler); ok {
  328. checkTextMarshalMatchesAppendTo(t, am)
  329. }
  330. }