bpo-35415: validate fileno argument to socket.socket (GH-10917)
https://bugs.python.org/issue35415
This commit is contained in:
parent
05c1b387f1
commit
e991270363
|
@ -1700,7 +1700,6 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
s.setblocking(False)
|
s.setblocking(False)
|
||||||
self.assertEqual(s.type, socket.SOCK_STREAM)
|
self.assertEqual(s.type, socket.SOCK_STREAM)
|
||||||
|
|
||||||
@unittest.skipIf(os.name == 'nt', 'Will not work on Windows')
|
|
||||||
def test_unknown_socket_family_repr(self):
|
def test_unknown_socket_family_repr(self):
|
||||||
# Test that when created with a family that's not one of the known
|
# Test that when created with a family that's not one of the known
|
||||||
# AF_*/SOCK_* constants, socket.family just returns the number.
|
# AF_*/SOCK_* constants, socket.family just returns the number.
|
||||||
|
@ -1708,10 +1707,8 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
# To do this we fool socket.socket into believing it already has an
|
# To do this we fool socket.socket into believing it already has an
|
||||||
# open fd because on this path it doesn't actually verify the family and
|
# open fd because on this path it doesn't actually verify the family and
|
||||||
# type and populates the socket object.
|
# type and populates the socket object.
|
||||||
#
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
# On Windows this trick won't work, so the test is skipped.
|
fd = sock.detach()
|
||||||
fd, path = tempfile.mkstemp()
|
|
||||||
self.addCleanup(os.unlink, path)
|
|
||||||
unknown_family = max(socket.AddressFamily.__members__.values()) + 1
|
unknown_family = max(socket.AddressFamily.__members__.values()) + 1
|
||||||
|
|
||||||
unknown_type = max(
|
unknown_type = max(
|
||||||
|
@ -1785,6 +1782,48 @@ class GeneralModuleTests(unittest.TestCase):
|
||||||
s.bind(os.path.join(tmpdir, 'socket'))
|
s.bind(os.path.join(tmpdir, 'socket'))
|
||||||
self._test_socket_fileno(s, socket.AF_UNIX, socket.SOCK_STREAM)
|
self._test_socket_fileno(s, socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
def test_socket_fileno_rejects_float(self):
|
||||||
|
with self.assertRaisesRegex(TypeError, "integer argument expected"):
|
||||||
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=42.5)
|
||||||
|
|
||||||
|
def test_socket_fileno_rejects_other_types(self):
|
||||||
|
with self.assertRaisesRegex(TypeError, "integer is required"):
|
||||||
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno="foo")
|
||||||
|
|
||||||
|
def test_socket_fileno_rejects_invalid_socket(self):
|
||||||
|
with self.assertRaisesRegex(ValueError, "negative file descriptor"):
|
||||||
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=-1)
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == "nt", "Windows disallows -1 only")
|
||||||
|
def test_socket_fileno_rejects_negative(self):
|
||||||
|
with self.assertRaisesRegex(ValueError, "negative file descriptor"):
|
||||||
|
socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=-42)
|
||||||
|
|
||||||
|
def test_socket_fileno_requires_valid_fd(self):
|
||||||
|
WSAENOTSOCK = 10038
|
||||||
|
with self.assertRaises(OSError) as cm:
|
||||||
|
socket.socket(fileno=support.make_bad_fd())
|
||||||
|
self.assertIn(cm.exception.errno, (errno.EBADF, WSAENOTSOCK))
|
||||||
|
|
||||||
|
with self.assertRaises(OSError) as cm:
|
||||||
|
socket.socket(
|
||||||
|
socket.AF_INET,
|
||||||
|
socket.SOCK_STREAM,
|
||||||
|
fileno=support.make_bad_fd())
|
||||||
|
self.assertIn(cm.exception.errno, (errno.EBADF, WSAENOTSOCK))
|
||||||
|
|
||||||
|
def test_socket_fileno_requires_socket_fd(self):
|
||||||
|
with tempfile.NamedTemporaryFile() as afile:
|
||||||
|
with self.assertRaises(OSError):
|
||||||
|
socket.socket(fileno=afile.fileno())
|
||||||
|
|
||||||
|
with self.assertRaises(OSError) as cm:
|
||||||
|
socket.socket(
|
||||||
|
socket.AF_INET,
|
||||||
|
socket.SOCK_STREAM,
|
||||||
|
fileno=afile.fileno())
|
||||||
|
self.assertEqual(cm.exception.errno, errno.ENOTSOCK)
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
|
@unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.')
|
||||||
class BasicCANTest(unittest.TestCase):
|
class BasicCANTest(unittest.TestCase):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Validate fileno= argument to socket.socket().
|
|
@ -5018,28 +5018,45 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
fd = PyLong_AsSocket_t(fdobj);
|
|
||||||
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
|
if (PyFloat_Check(fdobj)) {
|
||||||
return -1;
|
PyErr_SetString(PyExc_TypeError,
|
||||||
if (fd == INVALID_SOCKET) {
|
"integer argument expected, got float");
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"can't use invalid socket value");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family == -1) {
|
fd = PyLong_AsSocket_t(fdobj);
|
||||||
|
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
|
||||||
|
return -1;
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
if (fd == INVALID_SOCKET) {
|
||||||
|
#else
|
||||||
|
if (fd < 0) {
|
||||||
|
#endif
|
||||||
|
PyErr_SetString(PyExc_ValueError, "negative file descriptor");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* validate that passed file descriptor is valid and a socket. */
|
||||||
sock_addr_t addrbuf;
|
sock_addr_t addrbuf;
|
||||||
socklen_t addrlen = sizeof(sock_addr_t);
|
socklen_t addrlen = sizeof(sock_addr_t);
|
||||||
|
|
||||||
memset(&addrbuf, 0, addrlen);
|
memset(&addrbuf, 0, addrlen);
|
||||||
if (getsockname(fd, SAS2SA(&addrbuf), &addrlen) == 0) {
|
if (getsockname(fd, SAS2SA(&addrbuf), &addrlen) == 0) {
|
||||||
|
if (family == -1) {
|
||||||
family = SAS2SA(&addrbuf)->sa_family;
|
family = SAS2SA(&addrbuf)->sa_family;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
PyErr_SetFromWindowsErrWithFilename(0, "family");
|
/* getsockname() on an unbound socket is an error on Windows.
|
||||||
|
Invalid descriptor and not a socket is same error code.
|
||||||
|
Error out if family must be resolved, or bad descriptor. */
|
||||||
|
if (family == -1 || CHECK_ERRNO(ENOTSOCK)) {
|
||||||
#else
|
#else
|
||||||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "family");
|
/* getsockname() is not supported for SOL_ALG on Linux. */
|
||||||
|
if (family == -1 || CHECK_ERRNO(EBADF) || CHECK_ERRNO(ENOTSOCK)) {
|
||||||
#endif
|
#endif
|
||||||
|
set_error();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5052,11 +5069,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
type = tmp;
|
type = tmp;
|
||||||
} else {
|
} else {
|
||||||
#ifdef MS_WINDOWS
|
set_error();
|
||||||
PyErr_SetFromWindowsErrWithFilename(0, "type");
|
|
||||||
#else
|
|
||||||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "type");
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5072,11 +5085,7 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
proto = tmp;
|
proto = tmp;
|
||||||
} else {
|
} else {
|
||||||
#ifdef MS_WINDOWS
|
set_error();
|
||||||
PyErr_SetFromWindowsErrWithFilename(0, "protocol");
|
|
||||||
#else
|
|
||||||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, "protocol");
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue