Multiaddr._from_bytes() stores raw bytes without any validation. Invalid binary multiaddrs are accepted silently and only fail later when __str__() or other methods try to parse them. This makes debugging difficult and violates the principle of fail-fast.
Problem
In multiaddr/multiaddr.py:
def _from_bytes(self, addr: bytes) -> None:
if not addr:
self._bytes = b""
return
self._bytes = addr # ← No validation at all!
This means:
# These all succeed without error:
Multiaddr(b'\xff\xff\xff') # Invalid varint
Multiaddr(b'\x99\x01\x00') # Unknown protocol code 0x99
Multiaddr(b'\x04\x04\x01\x02') # ip4 with only 3 bytes of address (needs 4)
# They only fail later:
str(Multiaddr(b'\xff\xff\xff')) # BinaryParseError
str(Multiaddr(b'\x99\x01\x00')) # BinaryParseError: Unknown Protocol
Go's NewMultiaddrBytes() validates immediately:
func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
bytesRead, m, err := readMultiaddr(b)
if err != nil { return nil, err }
if bytesRead != len(b) {
return nil, fmt.Errorf("unexpected extra data. %v bytes leftover", len(b)-bytesRead)
}
return m, nil
}
Proposed Solution
Add validation in _from_bytes():
def _from_bytes(self, addr: bytes) -> None:
if not addr:
self._bytes = b""
return
# Validate by iterating all components
consumed = 0
for offset, proto, codec, part_value in bytes_iter(addr):
consumed = offset + len(proto.vcode)
if codec.SIZE < 0:
consumed += len(varint.encode(len(part_value)))
consumed += len(part_value)
if consumed != len(addr):
raise exceptions.BinaryParseError(
f"unexpected extra data: {len(addr) - consumed} bytes leftover",
addr,
0,
)
self._bytes = addr
Related
Multiaddr._from_bytes()stores raw bytes without any validation. Invalid binary multiaddrs are accepted silently and only fail later when__str__()or other methods try to parse them. This makes debugging difficult and violates the principle of fail-fast.Problem
In
multiaddr/multiaddr.py:This means:
Go's
NewMultiaddrBytes()validates immediately:Proposed Solution
Add validation in
_from_bytes():Related
multibase.goNewMultiaddrBytes()