From a92cc91ee63ea5c21297e468fbea725c8f7542dd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 14 Dec 2013 19:11:04 +0200 Subject: [PATCH] Issue #17919: Fixed integer overflow in the eventmask parameter. --- Lib/test/test_poll.py | 13 ++++++++----- Misc/NEWS | 3 ++- Modules/selectmodule.c | 32 +++++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py index 7e94e3da9c..e4cdc16bde 100644 --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -3,7 +3,7 @@ import os import random import select -import _testcapi +from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX try: import threading except ImportError: @@ -159,10 +159,13 @@ class PollTests(unittest.TestCase): 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 --git a/Misc/NEWS b/Misc/NEWS index 6e54379d5d..327c3d7842 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,7 +23,8 @@ Core and Builtins 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 #17200: telnetlib's read_until and expect timeout was broken by the fix to Issue #14635 in Python 2.7.4 to be interpreted as milliseconds diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index dcd6b9c258..6071996a2d 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -347,7 +347,7 @@ update_ufd_array(pollObject *self) assert(i < self->ufd_len); /* Never overflow */ self->ufds[i].fd = (int)PyInt_AsLong(key); - self->ufds[i].events = (short)PyInt_AsLong(value); + self->ufds[i].events = (short)(unsigned short)PyInt_AsLong(value); i++; } assert(i == self->ufd_len); @@ -355,6 +355,24 @@ update_ufd_array(pollObject *self) 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, "register(fd [, eventmask] ) -> None\n\n\ Register a file descriptor with the polling object.\n\ @@ -366,12 +384,12 @@ static PyObject * 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; - } fd = PyObject_AsFileDescriptor(o); if (fd == -1) return NULL; @@ -409,12 +427,12 @@ static PyObject * 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; - } fd = PyObject_AsFileDescriptor(o); if (fd == -1) return NULL; -- 2.50.1