From d14e9ef449fcd741580e609675bbfcfbb95e0263 Mon Sep 17 00:00:00 2001 From: sumanjeet0012 Date: Mon, 13 Jul 2026 23:40:58 +0530 Subject: [PATCH] fix: validate binary input in _from_bytes --- multiaddr/multiaddr.py | 18 ++++++++++++++++++ multiaddr/transforms.py | 9 ++++++++- newsfragments/110.bugfix | 1 + tests/test_multiaddr.py | 14 +++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 newsfragments/110.bugfix diff --git a/multiaddr/multiaddr.py b/multiaddr/multiaddr.py index 45efc6c..8978d4a 100644 --- a/multiaddr/multiaddr.py +++ b/multiaddr/multiaddr.py @@ -508,6 +508,24 @@ def _from_bytes(self, addr: bytes) -> None: self._bytes = b"" return + # Validate by iterating all components + consumed = 0 + try: + 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) + except Exception as e: + raise exceptions.BinaryParseError(f"invalid multiaddr bytes: {e}", addr, 0) from e + + if consumed != len(addr): + raise exceptions.BinaryParseError( + f"unexpected extra data: {len(addr) - consumed} bytes leftover", + addr, + 0, + ) + self._bytes = addr def get_peer_id(self) -> str | None: diff --git a/multiaddr/transforms.py b/multiaddr/transforms.py index b366f59..1b373fc 100644 --- a/multiaddr/transforms.py +++ b/multiaddr/transforms.py @@ -172,4 +172,11 @@ def bytes_iter(buf: bytes) -> Generator[tuple[int, Protocol, CodecBase, bytes], ) from exc size = size_for_addr(codec, buf_io) - yield offset, proto, codec, buf_io.read(size) + part = buf_io.read(size) + if len(part) != size: + raise exceptions.BinaryParseError( + f"unexpected end of data for protocol {proto.name if proto else code}", + buf, + proto.name if proto else code, + ) + yield offset, proto, codec, part diff --git a/newsfragments/110.bugfix b/newsfragments/110.bugfix new file mode 100644 index 0000000..2e1ed17 --- /dev/null +++ b/newsfragments/110.bugfix @@ -0,0 +1 @@ +Add validation to Multiaddr initialization from bytes to reject invalid sequences immediately diff --git a/tests/test_multiaddr.py b/tests/test_multiaddr.py index da402e5..0a52f65 100644 --- a/tests/test_multiaddr.py +++ b/tests/test_multiaddr.py @@ -588,7 +588,19 @@ def test_bad_initialization_too_many_params(): def test_bad_initialization_wrong_type(): with pytest.raises(TypeError): - Multiaddr(42) # type: ignore + Multiaddr(1) # type: ignore + + +def test_invalid_bytes(): + from multiaddr.exceptions import BinaryParseError + + # These all should fail immediately when initializing from bytes: + with pytest.raises(BinaryParseError): + Multiaddr(b"\xff\xff\xff") # Invalid varint + with pytest.raises(BinaryParseError): + Multiaddr(b"\x99\x01\x00") # Unknown protocol code 0x99 + with pytest.raises(BinaryParseError): + Multiaddr(b"\x04\x04\x01\x02") # ip4 with only 3 bytes of address (needs 4) def test_value_for_protocol_argument_wrong_type():