|
|
|
|
package locator_test
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"g.activething.com/go/DateKeys/extension"
|
|
|
|
|
"g.activething.com/go/DateKeys/internal/testkit"
|
|
|
|
|
"g.activething.com/go/DateKeys/locator"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// FuzzUnmarshal reads the plaintext of a locator: it never panics, and what
|
|
|
|
|
// it accepts is canonical, so that encoding it again gives the same bytes.
|
|
|
|
|
func FuzzUnmarshal(f *testing.F) {
|
|
|
|
|
var v testkit.LocatorVectorFile
|
|
|
|
|
if err := testkit.ReadJSON("../testdata/vectors/locator.json", &v); err != nil {
|
|
|
|
|
f.Fatal(err)
|
|
|
|
|
}
|
Test data: locator.json with the cases of spec v0.12, section 64
- uri_cases: the first and the last address of each IPv4 block of 44.1,
with the public addresses next to them; the IPv6 blocks and the
addresses that hold an IPv4 one; the local names; characters outside
RFC 3986 and broken percent signs; "." and ".." segments; base32 that
is not a CID v1.
- mixed: a locator whose http and NAT64 addresses a reader rejects, and
whose third address it uses to find the rest.
- rest_cases: the rest alone, a host with bytes after the rest, a rest
with a byte changed, an offset that is not its own, a rest cut short.
- extension_cases: a locator sealed for round 1001 with a DateKey of
round 1000, and the other data that a reader cannot use.
- plaintext_cases: change 7, the bases 4094, 4070 and 3837 completed to
4096 with an empty key 6 or a length not in its shortest form, and a
defect in each field of the map.
- padding_cases: the bases 3837, 4070, 4094 and 4095 and those of the
next multiple, checked against the rule of 44.1.
The generator checks every case against this module and moves to its
own file. The vector is frozen: delete it to make it again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 days ago
|
|
|
for _, s := range []string{v.Plaintext, v.Mixed.Plaintext} {
|
|
|
|
|
if b, err := hex.DecodeString(s); err == nil {
|
|
|
|
|
f.Add(b)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, c := range v.PlaintextCases {
|
|
|
|
|
if b, err := hex.DecodeString(c.Plaintext); err == nil {
|
|
|
|
|
f.Add(b)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f.Add([]byte{0xa0})
|
|
|
|
|
f.Fuzz(func(t *testing.T, b []byte) {
|
|
|
|
|
l, err := locator.Unmarshal(b)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for _, a := range l.Usable() {
|
|
|
|
|
if locator.CheckURI(a.URI) != nil || a.Host() == "" {
|
|
|
|
|
t.Fatalf("a usable address %q that the rules refuse", a.URI)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FuzzParseInfo reads the data of datekeys.capsule: it never panics, and its
|
|
|
|
|
// only normative code is ERR_EXTENSION_DATA_INVALID (spec §54, §57).
|
|
|
|
|
func FuzzParseInfo(f *testing.F) {
|
|
|
|
|
var v testkit.LocatorVectorFile
|
|
|
|
|
if err := testkit.ReadJSON("../testdata/vectors/locator.json", &v); err != nil {
|
|
|
|
|
f.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
if b, err := hex.DecodeString(v.Extension); err == nil {
|
|
|
|
|
f.Add(b)
|
|
|
|
|
}
|
Test data: locator.json with the cases of spec v0.12, section 64
- uri_cases: the first and the last address of each IPv4 block of 44.1,
with the public addresses next to them; the IPv6 blocks and the
addresses that hold an IPv4 one; the local names; characters outside
RFC 3986 and broken percent signs; "." and ".." segments; base32 that
is not a CID v1.
- mixed: a locator whose http and NAT64 addresses a reader rejects, and
whose third address it uses to find the rest.
- rest_cases: the rest alone, a host with bytes after the rest, a rest
with a byte changed, an offset that is not its own, a rest cut short.
- extension_cases: a locator sealed for round 1001 with a DateKey of
round 1000, and the other data that a reader cannot use.
- plaintext_cases: change 7, the bases 4094, 4070 and 3837 completed to
4096 with an empty key 6 or a length not in its shortest form, and a
defect in each field of the map.
- padding_cases: the bases 3837, 4070, 4094 and 4095 and those of the
next multiple, checked against the rule of 44.1.
The generator checks every case against this module and moves to its
own file. The vector is frozen: delete it to make it again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 days ago
|
|
|
for _, c := range v.ExtensionCases {
|
|
|
|
|
if b, err := hex.DecodeString(c.Data); err == nil {
|
|
|
|
|
f.Add(b)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f.Fuzz(func(t *testing.T, b []byte) {
|
|
|
|
|
_, err := locator.ParseInfo(extension.Extension{ID: extension.CapsuleID, Version: 1, Data: b})
|
|
|
|
|
if err != nil && !bytes.Contains([]byte(err.Error()), []byte("ERR_EXTENSION_DATA_INVALID")) {
|
|
|
|
|
t.Fatalf("an error without its code: %v", err)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FuzzCheckURI checks an address: it never panics, and a host that it shows
|
|
|
|
|
// is in the address as it is written, with no decoding.
|
|
|
|
|
func FuzzCheckURI(f *testing.F) {
|
|
|
|
|
var v testkit.LocatorVectorFile
|
|
|
|
|
if err := testkit.ReadJSON("../testdata/vectors/locator.json", &v); err != nil {
|
|
|
|
|
f.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
for _, c := range v.URICases {
|
|
|
|
|
f.Add(c.URI)
|
|
|
|
|
}
|
|
|
|
|
f.Fuzz(func(t *testing.T, uri string) {
|
|
|
|
|
if locator.CheckURI(uri) != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if h := (locator.Address{URI: uri}).Host(); h == "" || !bytes.Contains([]byte(uri), []byte(h)) {
|
|
|
|
|
t.Fatalf("%q: host %q", uri, h)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|