mirror of
https://github.com/soypat/lneto.git
synced 2026-09-01 20:39:11 +00:00
use top level method signature for iterators
This commit is contained in:
@@ -171,148 +171,6 @@ func TestHandshakeFrameRawDataIncludesHeader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachExtensionWalksAndToleratesGREASE(t *testing.T) {
|
||||
// Two extensions: a GREASE type with empty data, then supported_versions.
|
||||
exts := []byte{
|
||||
0x0a, 0x0a, 0x00, 0x00, // GREASE, len 0
|
||||
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, // supported_versions
|
||||
}
|
||||
var types []tls.ExtensionType
|
||||
err := tls.ForEachExtension(exts, func(ext tls.ExtensionType, data []byte) error {
|
||||
types = append(types, ext)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(types) != 2 || types[1] != tls.ExtSupportedVersions {
|
||||
t.Fatalf("got %v", types)
|
||||
}
|
||||
if !tls.IsGREASE(uint16(types[0])) {
|
||||
t.Errorf("first extension %#x not recognized as GREASE", types[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachExtensionTruncated(t *testing.T) {
|
||||
for _, tc := range [][]byte{
|
||||
{0x00}, // partial type
|
||||
{0x00, 0x2b, 0x00}, // partial length
|
||||
{0x00, 0x2b, 0x00, 0x05, 0x02, 0x03}, // length overruns
|
||||
} {
|
||||
err := tls.ForEachExtension(tc, func(tls.ExtensionType, []byte) error { return nil })
|
||||
if !errors.Is(err, lneto.ErrTruncatedFrame) {
|
||||
t.Errorf("% x: got %v want ErrTruncatedFrame", tc, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachExtensionPropagatesCallbackError(t *testing.T) {
|
||||
sentinel := errors.New("stop")
|
||||
exts := []byte{0x00, 0x2b, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00}
|
||||
n := 0
|
||||
err := tls.ForEachExtension(exts, func(tls.ExtensionType, []byte) error {
|
||||
n++
|
||||
return sentinel
|
||||
})
|
||||
if !errors.Is(err, sentinel) {
|
||||
t.Errorf("got %v want sentinel", err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("walk continued after callback error: %d calls", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachKeyShareAcceptsGREASEEntry(t *testing.T) {
|
||||
// Chrome sends a GREASE key share whose key_exchange is a single byte.
|
||||
// Rejecting it as malformed breaks Chrome outright.
|
||||
extData := []byte{
|
||||
0x00, 0x0b, // client_shares length 11
|
||||
0x1a, 0x1a, 0x00, 0x01, 0x00, // GREASE group, 1 byte body
|
||||
0x00, 0x1d, 0x00, 0x02, 0xab, 0xcd, // x25519, 2 byte body
|
||||
}
|
||||
type share struct {
|
||||
g tls.NamedGroup
|
||||
n int
|
||||
}
|
||||
var got []share
|
||||
err := tls.ForEachKeyShare(extData, func(g tls.NamedGroup, key []byte) error {
|
||||
got = append(got, share{g, len(key)})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("got %d shares want 2", len(got))
|
||||
}
|
||||
if !tls.IsGREASE(uint16(got[0].g)) || got[0].n != 1 {
|
||||
t.Errorf("GREASE share mishandled: %+v", got[0])
|
||||
}
|
||||
if got[1].g != tls.GroupX25519 || got[1].n != 2 {
|
||||
t.Errorf("x25519 share mishandled: %+v", got[1])
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachALPNProtoRejectsEmptyName(t *testing.T) {
|
||||
// A zero-length protocol name would make the walk unable to advance.
|
||||
extData := []byte{0x00, 0x01, 0x00}
|
||||
err := tls.ForEachALPNProto(extData, func([]byte) error { return nil })
|
||||
if !errors.Is(err, lneto.ErrInvalidLengthField) {
|
||||
t.Errorf("got %v want ErrInvalidLengthField", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachALPNProto(t *testing.T) {
|
||||
extData := []byte{
|
||||
0x00, 0x0c,
|
||||
0x02, 'h', '2',
|
||||
0x08, 'h', 't', 't', 'p', '/', '1', '.', '1',
|
||||
}
|
||||
var names []string
|
||||
err := tls.ForEachALPNProto(extData, func(b []byte) error {
|
||||
names = append(names, string(b))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(names) != 2 || names[0] != "h2" || names[1] != "http/1.1" {
|
||||
t.Errorf("got %q", names)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachSupportedVersionUsesU8Prefix(t *testing.T) {
|
||||
// supported_versions is the one hello list with a single byte prefix.
|
||||
extData := []byte{0x04, 0x1a, 0x1a, 0x03, 0x04}
|
||||
var vers []uint16
|
||||
err := tls.ForEachSupportedVersion(extData, func(v uint16) error {
|
||||
vers = append(vers, v)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(vers) != 2 || vers[1] != tls.VersionTLS13 {
|
||||
t.Errorf("got %#x", vers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVectorRejectsTrailingBytes(t *testing.T) {
|
||||
// A prefix that under-describes its buffer leaves bytes whose meaning this
|
||||
// parser and a middlebox could disagree about.
|
||||
err := tls.ForEachSupportedGroup([]byte{0x00, 0x02, 0x00, 0x1d, 0xff}, func(tls.NamedGroup) error { return nil })
|
||||
if err == nil {
|
||||
t.Error("trailing bytes after vector accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestForEachU16RejectsOddLength(t *testing.T) {
|
||||
err := tls.ForEachU16([]byte{0x00, 0x1d, 0x00}, func(uint16) error { return nil })
|
||||
if !errors.Is(err, lneto.ErrInvalidLengthField) {
|
||||
t.Errorf("got %v want ErrInvalidLengthField", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsGREASE(t *testing.T) {
|
||||
// The 16 reserved values of RFC 8701.
|
||||
for i := range 16 {
|
||||
@@ -392,27 +250,3 @@ func FuzzNewInnerPlaintext(f *testing.F) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func FuzzForEachExtension(f *testing.F) {
|
||||
f.Add([]byte{0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04})
|
||||
f.Add([]byte{0x0a, 0x0a, 0x00, 0x00})
|
||||
f.Fuzz(func(t *testing.T, b []byte) {
|
||||
total := 0
|
||||
err := tls.ForEachExtension(b, func(ext tls.ExtensionType, data []byte) error {
|
||||
total += 4 + len(data)
|
||||
if total > len(b) {
|
||||
t.Fatalf("walked %d bytes past input length %d", total, len(b))
|
||||
}
|
||||
// Sub-walkers must also never escape their slice.
|
||||
_ = tls.ForEachKeyShare(data, func(tls.NamedGroup, []byte) error { return nil })
|
||||
_ = tls.ForEachALPNProto(data, func([]byte) error { return nil })
|
||||
_ = tls.ForEachSupportedGroup(data, func(tls.NamedGroup) error { return nil })
|
||||
_ = tls.ForEachSupportedVersion(data, func(uint16) error { return nil })
|
||||
_ = tls.ForEachServerName(data, func(uint8, []byte) error { return nil })
|
||||
return nil
|
||||
})
|
||||
if err == nil && total != len(b) {
|
||||
t.Fatalf("clean walk consumed %d of %d bytes", total, len(b))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user