diff options
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/dictobject.c | 214 | ||||
-rw-r--r-- | Objects/enumobject.c | 55 | ||||
-rw-r--r-- | Objects/listobject.c | 11 | ||||
-rw-r--r-- | Objects/object.c | 5 | ||||
-rw-r--r-- | Objects/stringobject.c | 6 | ||||
-rw-r--r-- | Objects/tupleobject.c | 13 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 9 |
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; |