https://github.com/python/cpython/commit/9622dec7c83e634630fbdde1486e78d69cc0fbe5
commit: 9622dec7c83e634630fbdde1486e78d69cc0fbe5
branch: 3.13
author: Jakub KulĂk <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-11T08:43:39Z
summary:
[3.13] gh-155336: Preserve resolver errors from gethostby*_r() (GH-155337)
(GH-155473)
(cherry picked from commit 5181a6eca5de011cba15f8fc8fbffbeb3eec6db6)
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 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
_______________________________________________
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]