Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 928752c

Browse filesBrowse files
authored
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.
1 parent 0c6fe81 commit 928752c
Copy full SHA for 928752c

File tree

5 files changed

+68
-6
lines changed
Filter options

5 files changed

+68
-6
lines changed

‎Lib/test/test_socket.py

Copy file name to clipboardExpand all lines: Lib/test/test_socket.py
+48Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,54 @@ def testGetaddrinfo(self):
16001600
except socket.gaierror:
16011601
pass
16021602

1603+
def test_getaddrinfo_int_port_overflow(self):
1604+
# gh-74895: Test that getaddrinfo does not raise OverflowError on port.
1605+
#
1606+
# POSIX getaddrinfo() never specify the valid range for "service"
1607+
# decimal port number values. For IPv4 and IPv6 they are technically
1608+
# unsigned 16-bit values, but the API is protocol agnostic. Which values
1609+
# trigger an error from the C library function varies by platform as
1610+
# they do not all perform validation.
1611+
1612+
# The key here is that we don't want to produce OverflowError as Python
1613+
# prior to 3.12 did for ints outside of a [LONG_MIN, LONG_MAX] range.
1614+
# Leave the error up to the underlying string based platform C API.
1615+
1616+
from _testcapi import ULONG_MAX, LONG_MAX, LONG_MIN
1617+
try:
1618+
socket.getaddrinfo(None, ULONG_MAX + 1)
1619+
except OverflowError:
1620+
# Platforms differ as to what values consitute a getaddrinfo() error
1621+
# return. Some fail for LONG_MAX+1, others ULONG_MAX+1, and Windows
1622+
# silently accepts such huge "port" aka "service" numeric values.
1623+
self.fail("Either no error or socket.gaierror expected.")
1624+
except socket.gaierror:
1625+
pass
1626+
1627+
try:
1628+
socket.getaddrinfo(None, LONG_MAX + 1)
1629+
except OverflowError:
1630+
self.fail("Either no error or socket.gaierror expected.")
1631+
except socket.gaierror:
1632+
pass
1633+
1634+
try:
1635+
socket.getaddrinfo(None, LONG_MAX - 0xffff + 1)
1636+
except OverflowError:
1637+
self.fail("Either no error or socket.gaierror expected.")
1638+
except socket.gaierror:
1639+
pass
1640+
1641+
try:
1642+
socket.getaddrinfo(None, LONG_MIN - 1)
1643+
except OverflowError:
1644+
self.fail("Either no error or socket.gaierror expected.")
1645+
except socket.gaierror:
1646+
pass
1647+
1648+
socket.getaddrinfo(None, 0) # No error expected.
1649+
socket.getaddrinfo(None, 0xffff) # No error expected.
1650+
16031651
def test_getnameinfo(self):
16041652
# only IP addresses are allowed
16051653
self.assertRaises(OSError, socket.getnameinfo, ('mail.python.org',0), 0)

‎Misc/ACKS

Copy file name to clipboardExpand all lines: Misc/ACKS
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,7 @@ Roman Skurikhin
16881688
Ville Skyttä
16891689
Michael Sloan
16901690
Nick Sloan
1691+
Radek Smejkal
16911692
Václav Šmilauer
16921693
Casper W. Smet
16931694
Allen W. Smith
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:mod:`socket.getaddrinfo` no longer raises :class:`OverflowError` for
2+
:class:`int` **port** values outside of the C long range. Out of range values
3+
are left up to the underlying string based C library API to report. A
4+
:class:`socket.gaierror` ``SAI_SERVICE`` may occur instead, or no error at all
5+
as not all platform C libraries generate an error.

‎Modules/getaddrinfo.c

Copy file name to clipboardExpand all lines: Modules/getaddrinfo.c
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,11 @@ getaddrinfo(const char*hostname, const char*servname,
342342
pai->ai_socktype = SOCK_DGRAM;
343343
pai->ai_protocol = IPPROTO_UDP;
344344
}
345-
port = htons((u_short)atoi(servname));
345+
long maybe_port = strtol(servname, NULL, 10);
346+
if (maybe_port < 0 || maybe_port > 0xffff) {
347+
ERR(EAI_SERVICE);
348+
}
349+
port = htons((u_short)maybe_port);
346350
} else {
347351
struct servent *sp;
348352
const char *proto;

‎Modules/socketmodule.c

Copy file name to clipboardExpand all lines: Modules/socketmodule.c
+9-5Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6650,7 +6650,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
66506650
struct addrinfo *res0 = NULL;
66516651
PyObject *hobj = NULL;
66526652
PyObject *pobj = (PyObject *)NULL;
6653-
char pbuf[30];
6653+
PyObject *pstr = NULL;
66546654
const char *hptr, *pptr;
66556655
int family, socktype, protocol, flags;
66566656
int error;
@@ -6680,11 +6680,13 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
66806680
return NULL;
66816681
}
66826682
if (PyLong_CheckExact(pobj)) {
6683-
long value = PyLong_AsLong(pobj);
6684-
if (value == -1 && PyErr_Occurred())
6683+
pstr = PyObject_Str(pobj);
6684+
if (pstr == NULL)
6685+
goto err;
6686+
assert(PyUnicode_Check(pstr));
6687+
pptr = PyUnicode_AsUTF8(pstr);
6688+
if (pptr == NULL)
66856689
goto err;
6686-
PyOS_snprintf(pbuf, sizeof(pbuf), "%ld", value);
6687-
pptr = pbuf;
66886690
} else if (PyUnicode_Check(pobj)) {
66896691
pptr = PyUnicode_AsUTF8(pobj);
66906692
if (pptr == NULL)
@@ -6750,12 +6752,14 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs)
67506752
Py_DECREF(single);
67516753
}
67526754
Py_XDECREF(idna);
6755+
Py_XDECREF(pstr);
67536756
if (res0)
67546757
freeaddrinfo(res0);
67556758
return all;
67566759
err:
67576760
Py_XDECREF(all);
67586761
Py_XDECREF(idna);
6762+
Py_XDECREF(pstr);
67596763
if (res0)
67606764
freeaddrinfo(res0);
67616765
return (PyObject *)NULL;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.