Skip to content

bpo-42393: Raise OverflowError iso. DeprecationWarning on overflow in socket.ntohs and socket.htons #23980

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions Doc/library/socket.rst
Original file line number Diff line number Diff line change
Expand Up @@ -907,11 +907,9 @@ The :mod:`socket` module also offers various network-related services:
where the host byte order is the same as network byte order, this is a no-op;
otherwise, it performs a 2-byte swap operation.

.. deprecated:: 3.7
In case *x* does not fit in 16-bit unsigned integer, but does fit in a
positive C int, it is silently truncated to 16-bit unsigned integer.
This silent truncation feature is deprecated, and will raise an
exception in future versions of Python.
.. versionchanged:: 3.10
Raises :exc:`OverflowError` if *x* does not fit in a 16-bit unsigned
integer.


.. function:: htonl(x)
Expand All @@ -927,11 +925,9 @@ The :mod:`socket` module also offers various network-related services:
where the host byte order is the same as network byte order, this is a no-op;
otherwise, it performs a 2-byte swap operation.

.. deprecated:: 3.7
In case *x* does not fit in 16-bit unsigned integer, but does fit in a
positive C int, it is silently truncated to 16-bit unsigned integer.
This silent truncation feature is deprecated, and will raise an
exception in future versions of Python.
.. versionchanged:: 3.10
Raises :exc:`OverflowError` if *x* does not fit in a 16-bit unsigned
integer.


.. function:: inet_aton(ip_string)
Expand Down
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,12 @@ Changes in the Python API
silently in Python 3.9.
(Contributed by Ken Jin in :issue:`42195`.)

* :meth:`socket.htons` and :meth:`socket.ntohs` now raise :exc:`OverflowError`
instead of :exc:`DeprecationWarning` if the given parameter will not fit in
a 16-bit unsigned integer.
(Contributed by Erlend E. Aasland in :issue:`42393`.)


CPython bytecode changes
========================

Expand Down
11 changes: 5 additions & 6 deletions Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1121,9 +1121,11 @@ def testNtoHErrors(self):
s_good_values = [0, 1, 2, 0xffff]
l_good_values = s_good_values + [0xffffffff]
l_bad_values = [-1, -2, 1<<32, 1<<1000]
s_bad_values = l_bad_values + [_testcapi.INT_MIN - 1,
_testcapi.INT_MAX + 1]
s_deprecated_values = [1<<16, _testcapi.INT_MAX]
s_bad_values = (
l_bad_values +
[_testcapi.INT_MIN-1, _testcapi.INT_MAX+1] +
[1 << 16, _testcapi.INT_MAX]
)
for k in s_good_values:
socket.ntohs(k)
socket.htons(k)
Expand All @@ -1136,9 +1138,6 @@ def testNtoHErrors(self):
for k in l_bad_values:
self.assertRaises(OverflowError, socket.ntohl, k)
self.assertRaises(OverflowError, socket.htonl, k)
for k in s_deprecated_values:
self.assertWarns(DeprecationWarning, socket.ntohs, k)
self.assertWarns(DeprecationWarning, socket.htons, k)

def testGetServBy(self):
eq = self.assertEqual
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Raise :exc:`OverflowError` instead of silent truncation in :meth:`socket.ntohs`
and :meth:`socket.htons`. Silent truncation was deprecated in Python 3.7.
Patch by Erlend E. Aasland
36 changes: 10 additions & 26 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6102,26 +6102,18 @@ socket_ntohs(PyObject *self, PyObject *args)
return NULL;
}
if (x > 0xffff) {
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"ntohs: Python int too large to convert to C "
"16-bit unsigned integer (The silent truncation "
"is deprecated)",
1)) {
return NULL;
}
PyErr_SetString(PyExc_OverflowError,
"ntohs: Python int too large to convert to C "
"16-bit unsigned integer");
return NULL;
}
return PyLong_FromUnsignedLong(ntohs((unsigned short)x));
}

PyDoc_STRVAR(ntohs_doc,
"ntohs(integer) -> integer\n\
\n\
Convert a 16-bit unsigned integer from network to host byte order.\n\
Note that in case the received integer does not fit in 16-bit unsigned\n\
integer, but does fit in a positive C int, it is silently truncated to\n\
16-bit unsigned integer.\n\
However, this silent truncation feature is deprecated, and will raise an\n\
exception in future versions of Python.");
Convert a 16-bit unsigned integer from network to host byte order.");


static PyObject *
Expand Down Expand Up @@ -6173,26 +6165,18 @@ socket_htons(PyObject *self, PyObject *args)
return NULL;
}
if (x > 0xffff) {
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"htons: Python int too large to convert to C "
"16-bit unsigned integer (The silent truncation "
"is deprecated)",
1)) {
return NULL;
}
PyErr_SetString(PyExc_OverflowError,
"htons: Python int too large to convert to C "
"16-bit unsigned integer");
return NULL;
}
return PyLong_FromUnsignedLong(htons((unsigned short)x));
}

PyDoc_STRVAR(htons_doc,
"htons(integer) -> integer\n\
\n\
Convert a 16-bit unsigned integer from host to network byte order.\n\
Note that in case the received integer does not fit in 16-bit unsigned\n\
integer, but does fit in a positive C int, it is silently truncated to\n\
16-bit unsigned integer.\n\
However, this silent truncation feature is deprecated, and will raise an\n\
exception in future versions of Python.");
Convert a 16-bit unsigned integer from host to network byte order.");


static PyObject *
Expand Down