Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

Commit ee60d5d

Browse files
[3.15] pythongh-160898: Reject null bytes in socket.getaddrinfo() host and port (pythonGH-160899)
(cherry picked from commit 131a3a6) Co-authored-by: Seth Larson <seth@python.org> Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent f4be2e5 commit ee60d5d

4 files changed

Lines changed: 57 additions & 3 deletions

File tree

‎Doc/library/socket.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,9 @@ The :mod:`!socket` module also offers various network-related services:
10651065
for IPv6 multicast addresses, string representing an address will not
10661066
contain ``%scope_id`` part.
10671067

1068+
.. versionchanged:: next
1069+
Null characters are now rejected in the *host* and *port* parameters.
1070+
10681071
.. _Happy Eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs
10691072

10701073
.. function:: getfqdn([name])

‎Lib/test/test_socket.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,39 @@ def test_getnameinfo_ipv6_scopeid_numeric(self):
20842084
nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV)
20852085
self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + str(ifindex), '1234'))
20862086

2087+
def test_getaddrinfo_null_bytes(self):
2088+
# getaddrinfo() must reject embedded null bytes instead of silently
2089+
# truncating the host or port at the C boundary. The checks run
2090+
# before any name resolution, so no network access is needed.
2091+
hosts = [
2092+
# embedded
2093+
'local\0host', b'local\0host',
2094+
# trailing
2095+
'localhost\0', b'localhost\0',
2096+
# leading (truncates to '')
2097+
'\0localhost', b'\0localhost',
2098+
'\0', b'\0',
2099+
# non-ASCII, goes through IDNA
2100+
'b\xfccher\0.example',
2101+
]
2102+
for host in hosts:
2103+
with self.subTest(host=host):
2104+
with self.assertRaisesRegex(ValueError, 'host'):
2105+
socket.getaddrinfo(host, 80)
2106+
2107+
ports = [
2108+
'8\x000',
2109+
b'8\x000',
2110+
'http\0',
2111+
b'http\0',
2112+
'\0',
2113+
b'\0'
2114+
]
2115+
for port in ports:
2116+
with self.subTest(port=port):
2117+
with self.assertRaisesRegex(ValueError, 'port'):
2118+
socket.getaddrinfo("localhost", port)
2119+
20872120
def test_str_for_enums(self):
20882121
# Make sure that the AF_* and SOCK_* constants have enum-like string
20892122
# reprs.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.. cve: CVE-2026-116566
2+
3+
:func:`socket.getaddrinfo` now rejects null bytes within *host* and *port*
4+
parameters as this previously caused the values to be silently truncated.

‎Modules/socketmodule.c‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6935,6 +6935,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
69356935
PyObject *pobj = (PyObject *)NULL;
69366936
PyObject *pstr = NULL;
69376937
const char *hptr, *pptr;
6938+
Py_ssize_t hlen = 0, plen = 0;
69386939
int family, socktype, protocol, flags;
69396940
int error;
69406941
PyObject *all = (PyObject *)NULL;
@@ -6955,13 +6956,20 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
69556956
return NULL;
69566957
assert(PyBytes_Check(idna));
69576958
hptr = PyBytes_AS_STRING(idna);
6959+
hlen = PyBytes_GET_SIZE(idna);
69586960
} else if (PyBytes_Check(hobj)) {
6959-
hptr = PyBytes_AsString(hobj);
6961+
hptr = PyBytes_AS_STRING(hobj);
6962+
hlen = PyBytes_GET_SIZE(hobj);
69606963
} else {
69616964
PyErr_SetString(PyExc_TypeError,
69626965
"getaddrinfo() argument 1 must be string or None");
69636966
return NULL;
69646967
}
6968+
if (hptr != NULL && strlen(hptr) != (size_t)hlen) {
6969+
PyErr_SetString(PyExc_ValueError,
6970+
"getaddrinfo() host must not contain null characters");
6971+
goto err;
6972+
}
69656973
if (PyIndex_Check(pobj)) {
69666974
pstr = PyNumber_Index(pobj);
69676975
if (pstr == NULL)
@@ -6971,21 +6979,27 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
69716979
if (pstr == NULL)
69726980
goto err;
69736981
assert(PyUnicode_Check(pstr));
6974-
pptr = PyUnicode_AsUTF8(pstr);
6982+
pptr = PyUnicode_AsUTF8AndSize(pstr, &plen);
69756983
if (pptr == NULL)
69766984
goto err;
69776985
} else if (PyUnicode_Check(pobj)) {
6978-
pptr = PyUnicode_AsUTF8(pobj);
6986+
pptr = PyUnicode_AsUTF8AndSize(pobj, &plen);
69796987
if (pptr == NULL)
69806988
goto err;
69816989
} else if (PyBytes_Check(pobj)) {
69826990
pptr = PyBytes_AS_STRING(pobj);
6991+
plen = PyBytes_GET_SIZE(pobj);
69836992
} else if (pobj == Py_None) {
69846993
pptr = (char *)NULL;
69856994
} else {
69866995
PyErr_SetString(PyExc_OSError, "Int or String expected");
69876996
goto err;
69886997
}
6998+
if (pptr != NULL && strlen(pptr) != (size_t)plen) {
6999+
PyErr_SetString(PyExc_ValueError,
7000+
"getaddrinfo() port must not contain null characters");
7001+
goto err;
7002+
}
69897003
#if defined(__APPLE__) && defined(AI_NUMERICSERV)
69907004
if ((flags & AI_NUMERICSERV) && (pptr == NULL || (pptr[0] == '0' && pptr[1] == 0))) {
69917005
/* On OSX up to at least OSX 10.8 getaddrinfo crashes

0 commit comments

Comments
 (0)