diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 61cf881f..345362fd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,6 +13,7 @@ jobs: test: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest, macos-latest] diff --git a/README.rst b/README.rst index fe6c000d..c279822e 100644 --- a/README.rst +++ b/README.rst @@ -109,7 +109,7 @@ To build uvloop, you'll need Python 3.8 or greater: .. code:: - $ python3.7 -m venv uvloop-dev + $ python3 -m venv uvloop-dev $ source uvloop-dev/bin/activate 3. Install development dependencies: diff --git a/setup.py b/setup.py index ba15af50..c369ac80 100644 --- a/setup.py +++ b/setup.py @@ -176,7 +176,11 @@ def build_libuv(self): cmd, cwd=LIBUV_BUILD_DIR, env=env, check=True) - j_flag = '-j{}'.format(os.cpu_count() or 1) + try: + njobs = len(os.sched_getaffinity(0)) + except AttributeError: + njobs = os.cpu_count() + j_flag = '-j{}'.format(njobs or 1) c_flag = "CFLAGS={}".format(env['CFLAGS']) subprocess.run( ['make', j_flag, c_flag], diff --git a/tests/test_dns.py b/tests/test_dns.py index f61b1e8a..66da026b 100644 --- a/tests/test_dns.py +++ b/tests/test_dns.py @@ -31,13 +31,13 @@ def _test_getaddrinfo(self, *args, _patch=False, **kwargs): a1 = patched_getaddrinfo(*args, **kwargs) else: a1 = socket.getaddrinfo(*args, **kwargs) - except socket.gaierror as ex: + except (socket.gaierror, UnicodeError) as ex: err = ex try: a2 = self.loop.run_until_complete( self.loop.getaddrinfo(*args, **kwargs)) - except socket.gaierror as ex: + except (socket.gaierror, UnicodeError) as ex: if err is not None: self.assertEqual(ex.args, err.args) else: @@ -187,6 +187,18 @@ def test_getaddrinfo_20(self): self._test_getaddrinfo('127.0.0.1', 80, type=socket.SOCK_STREAM, flags=socket.AI_CANONNAME, _patch=patch) + # https://github.com/libuv/libuv/security/advisories/GHSA-f74f-cvh7-c6q6 + # See also: https://github.com/MagicStack/uvloop/pull/600 + def test_getaddrinfo_21(self): + payload = f'0x{"0" * 246}7f000001.example.com'.encode('ascii') + self._test_getaddrinfo(payload, 80) + self._test_getaddrinfo(payload, 80, type=socket.SOCK_STREAM) + + def test_getaddrinfo_22(self): + payload = f'0x{"0" * 246}7f000001.example.com' + self._test_getaddrinfo(payload, 80) + self._test_getaddrinfo(payload, 80, type=socket.SOCK_STREAM) + ###### def test_getnameinfo_1(self): diff --git a/tests/test_tcp.py b/tests/test_tcp.py index 812e62b8..d7a73fbf 100644 --- a/tests/test_tcp.py +++ b/tests/test_tcp.py @@ -248,8 +248,9 @@ def test_create_server_4(self): addr = sock.getsockname() with self.assertRaisesRegex(OSError, - r"error while attempting.*\('127.*: " - r"address( already)? in use"): + r"error while attempting.*\('127.*:" + r"( \[errno \d+\])? address" + r"( already)? in use"): self.loop.run_until_complete( self.loop.create_server(object, *addr)) diff --git a/uvloop/dns.pyx b/uvloop/dns.pyx index 7aad6319..c6be7cbe 100644 --- a/uvloop/dns.pyx +++ b/uvloop/dns.pyx @@ -348,6 +348,11 @@ cdef class AddrInfoRequest(UVRequest): if host is None: chost = NULL + elif host == b'' and sys.platform == 'darwin': + # It seems `getaddrinfo("", ...)` on macOS is equivalent to + # `getaddrinfo("localhost", ...)`. This is inconsistent with + # libuv 1.48 which treats empty nodename as EINVAL. + chost = 'localhost' else: chost = host @@ -356,13 +361,6 @@ cdef class AddrInfoRequest(UVRequest): else: cport = port - if cport is NULL and chost is NULL: - self.on_done() - msg = system.gai_strerror(socket_EAI_NONAME).decode('utf-8') - ex = socket_gaierror(socket_EAI_NONAME, msg) - callback(ex) - return - memset(&self.hints, 0, sizeof(system.addrinfo)) self.hints.ai_flags = flags self.hints.ai_family = family @@ -382,7 +380,17 @@ cdef class AddrInfoRequest(UVRequest): if err < 0: self.on_done() - callback(convert_error(err)) + try: + if err == uv.UV_EINVAL: + # Convert UV_EINVAL to EAI_NONAME to match libc behavior + msg = system.gai_strerror(socket_EAI_NONAME).decode('utf-8') + ex = socket_gaierror(socket_EAI_NONAME, msg) + else: + ex = convert_error(err) + except Exception as ex: + callback(ex) + else: + callback(ex) cdef class NameInfoRequest(UVRequest): diff --git a/vendor/libuv b/vendor/libuv index f0bb7e40..e9f29cb9 160000 --- a/vendor/libuv +++ b/vendor/libuv @@ -1 +1 @@ -Subproject commit f0bb7e40f0508bedf6fad33769b3f87bb8aedfa6 +Subproject commit e9f29cb984231524e3931aa0ae2c5dae1a32884e