summaryrefslogtreecommitdiffstats
path: root/Modules/_ctypes
diff options
context:
space:
mode:
authorMartin Panter <vadmium+py@gmail.com>2015-11-13 21:43:39 (GMT)
committerMartin Panter <vadmium+py@gmail.com>2015-11-13 21:43:39 (GMT)
commit1bb651540e0743c4e58d875d1de240597862fa34 (patch)
treea0be0c700ee103423c37bcb2377d7fe345bc7656 /Modules/_ctypes
parentabe9625eeb71e40f042ccfccfe6a4489a6dcdf35 (diff)
downloadcpython-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/_ctypes')
-rw-r--r--Modules/_ctypes/_ctypes.c56
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;
}