Commit 60d6dcf7 authored by Jim Fulton's avatar Jim Fulton

Fixed bug:

  Calling __setstate__ on a persistent object could under certain
  uncommon cause the process to crash.
parent 561fec77
Whats new in ZODB 3.8.2 Whats new in ZODB 3.8.3
======================= =======================
New Feature: New Feature:
...@@ -16,6 +16,10 @@ Bugs Fixed: ...@@ -16,6 +16,10 @@ Bugs Fixed:
- Fixed a pack test that was not compatible with storages that always - Fixed a pack test that was not compatible with storages that always
return an object count of 0. return an object count of 0.
- Calling __setstate__ on a persistent object could under certain
uncommon cause the process to crash.
Whats new in ZODB 3.8.2 Whats new in ZODB 3.8.2
======================= =======================
......
...@@ -446,43 +446,47 @@ static char pickle___setstate__doc[] = ...@@ -446,43 +446,47 @@ static char pickle___setstate__doc[] =
" will be cleared and updated with the value.\n\n" " will be cleared and updated with the value.\n\n"
" The items in the second element will be assigned as attributes.\n" " The items in the second element will be assigned as attributes.\n"
; ;
static PyObject * static PyObject *
pickle___setstate__(PyObject *self, PyObject *state) pickle___setstate__(PyObject *self, PyObject *state)
{ {
PyObject *slots=NULL; PyObject *slots=NULL;
if (PyTuple_Check(state)) { if (PyTuple_Check(state))
if (!PyArg_ParseTuple(state, "OO:__setstate__", &state, &slots)) {
return NULL; if (!PyArg_ParseTuple(state, "OO:__setstate__", &state, &slots))
return NULL;
} }
if (state != Py_None) { if (state != Py_None)
PyObject **dict; {
PyObject **dict;
dict = _PyObject_GetDictPtr(self);
if (dict) { dict = _PyObject_GetDictPtr(self);
if (!*dict) {
*dict = PyDict_New(); if (!dict)
if (!*dict) {
return NULL; PyErr_SetString(PyExc_TypeError,
} "this object has no instance dictionary");
return NULL;
} }
if (*dict) { if (!*dict)
PyDict_Clear(*dict); {
if (PyDict_Update(*dict, state) < 0) *dict = PyDict_New();
return NULL; if (!*dict)
return NULL;
} }
else if (pickle_setattrs_from_dict(self, state) < 0)
return NULL; PyDict_Clear(*dict);
if (PyDict_Update(*dict, state) < 0)
return NULL;
} }
if (slots && pickle_setattrs_from_dict(self, slots) < 0) if (slots && pickle_setattrs_from_dict(self, slots) < 0)
return NULL; return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
static char pickle___reduce__doc[] = static char pickle___reduce__doc[] =
......
############################################################################## ##############################################################################
# #
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. # Copyright (c) Zope Foundation and Contributors.
# All Rights Reserved. # All Rights Reserved.
# #
# This software is subject to the provisions of the Zope Public License, # This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
# #
############################################################################## ##############################################################################
import unittest
from zope.testing import doctest from zope.testing import doctest
from persistent import Persistent from persistent import Persistent
...@@ -20,5 +21,23 @@ class P(Persistent): ...@@ -20,5 +21,23 @@ class P(Persistent):
def inc(self): def inc(self):
self.x += 1 self.x += 1
def cpersistent_setstate_pointer_sanity():
"""
>>> Persistent().__setstate__({})
Traceback (most recent call last):
...
TypeError: this object has no instance dictionary
>>> class C(Persistent): __slots__ = 'x', 'y'
>>> C().__setstate__(({}, {}))
Traceback (most recent call last):
...
TypeError: this object has no instance dictionary
"""
def test_suite(): def test_suite():
return doctest.DocFileSuite("persistent.txt", globs={"P": P}) return unittest.TestSuite((
doctest.DocFileSuite("persistent.txt", globs={"P": P}),
doctest.DocTestSuite(),
))
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