File: ipv6_test.go

package info (click to toggle)
golang-github-valyala-fasthttp 1%3A1.67.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,956 kB
  • sloc: makefile: 34
file content (85 lines) | stat: -rw-r--r-- 2,255 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package fasthttp

import (
	"bytes"
	"net"
	"testing"
)

// oracleValid replicates the original function's semantics using net.ParseIP:
// - Input must start with '['
// - There must be a closing ']' and a non-empty address between
// - Optional %zone allowed but must not be empty
// - Zone is stripped before checking with net.ParseIP
// - Must contain a ':' to be IPv6 (prevents raw IPv4-in-brackets).
func oracleValid(host []byte) bool {
	if len(host) == 0 || host[0] != '[' {
		// Original function: non-bracketed hosts return nil (treated as valid/no-op).
		return true
	}

	end := bytes.IndexByte(host, ']')
	if end < 0 {
		return false
	}
	addr := host[1:end]
	if len(addr) == 0 {
		return false
	}

	// Split off %zone (if present).
	if zi := bytes.IndexByte(addr, '%'); zi >= 0 {
		// Zone must not be empty.
		if zi == len(addr)-1 {
			return false
		}
		addr = addr[:zi]
	}

	// Must contain ':' to be IPv6.
	if bytes.IndexByte(addr, ':') < 0 {
		return false
	}

	// Use net.ParseIP on the de-zoned address (this was the original check).
	if ip := net.ParseIP(string(addr)); ip == nil {
		return false
	}
	return true
}

func FuzzValidateIPv6Literal(f *testing.F) {
	seeds := [][]byte{
		[]byte(""),            // non-bracketed => valid (no-op)
		[]byte("example.com"), // non-bracketed => valid (no-op)
		[]byte("["),           // unterminated
		[]byte("[]"),          // empty
		[]byte("[::]"),
		[]byte("[::1]"),
		[]byte("[2001:db8::1]"),
		[]byte("[2001:db8::]"),
		[]byte("[::ffff:192.168.0.1]"),
		[]byte("[fe80::1%eth0]"),
		[]byte("[fe80::1%]"),         // empty zone
		[]byte("[1234]"),             // no colon
		[]byte("[2001:db8:zzzz::1]"), // invalid hex
		[]byte("[::ffff:256.0.0.1]"), // invalid v4 tail
		[]byte("[2001:db8:::1]"),     // triple colon
		[]byte("[::1]:443"),          // trailing port outside ']' is ignored by validator
		[]byte("[2001:db8:0:0:0:0:2:1]"),
		[]byte("[2001:db8:0:0:0:0:2:1%en0]"),
	}
	for _, s := range seeds {
		f.Add(s)
	}

	f.Fuzz(func(t *testing.T, host []byte) {
		gotErr := validateIPv6Literal(host)
		wantValid := oracleValid(host)

		if (gotErr == nil) != wantValid {
			t.Fatalf("mismatch for %q: validateIPv6Literal err=%v, oracleValid=%v",
				b2s(host), gotErr, wantValid)
		}
	})
}