Skip to content

bpo-37013: Fix the error handling in socket.if_indextoname() #13503

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

13 changes: 13 additions & 0 deletions Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,20 @@ def testInterfaceNameIndex(self):
'socket.if_indextoname() not available.')
def testInvalidInterfaceIndexToName(self):
self.assertRaises(OSError, socket.if_indextoname, 0)
self.assertRaises(OverflowError, socket.if_indextoname, -1)
self.assertRaises(OverflowError, socket.if_indextoname, 2**1000)
self.assertRaises(TypeError, socket.if_indextoname, '_DEADBEEF')
if hasattr(socket, 'if_nameindex'):
indices = dict(socket.if_nameindex())
for index in indices:
index2 = index + 2**32
if index2 not in indices:
with self.assertRaises((OverflowError, OSError)):
socket.if_indextoname(index2)
for index in 2**32-1, 2**64-1:
if index not in indices:
with self.assertRaises((OverflowError, OSError)):
socket.if_indextoname(index)

@unittest.skipUnless(hasattr(socket, 'if_nametoindex'),
'socket.if_nametoindex() not available.')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix a crash in :func:`socket.if_indextoname` with specific value (UINT_MAX).
Fix an integer overflow in :func:`socket.if_indextoname` on 64-bit
non-Windows platforms.
16 changes: 11 additions & 5 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -7071,17 +7071,23 @@ _socket_socket_if_nametoindex_impl(PySocketSockObject *self, PyObject *oname)
static PyObject *
socket_if_indextoname(PyObject *self, PyObject *arg)
{
unsigned long index_long = PyLong_AsUnsignedLong(arg);
if (index_long == (unsigned long) -1 && PyErr_Occurred()) {
return NULL;
}

#ifdef MS_WINDOWS
NET_IFINDEX index;
NET_IFINDEX index = (NET_IFINDEX)index_long;
#else
unsigned long index;
unsigned int index = (unsigned int)index_long;
#endif
char name[IF_NAMESIZE + 1];

index = PyLong_AsUnsignedLong(arg);
if (index == (unsigned long) -1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the main change is that it checks PyErr_Occurred() now.

if ((unsigned long)index != index_long) {
PyErr_SetString(PyExc_OverflowError, "index is too large");
return NULL;
}

char name[IF_NAMESIZE + 1];
if (if_indextoname(index, name) == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
Expand Down