mirror of https://github.com/python/cpython
gh-74895: getaddrinfo no longer raises OverflowError (#2435)
`socket.getaddrinfo()` no longer raises `OverflowError` based on the **port** argument. Error reporting (or not) for its value is left up to the underlying C library `getaddrinfo()` implementation.
This commit is contained in:
parent
0c6fe81dce
commit
928752ce4c
|
@ -1600,6 +1600,54 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_getaddrinfo_int_port_overflow(self):
|
||||||
|
# gh-74895: Test that getaddrinfo does not raise OverflowError on port.
|
||||||
|
#
|
||||||
|
# POSIX getaddrinfo() never specify the valid range for "service"
|
||||||
|
# decimal port number values. For IPv4 and IPv6 they are technically
|
||||||
|
# unsigned 16-bit values, but the API is protocol agnostic. Which values
|
||||||
|
# trigger an error from the C library function varies by platform as
|
||||||
|
# they do not all perform validation.
|
||||||
|
|
||||||
|
# The key here is that we don't want to produce OverflowError as Python
|
||||||
|
# prior to 3.12 did for ints outside of a [LONG_MIN, LONG_MAX] range.
|
||||||
|
# Leave the error up to the underlying string based platform C API.
|
||||||
|
|
||||||
|
from _testcapi import ULONG_MAX, LONG_MAX, LONG_MIN
|
||||||
|
try:
|
||||||
|
socket.getaddrinfo(None, ULONG_MAX + 1)
|
||||||
|
except OverflowError:
|
||||||
|
# Platforms differ as to what values consitute a getaddrinfo() error
|
||||||
|
# return. Some fail for LONG_MAX+1, others ULONG_MAX+1, and Windows
|
||||||
|
# silently accepts such huge "port" aka "service" numeric values.
|
||||||
|
self.fail("Either no error or socket.gaierror expected.")
|
||||||
|
except socket.gaierror:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
socket.getaddrinfo(None, LONG_MAX + 1)
|
||||||
|
except OverflowError:
|
||||||
|
self.fail("Either no error or socket.gaierror expected.")
|
||||||
|
except socket.gaierror:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
socket.getaddrinfo(None, LONG_MAX - 0xffff + 1)
|
||||||
|
except OverflowError:
|
||||||
|
self.fail("Either no error or socket.gaierror expected.")
|
||||||
|
except socket.gaierror:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
socket.getaddrinfo(None, LONG_MIN - 1)
|
||||||
|
except OverflowError:
|
||||||
|
self.fail("Either no error or socket.gaierror expected.")
|
||||||
|
except socket.gaierror:
|
||||||
|
pass
|
||||||
|
|
||||||
|
socket.getaddrinfo(None, 0) # No error expected.
|
||||||
|
socket.getaddrinfo(None, 0xffff) # No error expected.
|
||||||
|
|
||||||
def test_getnameinfo(self):
|
def test_getnameinfo(self):
|
||||||
# only IP addresses are allowed
|
# only IP addresses are allowed
|
||||||
self.assertRaises(OSError, socket.getnameinfo, ('mail.python.org',0), 0)
|
self.assertRaises(OSError, socket.getnameinfo, ('mail.python.org',0), 0)
|
||||||
|
|
|
@ -1688,6 +1688,7 @@ Roman Skurikhin
|
||||||
Ville Skyttä
|
Ville Skyttä
|
||||||
Michael Sloan
|
Michael Sloan
|
||||||
Nick Sloan
|
Nick Sloan
|
||||||
|
Radek Smejkal
|
||||||
Václav Šmilauer
|
Václav Šmilauer
|
||||||
Casper W. Smet
|
Casper W. Smet
|
||||||
Allen W. Smith
|
Allen W. Smith
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
:mod:`socket.getaddrinfo` no longer raises :class:`OverflowError` for
|
||||||
|
:class:`int` **port** values outside of the C long range. Out of range values
|
||||||
|
are left up to the underlying string based C library API to report. A
|
||||||
|
:class:`socket.gaierror` ``SAI_SERVICE`` may occur instead, or no error at all
|
||||||
|
as not all platform C libraries generate an error.
|
|
@ -342,7 +342,11 @@ getaddrinfo(const char*hostname, const char*servname,
|
||||||
pai->ai_socktype = SOCK_DGRAM;
|
pai->ai_socktype = SOCK_DGRAM;
|
||||||
pai->ai_protocol = IPPROTO_UDP;
|
pai->ai_protocol = IPPROTO_UDP;
|
||||||
}
|
}
|
||||||
port = htons((u_short)atoi(servname));
|
long maybe_port = strtol(servname, NULL, 10);
|
||||||
|
if (maybe_port < 0 || maybe_port > 0xffff) {
|
||||||
|
ERR(EAI_SERVICE);
|
||||||
|
}
|
||||||
|
port = htons((u_short)maybe_port);
|
||||||
} else {
|
} else {
|
||||||
struct servent *sp;
|
struct servent *sp;
|
||||||
const char *proto;
|
const char *proto;
|
||||||
|
|
|
@ -6650,7 +6650,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
|
||||||
struct addrinfo *res0 = NULL;
|
struct addrinfo *res0 = NULL;
|
||||||
PyObject *hobj = NULL;
|
PyObject *hobj = NULL;
|
||||||
PyObject *pobj = (PyObject *)NULL;
|
PyObject *pobj = (PyObject *)NULL;
|
||||||
char pbuf[30];
|
PyObject *pstr = NULL;
|
||||||
const char *hptr, *pptr;
|
const char *hptr, *pptr;
|
||||||
int family, socktype, protocol, flags;
|
int family, socktype, protocol, flags;
|
||||||
int error;
|
int error;
|
||||||
|
@ -6680,11 +6680,13 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (PyLong_CheckExact(pobj)) {
|
if (PyLong_CheckExact(pobj)) {
|
||||||
long value = PyLong_AsLong(pobj);
|
pstr = PyObject_Str(pobj);
|
||||||
if (value == -1 && PyErr_Occurred())
|
if (pstr == NULL)
|
||||||
|
goto err;
|
||||||
|
assert(PyUnicode_Check(pstr));
|
||||||
|
pptr = PyUnicode_AsUTF8(pstr);
|
||||||
|
if (pptr == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value);
|
|
||||||
pptr = pbuf;
|
|
||||||
} else if (PyUnicode_Check(pobj)) {
|
} else if (PyUnicode_Check(pobj)) {
|
||||||
pptr = PyUnicode_AsUTF8(pobj);
|
pptr = PyUnicode_AsUTF8(pobj);
|
||||||
if (pptr == NULL)
|
if (pptr == NULL)
|
||||||
|
@ -6750,12 +6752,14 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
|
||||||
Py_DECREF(single);
|
Py_DECREF(single);
|
||||||
}
|
}
|
||||||
Py_XDECREF(idna);
|
Py_XDECREF(idna);
|
||||||
|
Py_XDECREF(pstr);
|
||||||
if (res0)
|
if (res0)
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
return all;
|
return all;
|
||||||
err:
|
err:
|
||||||
Py_XDECREF(all);
|
Py_XDECREF(all);
|
||||||
Py_XDECREF(idna);
|
Py_XDECREF(idna);
|
||||||
|
Py_XDECREF(pstr);
|
||||||
if (res0)
|
if (res0)
|
||||||
freeaddrinfo(res0);
|
freeaddrinfo(res0);
|
||||||
return (PyObject *)NULL;
|
return (PyObject *)NULL;
|
||||||
|
|
Loading…
Reference in New Issue