diff options
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/accu.c | 1 | ||||
-rw-r--r-- | Objects/bytearrayobject.c | 8 | ||||
-rw-r--r-- | Objects/bytesobject.c | 2 | ||||
-rw-r--r-- | Objects/dictobject.c | 112 | ||||
-rw-r--r-- | Objects/listobject.c | 1 | ||||
-rw-r--r-- | Objects/tupleobject.c | 1 | ||||
-rw-r--r-- | Objects/typeobject.c | 39 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 6 |
8 files changed, 107 insertions, 63 deletions
diff --git a/Objects/accu.c b/Objects/accu.c index 88e8f08f59..5bd2ee41fe 100644 --- a/Objects/accu.c +++ b/Objects/accu.c @@ -1,6 +1,7 @@ /* Accumulator struct implementation */ #include "Python.h" +#include "accu.h" static PyObject * join_list_unicode(PyObject *lst) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 4202ff28e4..55b4df638a 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2234,8 +2234,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg) } bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) + if (bytearray_obj == NULL) { + Py_DECREF(it); return NULL; + } buf = PyByteArray_AS_STRING(bytearray_obj); while ((item = PyIter_Next(it)) != NULL) { @@ -2268,8 +2270,10 @@ bytearray_extend(PyByteArrayObject *self, PyObject *arg) return NULL; } - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) + if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), bytearray_obj) == -1) { + Py_DECREF(bytearray_obj); return NULL; + } Py_DECREF(bytearray_obj); Py_RETURN_NONE; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 62ddf21532..796e400a82 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -875,7 +875,9 @@ bytes_hash(PyBytesObject *a) register unsigned char *p; register Py_hash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (a->ob_shash != -1) return a->ob_shash; len = Py_SIZE(a); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 768351e224..27de10dc8d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -510,27 +510,16 @@ _PyDict_MaybeUntrack(PyObject *op) _PyObject_GC_UNTRACK(op); } - /* -Internal routine to insert a new item into the table. -Used both by the internal resize routine and by the public insert routine. -Eats a reference to key and one to value. -Returns -1 if an error occurred, or 0 on success. +Internal routine to insert a new item into the table when you have entry object. +Used by insertdict. */ static int -insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) +insertdict_by_entry(register PyDictObject *mp, PyObject *key, Py_hash_t hash, + PyDictEntry *ep, PyObject *value) { PyObject *old_value; - register PyDictEntry *ep; - typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, Py_hash_t); - assert(mp->ma_lookup != NULL); - ep = mp->ma_lookup(mp, key, hash); - if (ep == NULL) { - Py_DECREF(key); - Py_DECREF(value); - return -1; - } MAINTAIN_TRACKING(mp, key, value); if (ep->me_value != NULL) { old_value = ep->me_value; @@ -553,6 +542,28 @@ insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *v return 0; } + +/* +Internal routine to insert a new item into the table. +Used both by the internal resize routine and by the public insert routine. +Eats a reference to key and one to value. +Returns -1 if an error occurred, or 0 on success. +*/ +static int +insertdict(register PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) +{ + register PyDictEntry *ep; + + assert(mp->ma_lookup != NULL); + ep = mp->ma_lookup(mp, key, hash); + if (ep == NULL) { + Py_DECREF(key); + Py_DECREF(value); + return -1; + } + return insertdict_by_entry(mp, key, hash, ep, value); +} + /* Internal routine used by dictresize() to insert an item which is known to be absent from the dict. This routine also assumes that @@ -776,39 +787,26 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key) return ep->me_value; } -/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the - * dictionary if it's merely replacing the value for an existing key. - * This means that it's safe to loop over a dictionary with PyDict_Next() - * and occasionally replace a value -- but you can't insert new keys or - * remove them. - */ -int -PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) +static int +dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key, + Py_hash_t hash, PyDictEntry *ep, PyObject *value) { register PyDictObject *mp; - register Py_hash_t hash; register Py_ssize_t n_used; - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } - assert(key); - assert(value); mp = (PyDictObject *)op; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyUnicodeObject *) key)->hash) == -1) - { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */ n_used = mp->ma_used; Py_INCREF(value); Py_INCREF(key); - if (insertdict(mp, key, hash, value) != 0) - return -1; + if (ep == NULL) { + if (insertdict(mp, key, hash, value) != 0) + return -1; + } + else { + if (insertdict_by_entry(mp, key, hash, ep, value) != 0) + return -1; + } /* If we added a key, we can safely resize. Otherwise just return! * If fill >= 2/3 size, adjust size. Normally, this doubles or * quaduples the size, but it's also possible for the dict to shrink @@ -828,6 +826,36 @@ PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used); } +/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the + * dictionary if it's merely replacing the value for an existing key. + * This means that it's safe to loop over a dictionary with PyDict_Next() + * and occasionally replace a value -- but you can't insert new keys or + * remove them. + */ +int +PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value) +{ + register Py_hash_t hash; + + if (!PyDict_Check(op)) { + PyErr_BadInternalCall(); + return -1; + } + assert(key); + assert(value); + if (PyUnicode_CheckExact(key)) { + hash = ((PyUnicodeObject *) key)->hash; + if (hash == -1) + hash = PyObject_Hash(key); + } + else { + hash = PyObject_Hash(key); + if (hash == -1) + return -1; + } + return dict_set_item_by_hash_or_entry(op, key, hash, NULL, value); +} + int PyDict_DelItem(PyObject *op, PyObject *key) { @@ -1797,9 +1825,9 @@ dict_setdefault(register PyDictObject *mp, PyObject *args) return NULL; val = ep->me_value; if (val == NULL) { - val = failobj; - if (PyDict_SetItem((PyObject*)mp, key, failobj)) - val = NULL; + if (dict_set_item_by_hash_or_entry((PyObject*)mp, key, hash, ep, + failobj) == 0) + val = failobj; } Py_XINCREF(val); return val; diff --git a/Objects/listobject.c b/Objects/listobject.c index 00de597e56..b9ef0d0287 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1,6 +1,7 @@ /* List object implementation */ #include "Python.h" +#include "accu.h" #ifdef STDC_HEADERS #include <stddef.h> diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index f6dbc315d9..e99eda06f1 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -2,6 +2,7 @@ /* Tuple object implementation */ #include "Python.h" +#include "accu.h" /* Speed optimization to avoid frequent malloc/free of small tuples */ #ifndef PyTuple_MAXSAVESIZE diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c3822abb0e..8cfa8894b0 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -458,26 +458,23 @@ type_set_bases(PyTypeObject *type, PyObject *value, void *context) for (i = 0; i < PyTuple_GET_SIZE(value); i++) { ob = PyTuple_GET_ITEM(value, i); if (!PyType_Check(ob)) { - PyErr_Format( - PyExc_TypeError, - "%s.__bases__ must be tuple of old- or new-style classes, not '%s'", - type->tp_name, Py_TYPE(ob)->tp_name); - return -1; + PyErr_Format(PyExc_TypeError, + "%s.__bases__ must be tuple of old- or " + "new-style classes, not '%s'", + type->tp_name, Py_TYPE(ob)->tp_name); + return -1; } - if (PyType_Check(ob)) { - if (PyType_IsSubtype((PyTypeObject*)ob, type)) { - PyErr_SetString(PyExc_TypeError, - "a __bases__ item causes an inheritance cycle"); - return -1; - } + if (PyType_IsSubtype((PyTypeObject*)ob, type)) { + PyErr_SetString(PyExc_TypeError, + "a __bases__ item causes an inheritance cycle"); + return -1; } } new_base = best_base(value); - if (!new_base) { + if (!new_base) return -1; - } if (!compatible_for_assignment(type->tp_base, new_base, "__bases__")) return -1; @@ -830,8 +827,13 @@ subtype_clear(PyObject *self) assert(base); } - /* There's no need to clear the instance dict (if any); - the collector will call its tp_clear handler. */ + /* Clear the instance dict (if any), to break cycles involving only + __dict__ slots (as in the case 'self.__dict__ is self'). */ + if (type->tp_dictoffset != base->tp_dictoffset) { + PyObject **dictptr = _PyObject_GetDictPtr(self); + if (dictptr && *dictptr) + Py_CLEAR(*dictptr); + } if (baseclear) return baseclear(self); @@ -2457,6 +2459,13 @@ type_getattro(PyTypeObject *type, PyObject *name) PyObject *meta_attribute, *attribute; descrgetfunc meta_get; + if (!PyUnicode_Check(name)) { + PyErr_Format(PyExc_TypeError, + "attribute name must be string, not '%.200s'", + name->ob_type->tp_name); + return NULL; + } + /* Initialize this type (we'll assume the metatype is initialized) */ if (type->tp_dict == NULL) { if (PyType_Ready(type) < 0) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index b70666106d..cd17789f53 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -7673,7 +7673,9 @@ unicode_hash(PyUnicodeObject *self) Py_UNICODE *p; Py_hash_t x; +#ifdef Py_DEBUG assert(_Py_HashSecret_Initialized); +#endif if (self->hash != -1) return self->hash; len = Py_SIZE(self); @@ -9208,10 +9210,6 @@ unicode_getnewargs(PyUnicodeObject *v) } static PyMethodDef unicode_methods[] = { - - /* Order is according to common usage: often used methods should - appear first, since lookup is done sequentially. */ - {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__}, {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__}, |