diff -r d9bb7a3ed51e Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c Tue Oct 27 22:05:09 2015 -0500 +++ b/Modules/_ctypes/_ctypes.c Wed Oct 28 23:20:51 2015 -0500 @@ -465,7 +465,8 @@ { Py_buffer buffer; Py_ssize_t offset = 0; - PyObject *result, *mv; + PyObject *result = NULL; + PyObject *mv = NULL; StgDictObject *dict = PyType_stgdict(type); assert (dict); @@ -474,34 +475,35 @@ if (offset < 0) { PyErr_SetString(PyExc_ValueError, - "offset cannot be negative"); - PyBuffer_Release(&buffer); - return NULL; - } + "offset cannot be negative"); + goto exit; + } + if (dict->size > buffer.len - offset) { PyErr_Format(PyExc_ValueError, "Buffer size too small (%zd instead of at least %zd bytes)", buffer.len, dict->size + offset); - PyBuffer_Release(&buffer); - return NULL; + goto exit; + } + + mv = PyMemoryView_FromObject(buffer.obj); + if (mv == NULL) { + goto exit; } result = PyCData_AtAddress(type, (char *)buffer.buf + offset); if (result == NULL) { - PyBuffer_Release(&buffer); - return NULL; - } - - mv = PyMemoryView_FromBuffer(&buffer); - if (mv == NULL) { - PyBuffer_Release(&buffer); - return NULL; - } - /* Hack the memoryview so that it will release the buffer. */ - ((PyMemoryViewObject *)mv)->mbuf->master.obj = buffer.obj; - ((PyMemoryViewObject *)mv)->view.obj = buffer.obj; - if (-1 == KeepRef((CDataObject *)result, -1, mv)) + Py_DECREF(mv); + goto exit; + } + + if (-1 == KeepRef((CDataObject *)result, -1, mv)) { + Py_DECREF(result); result = NULL; + } + + exit: + PyBuffer_Release(&buffer); return result; }