diff --git a/src/hyperlink/_url.py b/src/hyperlink/_url.py index 8797b5c..ff69aa5 100644 --- a/src/hyperlink/_url.py +++ b/src/hyperlink/_url.py @@ -1035,6 +1035,8 @@ def __init__( ) self._fragment = _textcheck("fragment", fragment) self._port = _typecheck("port", port, int, NoneType) + if self._port is not None and not (0 <= self._port <= 65535): + raise ValueError("port must be in range 0-65535, not %r" % (self._port,)) self._rooted = _typecheck("rooted", rooted, bool) self._userinfo = _textcheck("userinfo", userinfo, "/?#@") @@ -1413,6 +1415,10 @@ def from_text(cls, text): if not port: # TODO: excessive? raise URLParseError("port must not be empty: %r" % au_text) raise URLParseError("expected integer for port, not %r" % port) + if not (0 <= port <= 65535): + raise URLParseError( + "port must be in range 0-65535, not %r" % (port,) + ) scheme = gs["scheme"] or u"" fragment = gs["fragment"] or u"" diff --git a/src/hyperlink/test/test_url.py b/src/hyperlink/test/test_url.py index 37c9172..7ea1517 100644 --- a/src/hyperlink/test/test_url.py +++ b/src/hyperlink/test/test_url.py @@ -1493,3 +1493,25 @@ def test_idna_corners(self): assert ( URL.from_text(text).to_uri().get_decoded_url().host == "example.com" ) + + +class OutOfRangePortTests(HyperlinkTestCase): + def test_from_text_rejects_out_of_range_port(self): + from hyperlink import URL, URLParseError + for bad in ("http://ex.com:-1", "http://ex.com:65536", "http://ex.com:99999"): + try: + URL.from_text(bad) + except URLParseError: + pass + else: + raise AssertionError("expected URLParseError for %r" % (bad,)) + + def test_ctor_rejects_out_of_range_port(self): + from hyperlink import URL + for bad in (-1, 65536, 99999): + try: + URL(scheme=u"http", host=u"ex.com", port=bad) + except ValueError: + pass + else: + raise AssertionError("expected ValueError for port %r" % (bad,))