Commit 516f90ec authored by Jason Madden's avatar Jason Madden

Change cPickleCache to use PER_TypeCheck

Instead of testing object sizes.

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.

This resolves several compiler warnings:

persistent/cPickleCache.c:521:43: warning: comparison of integers of different signs: 'Py_ssize_t' (aka 'long') and 'unsigned long' [-Wsign-compare]
                (v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
                 ~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~
persistent/cPickleCache.c:709:39: warning: comparison of integers of different signs: 'Py_ssize_t' (aka 'long') and 'unsigned long' [-Wsign-compare]
    else if (v->ob_type->tp_basicsize < sizeof(cPersistentObject))

Fixes #69.
parent d1966b53
``persistent`` Changelog
========================
4.2.5 (unreleased)
4.3.0 (unreleased)
------------------
- Fix the possibility of a rare crash in the C extension when
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)
--------------------
......
......@@ -99,11 +99,6 @@ static char cPickleCache_doc_string[] =
#include <stddef.h>
#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. */
static PyObject *py__p_changed;
......@@ -111,7 +106,7 @@ static PyObject *py__p_deactivate;
static PyObject *py__p_jar;
static PyObject *py__p_oid;
static cPersistenceCAPIstruct *capi;
static cPersistenceCAPIstruct *cPersistenceCAPI;
/* This object is the pickle cache. The CACHE_HEAD macro guarantees
that layout of this struct is the same as the start of
......@@ -523,7 +518,7 @@ cc_debug_info(ccobject *self)
v = Py_BuildValue("Oi", k, v->ob_refcnt);
else if (! PyType_Check(v) &&
(v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
PER_TypeCheck(v)
)
v = Py_BuildValue("Oisi",
k, v->ob_refcnt, v->ob_type->tp_name,
......@@ -711,13 +706,12 @@ cc_new_ghost(ccobject *self, PyObject *args)
{
/* 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
classes that derive from persistent.Persistent, BTrees,
etc), report an error.
TODO: checking sizeof() seems a poor test.
*/
PyErr_SetString(PyExc_TypeError,
"Cache values must be persistent objects.");
......@@ -1034,13 +1028,11 @@ cc_add_item(ccobject *self, PyObject *key, PyObject *v)
{
/* 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
classes that derive from persistent.Persistent, BTrees,
etc), report an error.
TODO: checking sizeof() seems a poor test.
*/
PyErr_SetString(PyExc_TypeError,
"Cache values must be persistent objects.");
......@@ -1347,14 +1339,14 @@ module_init(void)
#endif
#ifdef PY3K
capi = (cPersistenceCAPIstruct *)PyCapsule_Import(CAPI_CAPSULE_NAME, 0);
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCapsule_Import(CAPI_CAPSULE_NAME, 0);
#else
capi = (cPersistenceCAPIstruct *)PyCObject_Import(
"persistent.cPersistence", "CAPI");
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCObject_Import(
"persistent.cPersistence", "CAPI");
#endif
if (!capi)
if (!cPersistenceCAPI)
return NULL;
capi->percachedel = (percachedelfunc)cc_oid_unreferenced;
cPersistenceCAPI->percachedel = (percachedelfunc)cc_oid_unreferenced;
py__p_changed = INTERN("_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