summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c214
-rw-r--r--Objects/enumobject.c55
-rw-r--r--Objects/listobject.c11
-rw-r--r--Objects/object.c5
-rw-r--r--Objects/stringobject.c6
-rw-r--r--Objects/tupleobject.c13
-rw-r--r--Objects/unicodeobject.c9
7 files changed, 189 insertions, 124 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 957090f..4230125 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -9,8 +9,6 @@
#include "Python.h"
-typedef PyDictEntry dictentry;
-typedef PyDictObject dictobject;
/* Set a key error with the specified argument, wrapping it in a
* tuple automatically so that tuple keys are not unpacked as the
@@ -116,14 +114,14 @@ approach, using repeated multiplication by x in GF(2**n) where an irreducible
polynomial for each table size was chosen such that x was a primitive root.
Christian Tismer later extended that to use division by x instead, as an
efficient way to get the high bits of the hash code into play. This scheme
-also gave excellent collision statistics, but was more expensive: two if-tests
-were required inside the loop; computing "the next" index took about the same
-number of operations but without as much potential parallelism (e.g.,
-computing 5*j can go on at the same time as computing 1+perturb in the above,
-and then shifting perturb can be done while the table index is being masked);
-and the dictobject struct required a member to hold the table's polynomial.
-In Tim's experiments the current scheme ran faster, produced equally good
-collision statistics, needed less code & used less memory.
+also gave excellent collision statistics, but was more expensive: two
+if-tests were required inside the loop; computing "the next" index took about
+the same number of operations but without as much potential parallelism
+(e.g., computing 5*j can go on at the same time as computing 1+perturb in the
+above, and then shifting perturb can be done while the table index is being
+masked); and the PyDictObject struct required a member to hold the table's
+polynomial. In Tim's experiments the current scheme ran faster, produced
+equally good collision statistics, needed less code & used less memory.
Theoretical Python 2.5 headache: hash codes are only C "long", but
sizeof(Py_ssize_t) > sizeof(long) may be possible. In that case, and if a
@@ -137,7 +135,7 @@ which point everyone will have terabytes of RAM on 64-bit boxes).
*/
/* Object used as dummy key to fill deleted entries */
-static PyObject *dummy = NULL; /* Initialized by first call to newdictobject() */
+static PyObject *dummy = NULL; /* Initialized by first call to newPyDictObject() */
#ifdef Py_REF_DEBUG
PyObject *
@@ -148,8 +146,8 @@ _PyDict_Dummy(void)
#endif
/* forward declarations */
-static dictentry *
-lookdict_unicode(dictobject *mp, PyObject *key, long hash);
+static PyDictEntry *
+lookdict_unicode(PyDictObject *mp, PyObject *key, long hash);
#ifdef SHOW_CONVERSION_COUNTS
static long created = 0L;
@@ -192,7 +190,7 @@ static int num_free_dicts = 0;
PyObject *
PyDict_New(void)
{
- register dictobject *mp;
+ register PyDictObject *mp;
if (dummy == NULL) { /* Auto-initialize dummy */
dummy = PyUnicode_FromString("<dummy key>");
if (dummy == NULL)
@@ -213,7 +211,7 @@ PyDict_New(void)
assert (mp->ma_table == mp->ma_smalltable);
assert (mp->ma_mask == PyDict_MINSIZE - 1);
} else {
- mp = PyObject_GC_New(dictobject, &PyDict_Type);
+ mp = PyObject_GC_New(PyDictObject, &PyDict_Type);
if (mp == NULL)
return NULL;
EMPTY_TO_MINSIZE(mp);
@@ -245,20 +243,20 @@ lookdict() is general-purpose, and may return NULL if (and only if) a
comparison raises an exception (this was new in Python 2.5).
lookdict_unicode() below is specialized to string keys, comparison of which can
never raise an exception; that function can never return NULL. For both, when
-the key isn't found a dictentry* is returned for which the me_value field is
+the key isn't found a PyDictEntry* is returned for which the me_value field is
NULL; this is the slot in the dict at which the key would have been found, and
the caller can (if it wishes) add the <key, value> pair to the returned
-dictentry*.
+PyDictEntry*.
*/
-static dictentry *
-lookdict(dictobject *mp, PyObject *key, register long hash)
+static PyDictEntry *
+lookdict(PyDictObject *mp, PyObject *key, register long hash)
{
register size_t i;
register size_t perturb;
- register dictentry *freeslot;
+ register PyDictEntry *freeslot;
register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
+ PyDictEntry *ep0 = mp->ma_table;
+ register PyDictEntry *ep;
register int cmp;
PyObject *startkey;
@@ -354,15 +352,15 @@ unicode_eq(PyObject *aa, PyObject *bb)
*
* This is valuable because dicts with only unicode keys are very common.
*/
-static dictentry *
-lookdict_unicode(dictobject *mp, PyObject *key, register long hash)
+static PyDictEntry *
+lookdict_unicode(PyDictObject *mp, PyObject *key, register long hash)
{
register size_t i;
register size_t perturb;
- register dictentry *freeslot;
+ register PyDictEntry *freeslot;
register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
+ PyDictEntry *ep0 = mp->ma_table;
+ register PyDictEntry *ep;
/* Make sure this function doesn't have to handle non-unicode keys,
including subclasses of str; e.g., one reason to subclass
@@ -413,10 +411,10 @@ Eats a reference to key and one to value.
Returns -1 if an error occurred, or 0 on success.
*/
static int
-insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
+insertdict(register PyDictObject *mp, PyObject *key, long hash, PyObject *value)
{
PyObject *old_value;
- register dictentry *ep;
+ register PyDictEntry *ep;
typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long);
assert(mp->ma_lookup != NULL);
@@ -456,14 +454,14 @@ Note that no refcounts are changed by this routine; if needed, the caller
is responsible for incref'ing `key` and `value`.
*/
static void
-insertdict_clean(register dictobject *mp, PyObject *key, long hash,
+insertdict_clean(register PyDictObject *mp, PyObject *key, long hash,
PyObject *value)
{
register size_t i;
register size_t perturb;
register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
+ PyDictEntry *ep0 = mp->ma_table;
+ register PyDictEntry *ep;
i = hash & mask;
ep = &ep0[i];
@@ -485,13 +483,13 @@ items again. When entries have been deleted, the new table may
actually be smaller than the old one.
*/
static int
-dictresize(dictobject *mp, Py_ssize_t minused)
+dictresize(PyDictObject *mp, Py_ssize_t minused)
{
Py_ssize_t newsize;
- dictentry *oldtable, *newtable, *ep;
+ PyDictEntry *oldtable, *newtable, *ep;
Py_ssize_t i;
int is_oldtable_malloced;
- dictentry small_copy[PyDict_MINSIZE];
+ PyDictEntry small_copy[PyDict_MINSIZE];
assert(minused >= 0);
@@ -530,7 +528,7 @@ dictresize(dictobject *mp, Py_ssize_t minused)
}
}
else {
- newtable = PyMem_NEW(dictentry, newsize);
+ newtable = PyMem_NEW(PyDictEntry, newsize);
if (newtable == NULL) {
PyErr_NoMemory();
return -1;
@@ -541,7 +539,7 @@ dictresize(dictobject *mp, Py_ssize_t minused)
assert(newtable != oldtable);
mp->ma_table = newtable;
mp->ma_mask = newsize - 1;
- memset(newtable, 0, sizeof(dictentry) * newsize);
+ memset(newtable, 0, sizeof(PyDictEntry) * newsize);
mp->ma_used = 0;
i = mp->ma_fill;
mp->ma_fill = 0;
@@ -581,8 +579,8 @@ PyObject *
PyDict_GetItem(PyObject *op, PyObject *key)
{
long hash;
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
+ PyDictObject *mp = (PyDictObject *)op;
+ PyDictEntry *ep;
PyThreadState *tstate;
if (!PyDict_Check(op))
return NULL;
@@ -628,8 +626,8 @@ PyObject *
PyDict_GetItemWithError(PyObject *op, PyObject *key)
{
long hash;
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
+ PyDictObject*mp = (PyDictObject *)op;
+ PyDictEntry *ep;
if (!PyDict_Check(op)) {
PyErr_BadInternalCall();
@@ -659,7 +657,7 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key)
int
PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
{
- register dictobject *mp;
+ register PyDictObject *mp;
register long hash;
register Py_ssize_t n_used;
@@ -669,7 +667,7 @@ PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
}
assert(key);
assert(value);
- mp = (dictobject *)op;
+ mp = (PyDictObject *)op;
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyUnicodeObject *) key)->hash) == -1)
{
@@ -705,9 +703,9 @@ PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
int
PyDict_DelItem(PyObject *op, PyObject *key)
{
- register dictobject *mp;
+ register PyDictObject *mp;
register long hash;
- register dictentry *ep;
+ register PyDictEntry *ep;
PyObject *old_value, *old_key;
if (!PyDict_Check(op)) {
@@ -721,7 +719,7 @@ PyDict_DelItem(PyObject *op, PyObject *key)
if (hash == -1)
return -1;
}
- mp = (dictobject *)op;
+ mp = (PyDictObject *)op;
ep = (mp->ma_lookup)(mp, key, hash);
if (ep == NULL)
return -1;
@@ -743,18 +741,18 @@ PyDict_DelItem(PyObject *op, PyObject *key)
void
PyDict_Clear(PyObject *op)
{
- dictobject *mp;
- dictentry *ep, *table;
+ PyDictObject *mp;
+ PyDictEntry *ep, *table;
int table_is_malloced;
Py_ssize_t fill;
- dictentry small_copy[PyDict_MINSIZE];
+ PyDictEntry small_copy[PyDict_MINSIZE];
#ifdef Py_DEBUG
Py_ssize_t i, n;
#endif
if (!PyDict_Check(op))
return;
- mp = (dictobject *)op;
+ mp = (PyDictObject *)op;
#ifdef Py_DEBUG
n = mp->ma_mask + 1;
i = 0;
@@ -829,15 +827,15 @@ PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
{
register Py_ssize_t i;
register Py_ssize_t mask;
- register dictentry *ep;
+ register PyDictEntry *ep;
if (!PyDict_Check(op))
return 0;
i = *ppos;
if (i < 0)
return 0;
- ep = ((dictobject *)op)->ma_table;
- mask = ((dictobject *)op)->ma_mask;
+ ep = ((PyDictObject *)op)->ma_table;
+ mask = ((PyDictObject *)op)->ma_mask;
while (i <= mask && ep[i].me_value == NULL)
i++;
*ppos = i+1;
@@ -856,15 +854,15 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue,
{
register Py_ssize_t i;
register Py_ssize_t mask;
- register dictentry *ep;
+ register PyDictEntry *ep;
if (!PyDict_Check(op))
return 0;
i = *ppos;
if (i < 0)
return 0;
- ep = ((dictobject *)op)->ma_table;
- mask = ((dictobject *)op)->ma_mask;
+ ep = ((PyDictObject *)op)->ma_table;
+ mask = ((PyDictObject *)op)->ma_mask;
while (i <= mask && ep[i].me_value == NULL)
i++;
*ppos = i+1;
@@ -881,9 +879,9 @@ _PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue,
/* Methods */
static void
-dict_dealloc(register dictobject *mp)
+dict_dealloc(register PyDictObject *mp)
{
- register dictentry *ep;
+ register PyDictEntry *ep;
Py_ssize_t fill = mp->ma_fill;
PyObject_GC_UnTrack(mp);
Py_TRASHCAN_SAFE_BEGIN(mp)
@@ -904,7 +902,7 @@ dict_dealloc(register dictobject *mp)
}
static PyObject *
-dict_repr(dictobject *mp)
+dict_repr(PyDictObject *mp)
{
Py_ssize_t i;
PyObject *s, *temp, *colon = NULL;
@@ -983,17 +981,17 @@ Done:
}
static Py_ssize_t
-dict_length(dictobject *mp)
+dict_length(PyDictObject *mp)
{
return mp->ma_used;
}
static PyObject *
-dict_subscript(dictobject *mp, register PyObject *key)
+dict_subscript(PyDictObject *mp, register PyObject *key)
{
PyObject *v;
long hash;
- dictentry *ep;
+ PyDictEntry *ep;
assert(mp->ma_table != NULL);
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyUnicodeObject *) key)->hash) == -1) {
@@ -1027,7 +1025,7 @@ dict_subscript(dictobject *mp, register PyObject *key)
}
static int
-dict_ass_sub(dictobject *mp, PyObject *v, PyObject *w)
+dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w)
{
if (w == NULL)
return PyDict_DelItem((PyObject *)mp, v);
@@ -1042,11 +1040,11 @@ static PyMappingMethods dict_as_mapping = {
};
static PyObject *
-dict_keys(register dictobject *mp)
+dict_keys(register PyDictObject *mp)
{
register PyObject *v;
register Py_ssize_t i, j;
- dictentry *ep;
+ PyDictEntry *ep;
Py_ssize_t mask, n;
again:
@@ -1076,11 +1074,11 @@ dict_keys(register dictobject *mp)
}
static PyObject *
-dict_values(register dictobject *mp)
+dict_values(register PyDictObject *mp)
{
register PyObject *v;
register Py_ssize_t i, j;
- dictentry *ep;
+ PyDictEntry *ep;
Py_ssize_t mask, n;
again:
@@ -1110,13 +1108,13 @@ dict_values(register dictobject *mp)
}
static PyObject *
-dict_items(register dictobject *mp)
+dict_items(register PyDictObject *mp)
{
register PyObject *v;
register Py_ssize_t i, j, n;
Py_ssize_t mask;
PyObject *item, *key, *value;
- dictentry *ep;
+ PyDictEntry *ep;
/* Preallocate the list of tuples, to avoid allocations during
* the loop over the items, which could trigger GC, which
@@ -1178,7 +1176,7 @@ dict_fromkeys(PyObject *cls, PyObject *args)
return NULL;
if (PyDict_CheckExact(d) && PyAnySet_CheckExact(seq)) {
- dictobject *mp = (dictobject *)d;
+ PyDictObject *mp = (PyDictObject *)d;
Py_ssize_t pos = 0;
PyObject *key;
long hash;
@@ -1342,7 +1340,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
{
register PyDictObject *mp, *other;
register Py_ssize_t i;
- dictentry *entry;
+ PyDictEntry *entry;
/* We accept for the argument either a concrete dictionary object,
* or an abstract "mapping" object. For the former, we can do
@@ -1353,9 +1351,9 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
PyErr_BadInternalCall();
return -1;
}
- mp = (dictobject*)a;
+ mp = (PyDictObject*)a;
if (PyDict_CheckExact(b)) {
- other = (dictobject*)b;
+ other = (PyDictObject*)b;
if (other == mp || other->ma_used == 0)
/* a.update(a) or a.update({}); nothing to do */
return 0;
@@ -1435,7 +1433,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
}
static PyObject *
-dict_copy(register dictobject *mp)
+dict_copy(register PyDictObject *mp)
{
return PyDict_Copy((PyObject*)mp);
}
@@ -1465,7 +1463,7 @@ PyDict_Size(PyObject *mp)
PyErr_BadInternalCall();
return -1;
}
- return ((dictobject *)mp)->ma_used;
+ return ((PyDictObject *)mp)->ma_used;
}
PyObject *
@@ -1475,7 +1473,7 @@ PyDict_Keys(PyObject *mp)
PyErr_BadInternalCall();
return NULL;
}
- return dict_keys((dictobject *)mp);
+ return dict_keys((PyDictObject *)mp);
}
PyObject *
@@ -1485,7 +1483,7 @@ PyDict_Values(PyObject *mp)
PyErr_BadInternalCall();
return NULL;
}
- return dict_values((dictobject *)mp);
+ return dict_values((PyDictObject *)mp);
}
PyObject *
@@ -1495,7 +1493,7 @@ PyDict_Items(PyObject *mp)
PyErr_BadInternalCall();
return NULL;
}
- return dict_items((dictobject *)mp);
+ return dict_items((PyDictObject *)mp);
}
/* Return 1 if dicts equal, 0 if not, -1 if error.
@@ -1503,7 +1501,7 @@ PyDict_Items(PyObject *mp)
* Uses only Py_EQ comparison.
*/
static int
-dict_equal(dictobject *a, dictobject *b)
+dict_equal(PyDictObject *a, PyDictObject *b)
{
Py_ssize_t i;
@@ -1550,7 +1548,7 @@ dict_richcompare(PyObject *v, PyObject *w, int op)
res = Py_NotImplemented;
}
else if (op == Py_EQ || op == Py_NE) {
- cmp = dict_equal((dictobject *)v, (dictobject *)w);
+ cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w);
if (cmp < 0)
return NULL;
res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
@@ -1562,10 +1560,10 @@ dict_richcompare(PyObject *v, PyObject *w, int op)
}
static PyObject *
-dict_contains(register dictobject *mp, PyObject *key)
+dict_contains(register PyDictObject *mp, PyObject *key)
{
long hash;
- dictentry *ep;
+ PyDictEntry *ep;
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyUnicodeObject *) key)->hash) == -1) {
@@ -1580,13 +1578,13 @@ dict_contains(register dictobject *mp, PyObject *key)
}
static PyObject *
-dict_get(register dictobject *mp, PyObject *args)
+dict_get(register PyDictObject *mp, PyObject *args)
{
PyObject *key;
PyObject *failobj = Py_None;
PyObject *val = NULL;
long hash;
- dictentry *ep;
+ PyDictEntry *ep;
if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))
return NULL;
@@ -1609,13 +1607,13 @@ dict_get(register dictobject *mp, PyObject *args)
static PyObject *
-dict_setdefault(register dictobject *mp, PyObject *args)
+dict_setdefault(register PyDictObject *mp, PyObject *args)
{
PyObject *key;
PyObject *failobj = Py_None;
PyObject *val = NULL;
long hash;
- dictentry *ep;
+ PyDictEntry *ep;
if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
return NULL;
@@ -1641,17 +1639,17 @@ dict_setdefault(register dictobject *mp, PyObject *args)
static PyObject *
-dict_clear(register dictobject *mp)
+dict_clear(register PyDictObject *mp)
{
PyDict_Clear((PyObject *)mp);
Py_RETURN_NONE;
}
static PyObject *
-dict_pop(dictobject *mp, PyObject *args)
+dict_pop(PyDictObject *mp, PyObject *args)
{
long hash;
- dictentry *ep;
+ PyDictEntry *ep;
PyObject *old_value, *old_key;
PyObject *key, *deflt = NULL;
@@ -1694,10 +1692,10 @@ dict_pop(dictobject *mp, PyObject *args)
}
static PyObject *
-dict_popitem(dictobject *mp)
+dict_popitem(PyDictObject *mp)
{
Py_ssize_t i = 0;
- dictentry *ep;
+ PyDictEntry *ep;
PyObject *res;
/* Allocate the result tuple before checking the size. Believe it
@@ -1776,7 +1774,7 @@ dict_tp_clear(PyObject *op)
extern PyTypeObject PyDictIterKey_Type; /* Forward */
extern PyTypeObject PyDictIterValue_Type; /* Forward */
extern PyTypeObject PyDictIterItem_Type; /* Forward */
-static PyObject *dictiter_new(dictobject *, PyTypeObject *);
+static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
PyDoc_STRVAR(contains__doc__,
@@ -1859,8 +1857,8 @@ int
PyDict_Contains(PyObject *op, PyObject *key)
{
long hash;
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
+ PyDictObject *mp = (PyDictObject *)op;
+ PyDictEntry *ep;
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyUnicodeObject *) key)->hash) == -1) {
@@ -1876,8 +1874,8 @@ PyDict_Contains(PyObject *op, PyObject *key)
int
_PyDict_Contains(PyObject *op, PyObject *key, long hash)
{
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
+ PyDictObject *mp = (PyDictObject *)op;
+ PyDictEntry *ep;
ep = (mp->ma_lookup)(mp, key, hash);
return ep == NULL ? -1 : (ep->me_value != NULL);
@@ -1924,7 +1922,7 @@ dict_init(PyObject *self, PyObject *args, PyObject *kwds)
}
static PyObject *
-dict_iter(dictobject *dict)
+dict_iter(PyDictObject *dict)
{
return dictiter_new(dict, &PyDictIterKey_Type);
}
@@ -1943,7 +1941,7 @@ PyDoc_STRVAR(dictionary_doc,
PyTypeObject PyDict_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"dict",
- sizeof(dictobject),
+ sizeof(PyDictObject),
0,
(destructor)dict_dealloc, /* tp_dealloc */
0, /* tp_print */
@@ -2028,7 +2026,7 @@ PyDict_DelItemString(PyObject *v, const char *key)
typedef struct {
PyObject_HEAD
- dictobject *di_dict; /* Set to NULL when iterator is exhausted */
+ PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */
Py_ssize_t di_used;
Py_ssize_t di_pos;
PyObject* di_result; /* reusable result tuple for iteritems */
@@ -2036,7 +2034,7 @@ typedef struct {
} dictiterobject;
static PyObject *
-dictiter_new(dictobject *dict, PyTypeObject *itertype)
+dictiter_new(PyDictObject *dict, PyTypeObject *itertype)
{
dictiterobject *di;
di = PyObject_New(dictiterobject, itertype);
@@ -2089,8 +2087,8 @@ static PyObject *dictiter_iternextkey(dictiterobject *di)
{
PyObject *key;
register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
+ register PyDictEntry *ep;
+ PyDictObject *d = di->di_dict;
if (d == NULL)
return NULL;
@@ -2161,8 +2159,8 @@ static PyObject *dictiter_iternextvalue(dictiterobject *di)
{
PyObject *value;
register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
+ register PyDictEntry *ep;
+ PyDictObject *d = di->di_dict;
if (d == NULL)
return NULL;
@@ -2233,8 +2231,8 @@ static PyObject *dictiter_iternextitem(dictiterobject *di)
{
PyObject *key, *value, *result = di->di_result;
register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
+ register PyDictEntry *ep;
+ PyDictObject *d = di->di_dict;
if (d == NULL)
return NULL;
@@ -2324,7 +2322,7 @@ PyTypeObject PyDictIterItem_Type = {
typedef struct {
PyObject_HEAD
- dictobject *dv_dict;
+ PyDictObject *dv_dict;
} dictviewobject;
@@ -2363,7 +2361,7 @@ dictview_new(PyObject *dict, PyTypeObject *type)
if (dv == NULL)
return NULL;
Py_INCREF(dict);
- dv->dv_dict = (dictobject *)dict;
+ dv->dv_dict = (PyDictObject *)dict;
return (PyObject *)dv;
}
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index 6997fdc..0a3694d 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -7,6 +7,7 @@ typedef struct {
long en_index; /* current index of enumeration */
PyObject* en_sit; /* secondary iterator of enumeration */
PyObject* en_result; /* result tuple */
+ PyObject* en_longindex; /* index for sequences >= LONG_MAX */
} enumobject;
static PyObject *
@@ -25,6 +26,7 @@ enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
en->en_index = 0;
en->en_sit = PyObject_GetIter(seq);
+ en->en_longindex = NULL;
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;
@@ -43,6 +45,7 @@ enum_dealloc(enumobject *en)
PyObject_GC_UnTrack(en);
Py_XDECREF(en->en_sit);
Py_XDECREF(en->en_result);
+ Py_XDECREF(en->en_longindex);
Py_Type(en)->tp_free(en);
}
@@ -51,10 +54,53 @@ enum_traverse(enumobject *en, visitproc visit, void *arg)
{
Py_VISIT(en->en_sit);
Py_VISIT(en->en_result);
+ Py_VISIT(en->en_longindex);
return 0;
}
static PyObject *
+enum_next_long(enumobject *en, PyObject* next_item)
+{
+ static PyObject *one = NULL;
+ PyObject *result = en->en_result;
+ PyObject *next_index;
+ PyObject *stepped_up;
+
+ if (en->en_longindex == NULL) {
+ en->en_longindex = PyInt_FromLong(LONG_MAX);
+ if (en->en_longindex == NULL)
+ return NULL;
+ }
+ if (one == NULL) {
+ one = PyInt_FromLong(1);
+ if (one == NULL)
+ return NULL;
+ }
+ next_index = en->en_longindex;
+ assert(next_index != NULL);
+ stepped_up = PyNumber_Add(next_index, one);
+ if (stepped_up == NULL)
+ return NULL;
+ en->en_longindex = stepped_up;
+
+ if (result->ob_refcnt == 1) {
+ Py_INCREF(result);
+ Py_DECREF(PyTuple_GET_ITEM(result, 0));
+ Py_DECREF(PyTuple_GET_ITEM(result, 1));
+ } else {
+ result = PyTuple_New(2);
+ if (result == NULL) {
+ Py_DECREF(next_index);
+ Py_DECREF(next_item);
+ return NULL;
+ }
+ }
+ PyTuple_SET_ITEM(result, 0, next_index);
+ PyTuple_SET_ITEM(result, 1, next_item);
+ return result;
+}
+
+static PyObject *
enum_next(enumobject *en)
{
PyObject *next_index;
@@ -62,16 +108,13 @@ enum_next(enumobject *en)
PyObject *result = en->en_result;
PyObject *it = en->en_sit;
- if (en->en_index == LONG_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "enumerate() is limited to LONG_MAX items");
- return NULL;
- }
-
next_item = (*Py_Type(it)->tp_iternext)(it);
if (next_item == NULL)
return NULL;
+ if (en->en_index == LONG_MAX)
+ return enum_next_long(en, next_item);
+
next_index = PyInt_FromLong(en->en_index);
if (next_index == NULL) {
Py_DECREF(next_item);
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 235edf5..5df40fa 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -463,10 +463,10 @@ list_repeat(PyListObject *a, Py_ssize_t n)
if (n < 0)
n = 0;
size = Py_Size(a) * n;
- if (size == 0)
- return PyList_New(0);
if (n && size/n != Py_Size(a))
return PyErr_NoMemory();
+ if (size == 0)
+ return PyList_New(0);
np = (PyListObject *) PyList_New(size);
if (np == NULL)
return NULL;
@@ -633,7 +633,7 @@ static PyObject *
list_inplace_repeat(PyListObject *self, Py_ssize_t n)
{
PyObject **items;
- Py_ssize_t size, i, j, p;
+ Py_ssize_t size, i, j, p, newsize;
size = PyList_GET_SIZE(self);
@@ -648,7 +648,10 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n)
return (PyObject *)self;
}
- if (list_resize(self, size*n) == -1)
+ newsize = size * n;
+ if (newsize/n != size)
+ return PyErr_NoMemory();
+ if (list_resize(self, newsize) == -1)
return NULL;
p = size;
diff --git a/Objects/object.c b/Objects/object.c
index 77ddb1d..40b8b42 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -423,7 +423,12 @@ _PyObject_Str(PyObject *v)
if (Py_Type(v)->tp_str == NULL)
return PyObject_Repr(v);
+ /* It is possible for a type to have a tp_str representation that loops
+ infinitely. */
+ if (Py_EnterRecursiveCall(" while getting the str of an object"))
+ return NULL;
res = (*Py_Type(v)->tp_str)(v);
+ Py_LeaveRecursiveCall();
if (res == NULL)
return NULL;
if (!(PyString_Check(res) || PyUnicode_Check(res))) {
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 4b2778a..3dd1051 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -598,15 +598,15 @@ PyObject *PyString_DecodeEscape(const char *s,
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = s[-1] - '0';
- if ('0' <= *s && *s <= '7') {
+ if (s < end && '0' <= *s && *s <= '7') {
c = (c<<3) + *s++ - '0';
- if ('0' <= *s && *s <= '7')
+ if (s < end && '0' <= *s && *s <= '7')
c = (c<<3) + *s++ - '0';
}
*p++ = c;
break;
case 'x':
- if (ISXDIGIT(s[0]) && ISXDIGIT(s[1])) {
+ if (s+1 < end && ISXDIGIT(s[0]) && ISXDIGIT(s[1])) {
unsigned int x = 0;
c = Py_CHARMASK(*s);
s++;
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 222f362..c22785d 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -195,13 +195,25 @@ tuplerepr(PyTupleObject *v)
if (n == 0)
return PyUnicode_FromString("()");
+ /* While not mutable, it is still possible to end up with a cycle in a
+ tuple through an object that stores itself within a tuple (and thus
+ infinitely asks for the repr of itself). This should only be
+ possible within a type. */
+ i = Py_ReprEnter((PyObject *)v);
+ if (i != 0) {
+ return i > 0 ? PyString_FromString("(...)") : NULL;
+ }
+
pieces = PyTuple_New(n);
if (pieces == NULL)
return NULL;
/* Do repr() on each element. */
for (i = 0; i < n; ++i) {
+ if (Py_EnterRecursiveCall(" while getting the repr of a tuple"))
+ goto Done;
s = PyObject_Repr(v->ob_item[i]);
+ Py_LeaveRecursiveCall();
if (s == NULL)
goto Done;
PyTuple_SET_ITEM(pieces, i, s);
@@ -236,6 +248,7 @@ tuplerepr(PyTupleObject *v)
Done:
Py_DECREF(pieces);
+ Py_ReprLeave((PyObject *)v);
return result;
}
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index c77751d..23268f9 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -2671,7 +2671,10 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s,
startinpos = s-starts;
/* \ - Escapes */
s++;
- switch (*s++) {
+ c = *s++;
+ if (s > end)
+ c = '\0'; /* Invalid after \ */
+ switch (c) {
/* \x escapes */
case '\n': break;
@@ -2690,9 +2693,9 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s,
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
x = s[-1] - '0';
- if ('0' <= *s && *s <= '7') {
+ if (s < end && '0' <= *s && *s <= '7') {
x = (x<<3) + *s++ - '0';
- if ('0' <= *s && *s <= '7')
+ if (s < end && '0' <= *s && *s <= '7')
x = (x<<3) + *s++ - '0';
}
*p++ = x;