gh-155336: Preserve resolver errors from gethostby*_r() (GH-155337)

serhiy-storchaka <[email protected]> Mon, 10 Aug 2026 03:35:06 -0400 (EDT)
Newsgroups gmane.comp.python.cvs
Message-ID <[email protected]>
https://github.com/python/cpython/commit/5181a6eca5de011cba15f8fc8fbffbeb3eec6db6
commit: 5181a6eca5de011cba15f8fc8fbffbeb3eec6db6
branch: main
author: Jakub KulĂ­k <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-10T07:34:51Z
summary:

gh-155336: Preserve resolver errors from gethostby*_r() (GH-155337)

files:
A Misc/NEWS.d/next/Library/2026-08-10-09-00-18.gh-issue-155336.vrTXoU.rst
M Modules/socketmodule.c

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 00000000000000..87f8a7f4a21e66
--- /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 73ae1c942daba4..f9c77c631b5d2a 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -6041,7 +6041,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;
@@ -6052,7 +6052,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;
     }
 
@@ -6188,6 +6188,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;
@@ -6199,7 +6200,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;
@@ -6218,14 +6218,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
@@ -6235,6 +6235,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
@@ -6243,7 +6244,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
     PyMutex_Unlock(&netdb_lock);
 #endif
@@ -6282,7 +6283,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;
@@ -6291,6 +6291,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;
@@ -6323,16 +6324,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
@@ -6342,9 +6341,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
     PyMutex_Unlock(&netdb_lock);
 #endif

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]