diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-10-12 19:17:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-12 19:17:46 (GMT) |
commit | de072100775cc29e6cd93a75466cecbd1086f258 (patch) | |
tree | d07dfdb0d3c5ca964dab28eabc3f97f508de45b4 /Modules/selectmodule.c | |
parent | b7cbfe49e39a7bbd7da20b937735a8a60bbf1872 (diff) | |
download | cpython-de072100775cc29e6cd93a75466cecbd1086f258.zip cpython-de072100775cc29e6cd93a75466cecbd1086f258.tar.gz cpython-de072100775cc29e6cd93a75466cecbd1086f258.tar.bz2 |
bpo-30058: Fixed buffer overflow in select.kqueue.control(). (#1095)
Diffstat (limited to 'Modules/selectmodule.c')
-rw-r--r-- | Modules/selectmodule.c | 29 |
1 files changed, 13 insertions, 16 deletions
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index d763bae..66d1a37 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2102,7 +2102,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) int i = 0; PyObject *otimeout = NULL; PyObject *ch = NULL; - PyObject *it = NULL, *ei = NULL; + PyObject *seq = NULL, *ei = NULL; PyObject *result = NULL; struct kevent *evl = NULL; struct kevent *chl = NULL; @@ -2148,37 +2148,34 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) } if (ch != NULL && ch != Py_None) { - it = PyObject_GetIter(ch); - if (it == NULL) { - PyErr_SetString(PyExc_TypeError, - "changelist is not iterable"); + seq = PySequence_Fast(ch, "changelist is not iterable"); + if (seq == NULL) { return NULL; } - nchanges = PyObject_Size(ch); - if (nchanges < 0) { + if (PySequence_Fast_GET_SIZE(seq) > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "changelist is too long"); goto error; } + nchanges = (int)PySequence_Fast_GET_SIZE(seq); chl = PyMem_New(struct kevent, nchanges); if (chl == NULL) { PyErr_NoMemory(); goto error; } - i = 0; - while ((ei = PyIter_Next(it)) != NULL) { + for (i = 0; i < nchanges; ++i) { + ei = PySequence_Fast_GET_ITEM(seq, i); if (!kqueue_event_Check(ei)) { - Py_DECREF(ei); PyErr_SetString(PyExc_TypeError, "changelist must be an iterable of " "select.kevent objects"); goto error; - } else { - chl[i++] = ((kqueue_event_Object *)ei)->e; } - Py_DECREF(ei); + chl[i] = ((kqueue_event_Object *)ei)->e; } + Py_CLEAR(seq); } - Py_CLEAR(it); /* event list */ if (nevents) { @@ -2246,7 +2243,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) PyMem_Free(chl); PyMem_Free(evl); Py_XDECREF(result); - Py_XDECREF(it); + Py_XDECREF(seq); return NULL; } @@ -2254,7 +2251,7 @@ PyDoc_STRVAR(kqueue_queue_control_doc, "control(changelist, max_events[, timeout=None]) -> eventlist\n\ \n\ Calls the kernel kevent function.\n\ -- changelist must be a list of kevent objects describing the changes\n\ +- changelist must be an iterable of kevent objects describing the changes\n\ to be made to the kernel's watch list or None.\n\ - max_events lets you specify the maximum number of events that the\n\ kernel will return.\n\ |