diff -r e78743e03c8f Lib/test/test_devpoll.py --- a/Lib/test/test_devpoll.py Fri Dec 13 12:08:55 2013 +0200 +++ b/Lib/test/test_devpoll.py Fri Dec 13 12:54:09 2013 +0200 @@ -120,6 +120,16 @@ self.addCleanup(devpoll.close) self.assertEqual(os.get_inheritable(devpoll.fileno()), False) + 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(): run_unittest(DevPollTests) diff -r e78743e03c8f Lib/test/test_poll.py --- a/Lib/test/test_poll.py Fri Dec 13 12:08:55 2013 +0200 +++ b/Lib/test/test_poll.py Fri Dec 13 12:54:09 2013 +0200 @@ -4,7 +4,7 @@ import subprocess import random import select -import _testcapi +from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX try: import threading except ImportError: @@ -161,10 +161,13 @@ if x != 5: self.fail('Overflow must have occurred') - pollster = select.poll() - # Issue 15989 - self.assertRaises(OverflowError, pollster.poll, _testcapi.INT_MAX + 1) - self.assertRaises(OverflowError, pollster.poll, _testcapi.UINT_MAX + 1) + # Issues #15989, #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) + self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1) + self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1) @unittest.skipUnless(threading, 'Threading required for this test.') @reap_threads diff -r e78743e03c8f Modules/selectmodule.c --- a/Modules/selectmodule.c Fri Dec 13 12:08:55 2013 +0200 +++ b/Modules/selectmodule.c Fri Dec 13 12:54:09 2013 +0200 @@ -356,7 +356,7 @@ assert(i < self->ufd_len); /* Never overflow */ 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++; } assert(i == self->ufd_len); @@ -364,6 +364,24 @@ 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 int"); + return 0; + } + + *(unsigned short *)ptr = Py_SAFE_DOWNCAST(uval, unsigned long, unsigned short); + return 1; +} + PyDoc_STRVAR(poll_register_doc, "register(fd [, eventmask] ) -> None\n\n\ Register a file descriptor with the polling object.\n\ @@ -375,10 +393,11 @@ poll_register(pollObject *self, PyObject *args) { PyObject *o, *key, *value; - int fd, events = POLLIN | POLLPRI | POLLOUT; + int fd; + unsigned short events = POLLIN | POLLPRI | POLLOUT; int err; - if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { + if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events)) { return NULL; } @@ -418,10 +437,11 @@ poll_modify(pollObject *self, PyObject *args) { PyObject *o, *key, *value; - int fd, events; + int fd; + unsigned short events; int err; - if (!PyArg_ParseTuple(args, "Oi:modify", &o, &events)) { + if (!PyArg_ParseTuple(args, "OO&:modify", &o, ushort_converter, &events)) { return NULL; } @@ -728,12 +748,13 @@ internal_devpoll_register(devpollObject *self, PyObject *args, int remove) { PyObject *o; - int fd, events = POLLIN | POLLPRI | POLLOUT; + int fd; + unsigned short events = POLLIN | POLLPRI | POLLOUT; if (self->fd_devpoll < 0) return devpoll_err_closed(); - if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) { + if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events)) { return NULL; } @@ -751,7 +772,7 @@ } 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 (devpoll_flush(self))