summaryrefslogtreecommitdiff
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/accu.c1
-rw-r--r--Objects/bytearrayobject.c8
-rw-r--r--Objects/bytesobject.c2
-rw-r--r--Objects/dictobject.c112
-rw-r--r--Objects/listobject.c1
-rw-r--r--Objects/tupleobject.c1
-rw-r--r--Objects/typeobject.c39
-rw-r--r--Objects/unicodeobject.c6
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__},