From a1c3c8ff93310c0642f8490f053324bd17a5a9d1 Mon Sep 17 00:00:00 2001 From: Pitchfork-and-Torch Date: Fri, 18 Sep 2026 03:34:10 +0000 Subject: [PATCH] fix: reject bool/non-int port on URL construction isinstance(True, int) is True, so port=True was stored and bytes(url) silently became host:1. Reject bool and other non-int ports with TypeError. --- httpcore/_models.py | 4 ++++ tests/test_models.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/httpcore/_models.py b/httpcore/_models.py index 8a65f1334..d63ba4ee4 100644 --- a/httpcore/_models.py +++ b/httpcore/_models.py @@ -275,6 +275,10 @@ def __init__( else: self.scheme = enforce_bytes(scheme, name="scheme") self.host = enforce_bytes(host, name="host") + # bool is a subclass of int; reject it so port=True does not become 1. + if port is not None and (isinstance(port, bool) or not isinstance(port, int)): + seen = type(port).__name__ + raise TypeError(f"port must be int or None, but got {seen}.") self.port = port self.target = enforce_bytes(target, name="target") diff --git a/tests/test_models.py b/tests/test_models.py index 7dd6e419d..d63f55445 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -187,3 +187,19 @@ async def test_response_async_streaming(): with pytest.raises(RuntimeError): async for chunk in response.aiter_stream(): pass # pragma: nocover + + +def test_url_rejects_bool_port(): + # isinstance(True, int) is True; without an explicit check, port=True + # becomes port 1 in bytes(url) ("http://host:1/"). + with pytest.raises(TypeError, match="port must be int or None"): + httpcore.URL(scheme=b"http", host=b"www.example.com", port=True, target=b"/") + with pytest.raises(TypeError, match="port must be int or None"): + httpcore.URL(scheme=b"http", host=b"www.example.com", port=False, target=b"/") + + +def test_url_rejects_non_int_port(): + with pytest.raises(TypeError, match="port must be int or None"): + httpcore.URL(scheme=b"http", host=b"www.example.com", port=1.5, target=b"/") # type: ignore + with pytest.raises(TypeError, match="port must be int or None"): + httpcore.URL(scheme=b"http", host=b"www.example.com", port="80", target=b"/") # type: ignore