Commit 4284df33 authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #70 from zopefoundation/issue69

Change cPickleCache to use PER_TypeCheck
parents d1966b53 516f90ec
``persistent`` Changelog ``persistent`` Changelog
======================== ========================
4.2.5 (unreleased) 4.3.0 (unreleased)
------------------ ------------------
- Fix the possibility of a rare crash in the C extension when - Fix the possibility of a rare crash in the C extension when
deallocating items. See https://github.com/zopefoundation/persistent/issues/66 deallocating items. See https://github.com/zopefoundation/persistent/issues/66
- Change cPickleCache's comparison of object sizes to determine
whether an object can go in the cache to use ``PyObject_TypeCheck()``.
This matches what the pure Python implementation does and is a
stronger test that the object really is compatible with the cache.
Previously, an object could potentially include ``cPersistent_HEAD``
and *not* set ``tp_base`` to ``cPersistenceCAPI->pertype`` and still
be eligible for the pickle cache; that is no longer the case. See
`issue 69 <https://github.com/zopefoundation/persistent/issues/69>`_.
4.2.4.2 (2017-04-23) 4.2.4.2 (2017-04-23)
-------------------- --------------------
......
...@@ -99,11 +99,6 @@ static char cPickleCache_doc_string[] = ...@@ -99,11 +99,6 @@ static char cPickleCache_doc_string[] =
#include <stddef.h> #include <stddef.h>
#undef Py_FindMethod #undef Py_FindMethod
/* Python 2.4 backward compat */
#if PY_MAJOR_VERSION <= 2 && PY_MINOR_VERSION < 5
#define Py_ssize_t int
typedef Py_ssize_t (*lenfunc)(PyObject *);
#endif
/* Python string objects to speed lookups; set by module init. */ /* Python string objects to speed lookups; set by module init. */
static PyObject *py__p_changed; static PyObject *py__p_changed;
...@@ -111,7 +106,7 @@ static PyObject *py__p_deactivate; ...@@ -111,7 +106,7 @@ static PyObject *py__p_deactivate;
static PyObject *py__p_jar; static PyObject *py__p_jar;
static PyObject *py__p_oid; static PyObject *py__p_oid;
static cPersistenceCAPIstruct *capi; static cPersistenceCAPIstruct *cPersistenceCAPI;
/* This object is the pickle cache. The CACHE_HEAD macro guarantees /* This object is the pickle cache. The CACHE_HEAD macro guarantees
that layout of this struct is the same as the start of that layout of this struct is the same as the start of
...@@ -523,7 +518,7 @@ cc_debug_info(ccobject *self) ...@@ -523,7 +518,7 @@ cc_debug_info(ccobject *self)
v = Py_BuildValue("Oi", k, v->ob_refcnt); v = Py_BuildValue("Oi", k, v->ob_refcnt);
else if (! PyType_Check(v) && else if (! PyType_Check(v) &&
(v->ob_type->tp_basicsize >= sizeof(cPersistentObject)) PER_TypeCheck(v)
) )
v = Py_BuildValue("Oisi", v = Py_BuildValue("Oisi",
k, v->ob_refcnt, v->ob_type->tp_name, k, v->ob_refcnt, v->ob_type->tp_name,
...@@ -711,13 +706,12 @@ cc_new_ghost(ccobject *self, PyObject *args) ...@@ -711,13 +706,12 @@ cc_new_ghost(ccobject *self, PyObject *args)
{ {
/* Its a persistent class, such as a ZClass. Thats ok. */ /* Its a persistent class, such as a ZClass. Thats ok. */
} }
else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject)) else if (! PER_TypeCheck(v))
{ {
/* If it's not an instance of a persistent class, (ie Python /* If it's not an instance of a persistent class, (ie Python
classes that derive from persistent.Persistent, BTrees, classes that derive from persistent.Persistent, BTrees,
etc), report an error. etc), report an error.
TODO: checking sizeof() seems a poor test.
*/ */
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Cache values must be persistent objects."); "Cache values must be persistent objects.");
...@@ -1034,13 +1028,11 @@ cc_add_item(ccobject *self, PyObject *key, PyObject *v) ...@@ -1034,13 +1028,11 @@ cc_add_item(ccobject *self, PyObject *key, PyObject *v)
{ {
/* Its a persistent class, such as a ZClass. Thats ok. */ /* Its a persistent class, such as a ZClass. Thats ok. */
} }
else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject)) else if (! PER_TypeCheck(v))
{ {
/* If it's not an instance of a persistent class, (ie Python /* If it's not an instance of a persistent class, (ie Python
classes that derive from persistent.Persistent, BTrees, classes that derive from persistent.Persistent, BTrees,
etc), report an error. etc), report an error.
TODO: checking sizeof() seems a poor test.
*/ */
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Cache values must be persistent objects."); "Cache values must be persistent objects.");
...@@ -1347,14 +1339,14 @@ module_init(void) ...@@ -1347,14 +1339,14 @@ module_init(void)
#endif #endif
#ifdef PY3K #ifdef PY3K
capi = (cPersistenceCAPIstruct *)PyCapsule_Import(CAPI_CAPSULE_NAME, 0); cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCapsule_Import(CAPI_CAPSULE_NAME, 0);
#else #else
capi = (cPersistenceCAPIstruct *)PyCObject_Import( cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCObject_Import(
"persistent.cPersistence", "CAPI"); "persistent.cPersistence", "CAPI");
#endif #endif
if (!capi) if (!cPersistenceCAPI)
return NULL; return NULL;
capi->percachedel = (percachedelfunc)cc_oid_unreferenced; cPersistenceCAPI->percachedel = (percachedelfunc)cc_oid_unreferenced;
py__p_changed = INTERN("_p_changed"); py__p_changed = INTERN("_p_changed");
if (!py__p_changed) if (!py__p_changed)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment