Files
yggdrasil-go/src/multicast/advertisement.go
Alex Melan bc72b106b7 fix: reject malformed network input in parsers (#1340)
## Summary
- validate handshake metadata field lengths before fixed-size reads
- reject truncated multicast advertisements before slicing the hash
payload
- add regression tests for malformed and truncated input

## Why
Both parsers currently trust length information from the incoming
payload a bit too much. Malformed network input can reach fixed-size
reads/slices and panic the process instead of being rejected cleanly.

## Testing
- go test ./...
2026-04-11 12:04:12 +01:00

44 lines
1.3 KiB
Go

package multicast
import (
"crypto/ed25519"
"encoding/binary"
"fmt"
)
type multicastAdvertisement struct {
MajorVersion uint16
MinorVersion uint16
PublicKey ed25519.PublicKey
Port uint16
Hash []byte
}
func (m *multicastAdvertisement) MarshalBinary() ([]byte, error) {
b := make([]byte, 0, ed25519.PublicKeySize+8+len(m.Hash))
b = binary.BigEndian.AppendUint16(b, m.MajorVersion)
b = binary.BigEndian.AppendUint16(b, m.MinorVersion)
b = append(b, m.PublicKey...)
b = binary.BigEndian.AppendUint16(b, m.Port)
b = binary.BigEndian.AppendUint16(b, uint16(len(m.Hash)))
b = append(b, m.Hash...)
return b, nil
}
func (m *multicastAdvertisement) UnmarshalBinary(b []byte) error {
const headerLen = ed25519.PublicKeySize + 8
if len(b) < headerLen {
return fmt.Errorf("invalid multicast beacon")
}
m.MajorVersion = binary.BigEndian.Uint16(b[0:2])
m.MinorVersion = binary.BigEndian.Uint16(b[2:4])
m.PublicKey = append(m.PublicKey[:0], b[4:4+ed25519.PublicKeySize]...)
m.Port = binary.BigEndian.Uint16(b[4+ed25519.PublicKeySize : 6+ed25519.PublicKeySize])
dl := int(binary.BigEndian.Uint16(b[6+ed25519.PublicKeySize : 8+ed25519.PublicKeySize]))
if len(b) < headerLen+dl {
return fmt.Errorf("invalid multicast beacon")
}
m.Hash = append(m.Hash[:0], b[headerLen:headerLen+dl]...)
return nil
}