From 014cc92e0d8a1c5166be01796eb51b5b720c2ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Mon, 10 Aug 2026 09:34:51 +0200 Subject: [PATCH] gh-155336: Preserve resolver errors from gethostby*_r() (GH-155337) (cherry picked from commit 5181a6eca5de011cba15f8fc8fbffbeb3eec6db6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakub KulĂ­k --- ...-08-10-09-00-18.gh-issue-155336.vrTXoU.rst | 2 ++ Modules/socketmodule.c | 28 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-08-10-09-00-18.gh-issue-155336.vrTXoU.rst diff --git a/Misc/NEWS.d/next/Library/2026-08-10-09-00-18.gh-issue-155336.vrTXoU.rst b/Misc/NEWS.d/next/Library/2026-08-10-09-00-18.gh-issue-155336.vrTXoU.rst new file mode 100644 index 000000000000000..87f8a7f4a21e66d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-10-09-00-18.gh-issue-155336.vrTXoU.rst @@ -0,0 +1,2 @@ +Fix error handling in :func:`socket.gethostbyaddr` and +:func:`socket.gethostbyname_ex` when hostname resolution fails. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index fc870aaa5c1c2e4..698720e9c372a5d 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -6033,7 +6033,7 @@ sock_decode_hostname(const char *name) static PyObject * gethost_common(socket_state *state, struct hostent *h, struct sockaddr *addr, - size_t alen, int af) + size_t alen, int af, int h_error) { char **pch; PyObject *rtn_tuple = (PyObject *)NULL; @@ -6044,7 +6044,7 @@ gethost_common(socket_state *state, struct hostent *h, struct sockaddr *addr, if (h == NULL) { /* Let's get real error message to return */ - set_herror(state, h_errno); + set_herror(state, h_error); return NULL; } @@ -6180,6 +6180,7 @@ static PyObject * socket_gethostbyname_ex(PyObject *self, PyObject *args) { char *name; + int h_error; struct hostent *h; sock_addr_t addr; struct sockaddr *sa; @@ -6191,7 +6192,6 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) #else char buf[16384]; int buf_len = (sizeof buf) - 1; - int errnop; #endif #ifdef HAVE_GETHOSTBYNAME_R_3_ARG int result; @@ -6210,14 +6210,14 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_GETHOSTBYNAME_R #if defined(HAVE_GETHOSTBYNAME_R_6_ARG) - gethostbyname_r(name, &hp_allocated, buf, buf_len, - &h, &errnop); + gethostbyname_r(name, &hp_allocated, buf, buf_len, &h, &h_error); #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG) - h = gethostbyname_r(name, &hp_allocated, buf, buf_len, &errnop); + h = gethostbyname_r(name, &hp_allocated, buf, buf_len, &h_error); #else /* HAVE_GETHOSTBYNAME_R_3_ARG */ memset((void *) &data, '\0', sizeof(data)); result = gethostbyname_r(name, &hp_allocated, &data); h = (result != 0) ? NULL : &hp_allocated; + h_error = h_errno; #endif #else /* not HAVE_GETHOSTBYNAME_R */ #ifdef USE_GETHOSTBYNAME_LOCK @@ -6227,6 +6227,7 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) _Py_COMP_DIAG_IGNORE_DEPR_DECLS h = gethostbyname(name); _Py_COMP_DIAG_POP + h_error = h_errno; #endif /* HAVE_GETHOSTBYNAME_R */ Py_END_ALLOW_THREADS /* Some C libraries would require addr.__ss_family instead of @@ -6235,7 +6236,7 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) access sa_family. */ sa = SAS2SA(&addr); ret = gethost_common(state, h, SAS2SA(&addr), sizeof(addr), - sa->sa_family); + sa->sa_family, h_error); #ifdef USE_GETHOSTBYNAME_LOCK PyThread_release_lock(netdb_lock); #endif @@ -6274,7 +6275,6 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) to maintain this alignment. */ _Py_ALIGNED_DEF(8, char) buf[16384]; int buf_len = (sizeof buf) - 1; - int errnop; #endif #ifdef HAVE_GETHOSTBYNAME_R_3_ARG int result; @@ -6283,6 +6283,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) const char *ap; int al; int af; + int h_error; if (!PyArg_ParseTuple(args, "et:gethostbyaddr", "idna", &ip_num)) return NULL; @@ -6315,16 +6316,14 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_GETHOSTBYNAME_R #if defined(HAVE_GETHOSTBYNAME_R_6_ARG) - gethostbyaddr_r(ap, al, af, - &hp_allocated, buf, buf_len, - &h, &errnop); + gethostbyaddr_r(ap, al, af, &hp_allocated, buf, buf_len, &h, &h_error); #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG) - h = gethostbyaddr_r(ap, al, af, - &hp_allocated, buf, buf_len, &errnop); + h = gethostbyaddr_r(ap, al, af, &hp_allocated, buf, buf_len, &h_error); #else /* HAVE_GETHOSTBYNAME_R_3_ARG */ memset((void *) &data, '\0', sizeof(data)); result = gethostbyaddr_r(ap, al, af, &hp_allocated, &data); h = (result != 0) ? NULL : &hp_allocated; + h_error = h_errno; #endif #else /* not HAVE_GETHOSTBYNAME_R */ #ifdef USE_GETHOSTBYNAME_LOCK @@ -6334,9 +6333,10 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) _Py_COMP_DIAG_IGNORE_DEPR_DECLS h = gethostbyaddr(ap, al, af); _Py_COMP_DIAG_POP + h_error = h_errno; #endif /* HAVE_GETHOSTBYNAME_R */ Py_END_ALLOW_THREADS - ret = gethost_common(state, h, SAS2SA(&addr), sizeof(addr), af); + ret = gethost_common(state, h, SAS2SA(&addr), sizeof(addr), af, h_error); #ifdef USE_GETHOSTBYNAME_LOCK PyThread_release_lock(netdb_lock); #endif