From 65fcaa38ada727b504ec60ae283caf8e3ebbb845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 9 Sep 2024 16:59:13 +0200 Subject: [PATCH] gh-84808: socket.connect_ex: Handle negative errno (GH-122304) POSIX allows errno to be negative. Even though all currently supported platforms have non-negative errno, relying on a quirk like that would make Python less portable. --- ...4-09-06-10-17-54.gh-issue-84808.ION67Z.rst | 3 +++ Modules/socketmodule.c | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-09-06-10-17-54.gh-issue-84808.ION67Z.rst diff --git a/Misc/NEWS.d/next/Library/2024-09-06-10-17-54.gh-issue-84808.ION67Z.rst b/Misc/NEWS.d/next/Library/2024-09-06-10-17-54.gh-issue-84808.ION67Z.rst new file mode 100644 index 00000000000..c804c597424 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-06-10-17-54.gh-issue-84808.ION67Z.rst @@ -0,0 +1,3 @@ +Fix error handling in :py:class:`~socket.socket` method +:py:func:`~socket.socket.connect_ex` on platforms where +:c:data:`errno` can be negative. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 77e09659514..ded6f255aad 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3421,6 +3421,18 @@ sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data)) return 1; } +/* Common functionality for socket.connect and socket.connect_ex. + * + * If *raise* is set: + * - On success, return 0. + * - On any failure, return -1 with an exception set. + * If *raise* is zero: + * - On success, return 0. + * - On connect() failure, return errno (without an exception set) + * - On other error, return -1 with an exception set. + * + * Note that -1 is a valid errno value on some systems. + */ static int internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, int raise) @@ -3505,8 +3517,10 @@ sock_connect(PySocketSockObject *s, PyObject *addro) } res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); - if (res < 0) + if (res < 0) { + assert(PyErr_Occurred()); return NULL; + } Py_RETURN_NONE; } @@ -3536,8 +3550,9 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro) } res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0); - if (res < 0) + if (res == -1 && PyErr_Occurred()) { return NULL; + } return PyLong_FromLong((long) res); }