Commit 5da107ac authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #17919: Fixed integer overflow in the eventmask parameter.

parent 01e5f800
...@@ -87,6 +87,17 @@ class DevPollTests(unittest.TestCase): ...@@ -87,6 +87,17 @@ class DevPollTests(unittest.TestCase):
self.assertRaises(OverflowError, pollster.poll, 1 << 63) self.assertRaises(OverflowError, pollster.poll, 1 << 63)
self.assertRaises(OverflowError, pollster.poll, 1 << 64) self.assertRaises(OverflowError, pollster.poll, 1 << 64)
def test_events_mask_overflow(self):
pollster = select.devpoll()
w, r = os.pipe()
pollster.register(w)
# Issue #17919
self.assertRaises(OverflowError, pollster.register, 0, -1)
self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1)
self.assertRaises(OverflowError, pollster.modify, 1, -1)
self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1)
def test_main(): def test_main():
run_unittest(DevPollTests) run_unittest(DevPollTests)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import os import os
import random import random
import select import select
import _testcapi from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX
try: try:
import threading import threading
except ImportError: except ImportError:
...@@ -159,10 +159,13 @@ class PollTests(unittest.TestCase): ...@@ -159,10 +159,13 @@ class PollTests(unittest.TestCase):
if x != 5: if x != 5:
self.fail('Overflow must have occurred') self.fail('Overflow must have occurred')
pollster = select.poll() # Issues #15989, #17919
# Issue 15989 self.assertRaises(OverflowError, pollster.register, 0, -1)
self.assertRaises(OverflowError, pollster.poll, _testcapi.INT_MAX + 1) self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1)
self.assertRaises(OverflowError, pollster.poll, _testcapi.UINT_MAX + 1) self.assertRaises(OverflowError, pollster.modify, 1, -1)
self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1)
self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1)
self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1)
@unittest.skipUnless(threading, 'Threading required for this test.') @unittest.skipUnless(threading, 'Threading required for this test.')
@reap_threads @reap_threads
......
...@@ -32,7 +32,8 @@ Core and Builtins ...@@ -32,7 +32,8 @@ Core and Builtins
Library Library
------- -------
- Issue #17919: select.poll.poll() again works with poll.POLLNVAL on AIX. - Issue #17919: select.poll.register() again works with poll.POLLNVAL on AIX.
Fixed integer overflow in the eventmask parameter.
- Issue #19063: if a Charset's body_encoding was set to None, the email - Issue #19063: if a Charset's body_encoding was set to None, the email
package would generate a message claiming the Content-Transfer-Encoding package would generate a message claiming the Content-Transfer-Encoding
......
...@@ -361,7 +361,7 @@ update_ufd_array(pollObject *self) ...@@ -361,7 +361,7 @@ update_ufd_array(pollObject *self)
assert(i < self->ufd_len); assert(i < self->ufd_len);
/* Never overflow */ /* Never overflow */
self->ufds[i].fd = (int)PyLong_AsLong(key); self->ufds[i].fd = (int)PyLong_AsLong(key);
self->ufds[i].events = (short)PyLong_AsLong(value); self->ufds[i].events = (short)(unsigned short)PyLong_AsLong(value);
i++; i++;
} }
assert(i == self->ufd_len); assert(i == self->ufd_len);
...@@ -369,6 +369,24 @@ update_ufd_array(pollObject *self) ...@@ -369,6 +369,24 @@ update_ufd_array(pollObject *self)
return 1; return 1;
} }
static int
ushort_converter(PyObject *obj, void *ptr)
{
unsigned long uval;
uval = PyLong_AsUnsignedLong(obj);
if (uval == (unsigned long)-1 && PyErr_Occurred())
return 0;
if (uval > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large for C unsigned short");
return 0;
}
*(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short);
return 1;
}
PyDoc_STRVAR(poll_register_doc, PyDoc_STRVAR(poll_register_doc,
"register(fd [, eventmask] ) -> None\n\n\ "register(fd [, eventmask] ) -> None\n\n\
Register a file descriptor with the polling object.\n\ Register a file descriptor with the polling object.\n\
...@@ -380,12 +398,12 @@ static PyObject * ...@@ -380,12 +398,12 @@ static PyObject *
poll_register(pollObject *self, PyObject *args) poll_register(pollObject *self, PyObject *args)
{ {
PyObject *o, *key, *value; PyObject *o, *key, *value;
int fd, events = POLLIN | POLLPRI | POLLOUT; int fd;
unsigned short events = POLLIN | POLLPRI | POLLOUT;
int err; int err;
if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events))
return NULL; return NULL;
}
fd = PyObject_AsFileDescriptor(o); fd = PyObject_AsFileDescriptor(o);
if (fd == -1) return NULL; if (fd == -1) return NULL;
...@@ -423,12 +441,12 @@ static PyObject * ...@@ -423,12 +441,12 @@ static PyObject *
poll_modify(pollObject *self, PyObject *args) poll_modify(pollObject *self, PyObject *args)
{ {
PyObject *o, *key, *value; PyObject *o, *key, *value;
int fd, events; int fd;
unsigned short events;
int err; int err;
if (!PyArg_ParseTuple(args, "Oi:modify", &o, &events)) { if (!PyArg_ParseTuple(args, "OO&:modify", &o, ushort_converter, &events))
return NULL; return NULL;
}
fd = PyObject_AsFileDescriptor(o); fd = PyObject_AsFileDescriptor(o);
if (fd == -1) return NULL; if (fd == -1) return NULL;
...@@ -726,11 +744,11 @@ static PyObject * ...@@ -726,11 +744,11 @@ static PyObject *
internal_devpoll_register(devpollObject *self, PyObject *args, int remove) internal_devpoll_register(devpollObject *self, PyObject *args, int remove)
{ {
PyObject *o; PyObject *o;
int fd, events = POLLIN | POLLPRI | POLLOUT; int fd;
unsigned short events = POLLIN | POLLPRI | POLLOUT;
if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events))
return NULL; return NULL;
}
fd = PyObject_AsFileDescriptor(o); fd = PyObject_AsFileDescriptor(o);
if (fd == -1) return NULL; if (fd == -1) return NULL;
...@@ -746,7 +764,7 @@ internal_devpoll_register(devpollObject *self, PyObject *args, int remove) ...@@ -746,7 +764,7 @@ internal_devpoll_register(devpollObject *self, PyObject *args, int remove)
} }
self->fds[self->n_fds].fd = fd; self->fds[self->n_fds].fd = fd;
self->fds[self->n_fds].events = events; self->fds[self->n_fds].events = (signed short)events;
if (++self->n_fds == self->max_n_fds) { if (++self->n_fds == self->max_n_fds) {
if (devpoll_flush(self)) if (devpoll_flush(self))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment