diff options
author | Martin Panter <vadmium+py@gmail.com> | 2015-11-13 21:43:39 (GMT) |
---|---|---|
committer | Martin Panter <vadmium+py@gmail.com> | 2015-11-13 21:43:39 (GMT) |
commit | 1bb651540e0743c4e58d875d1de240597862fa34 (patch) | |
tree | a0be0c700ee103423c37bcb2377d7fe345bc7656 /Modules | |
parent | abe9625eeb71e40f042ccfccfe6a4489a6dcdf35 (diff) | |
download | cpython-1bb651540e0743c4e58d875d1de240597862fa34.zip cpython-1bb651540e0743c4e58d875d1de240597862fa34.tar.gz cpython-1bb651540e0743c4e58d875d1de240597862fa34.tar.bz2 |
Issue #25498: Fix GC crash due to ctypes objects wrapping a memoryview
This was a regression caused by revision 1da9630e9b7f. Based on patch by
Eryksun.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2e5939c..2b27ed3 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -463,45 +463,65 @@ KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep); static PyObject * CDataType_from_buffer(PyObject *type, PyObject *args) { - Py_buffer buffer; + PyObject *obj; + PyObject *mv; + PyObject *result; + Py_buffer *buffer; Py_ssize_t offset = 0; - PyObject *result, *mv; + StgDictObject *dict = PyType_stgdict(type); assert (dict); - if (!PyArg_ParseTuple(args, "w*|n:from_buffer", &buffer, &offset)) + if (!PyArg_ParseTuple(args, "O|n:from_buffer", &obj, &offset)) return NULL; + mv = PyMemoryView_FromObject(obj); + if (mv == NULL) + return NULL; + + buffer = PyMemoryView_GET_BUFFER(mv); + + if (buffer->readonly) { + PyErr_SetString(PyExc_TypeError, + "underlying buffer is not writable"); + Py_DECREF(mv); + return NULL; + } + + if (!PyBuffer_IsContiguous(buffer, 'C')) { + PyErr_SetString(PyExc_TypeError, + "underlying buffer is not C contiguous"); + Py_DECREF(mv); + return NULL; + } + if (offset < 0) { PyErr_SetString(PyExc_ValueError, "offset cannot be negative"); - PyBuffer_Release(&buffer); + Py_DECREF(mv); return NULL; } - if (dict->size > buffer.len - offset) { + + 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); + "Buffer size too small " + "(%zd instead of at least %zd bytes)", + buffer->len, dict->size + offset); + Py_DECREF(mv); return NULL; } - result = PyCData_AtAddress(type, (char *)buffer.buf + offset); + result = PyCData_AtAddress(type, (char *)buffer->buf + offset); if (result == NULL) { - PyBuffer_Release(&buffer); + Py_DECREF(mv); return NULL; } - mv = PyMemoryView_FromBuffer(&buffer); - if (mv == NULL) { - PyBuffer_Release(&buffer); + if (-1 == KeepRef((CDataObject *)result, -1, mv)) { + Py_DECREF(result); 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)) - result = NULL; + return result; } |