From 9ab84ccf402e7723e4a64e2574fb329fe9827ac3 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] [3.13] 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 d7e36c027405c8c..0968aafd327302a 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -5807,7 +5807,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; @@ -5818,7 +5818,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; } @@ -5954,6 +5954,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; @@ -5965,7 +5966,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; @@ -5984,14 +5984,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 @@ -5999,6 +5999,7 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) #endif SUPPRESS_DEPRECATED_CALL h = gethostbyname(name); + h_error = h_errno; #endif /* HAVE_GETHOSTBYNAME_R */ Py_END_ALLOW_THREADS /* Some C libraries would require addr.__ss_family instead of @@ -6007,7 +6008,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 @@ -6046,7 +6047,6 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) to maintain this alignment. */ char buf[16384] Py_ALIGNED(8); int buf_len = (sizeof buf) - 1; - int errnop; #endif #ifdef HAVE_GETHOSTBYNAME_R_3_ARG int result; @@ -6055,6 +6055,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; @@ -6087,16 +6088,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 @@ -6104,9 +6103,10 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) #endif SUPPRESS_DEPRECATED_CALL h = gethostbyaddr(ap, al, af); + 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