[Python-checkins] python/dist/src/Objects listobject.c,2.140,2.141
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Tue, 12 Nov 2002 14:08:12 -0800
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv19759/python/Objects
Modified Files:
listobject.c
Log Message:
SF patch 637176: list.sort crasher
Armin Rigo's Draconian but effective fix for
SF bug 453523: list.sort crasher
slightly fiddled to catch more cases of list mutation. The dreaded
internal "immutable list type" is gone! OTOH, if you look at a list
*while* it's being sorted now, it will appear to be empty. Better
than a core dump.
Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.140
retrieving revision 2.141
diff -C2 -d -r2.140 -r2.141
*** listobject.c 5 Nov 2002 22:41:37 -0000 2.140
--- listobject.c 12 Nov 2002 22:08:10 -0000 2.141
***************
*** 1635,1640 ****
}
- static PyTypeObject immutable_list_type;
-
/* An adaptive, stable, natural mergesort. See listsort.txt.
* Returns Py_None on success, NULL on error. Even in case of error, the
--- 1635,1638 ----
***************
*** 1649,1653 ****
int nremaining;
int minrun;
! PyTypeObject *savetype;
PyObject *compare = NULL;
PyObject *result = NULL; /* guilty until proved innocent */
--- 1647,1653 ----
int nremaining;
int minrun;
! int saved_ob_size;
! PyObject **saved_ob_item;
! PyObject **empty_ob_item;
PyObject *compare = NULL;
PyObject *result = NULL; /* guilty until proved innocent */
***************
*** 1660,1667 ****
merge_init(&ms, compare);
! savetype = self->ob_type;
! self->ob_type = &immutable_list_type;
! nremaining = self->ob_size;
if (nremaining < 2)
goto succeed;
--- 1660,1674 ----
merge_init(&ms, compare);
! /* The list is temporarily made empty, so that mutations performed
! * by comparison functions can't affect the slice of memory we're
! * sorting (allowing mutations during sorting is a core-dump
! * factory, since ob_item may change).
! */
! saved_ob_size = self->ob_size;
! saved_ob_item = self->ob_item;
! self->ob_size = 0;
! self->ob_item = empty_ob_item = PyMem_NEW(PyObject *, 0);
! nremaining = saved_ob_size;
if (nremaining < 2)
goto succeed;
***************
*** 1670,1674 ****
* and extending short natural runs to minrun elements.
*/
! lo = self->ob_item;
hi = lo + nremaining;
minrun = merge_compute_minrun(nremaining);
--- 1677,1681 ----
* and extending short natural runs to minrun elements.
*/
! lo = saved_ob_item;
hi = lo + nremaining;
minrun = merge_compute_minrun(nremaining);
***************
*** 1707,1717 ****
goto fail;
assert(ms.n == 1);
! assert(ms.pending[0].base == self->ob_item);
! assert(ms.pending[0].len == self->ob_size);
succeed:
result = Py_None;
fail:
! self->ob_type = savetype;
merge_freemem(&ms);
Py_XINCREF(result);
--- 1714,1736 ----
goto fail;
assert(ms.n == 1);
! assert(ms.pending[0].base == saved_ob_item);
! assert(ms.pending[0].len == saved_ob_size);
succeed:
result = Py_None;
fail:
! if (self->ob_item != empty_ob_item || self->ob_size) {
! /* The user mucked with the list during the sort. */
! (void)list_ass_slice(self, 0, self->ob_size, (PyObject *)NULL);
! if (result != NULL) {
! PyErr_SetString(PyExc_ValueError,
! "list modified during sort");
! result = NULL;
! }
! }
! if (self->ob_item == empty_ob_item)
! PyMem_FREE(empty_ob_item);
! self->ob_size = saved_ob_size;
! self->ob_item = saved_ob_item;
merge_freemem(&ms);
Py_XINCREF(result);
***************
*** 2326,2415 ****
PyType_GenericNew, /* tp_new */
PyObject_GC_Del, /* tp_free */
- };
-
-
- /* During a sort, we really can't have anyone modifying the list; it could
- cause core dumps. Thus, we substitute a dummy type that raises an
- explanatory exception when a modifying operation is used. Caveat:
- comparisons may behave differently; but I guess it's a bad idea anyway to
- compare a list that's being sorted... */
-
- static PyObject *
- immutable_list_op(void)
- {
- PyErr_SetString(PyExc_TypeError,
- "a list cannot be modified while it is being sorted");
- return NULL;
- }
-
- static PyMethodDef immutable_list_methods[] = {
- {"append", (PyCFunction)immutable_list_op, METH_VARARGS},
- {"insert", (PyCFunction)immutable_list_op, METH_VARARGS},
- {"extend", (PyCFunction)immutable_list_op, METH_O},
- {"pop", (PyCFunction)immutable_list_op, METH_VARARGS},
- {"remove", (PyCFunction)immutable_list_op, METH_VARARGS},
- {"index", (PyCFunction)listindex, METH_O},
- {"count", (PyCFunction)listcount, METH_O},
- {"reverse", (PyCFunction)immutable_list_op, METH_VARARGS},
- {"sort", (PyCFunction)immutable_list_op, METH_VARARGS},
- {NULL, NULL} /* sentinel */
- };
-
- static int
- immutable_list_ass(void)
- {
- immutable_list_op();
- return -1;
- }
-
- static PySequenceMethods immutable_list_as_sequence = {
- (inquiry)list_length, /* sq_length */
- (binaryfunc)list_concat, /* sq_concat */
- (intargfunc)list_repeat, /* sq_repeat */
- (intargfunc)list_item, /* sq_item */
- (intintargfunc)list_slice, /* sq_slice */
- (intobjargproc)immutable_list_ass, /* sq_ass_item */
- (intintobjargproc)immutable_list_ass, /* sq_ass_slice */
- (objobjproc)list_contains, /* sq_contains */
- };
-
- static PyTypeObject immutable_list_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "list (immutable, during sort)",
- sizeof(PyListObject),
- 0,
- 0, /* Cannot happen */ /* tp_dealloc */
- (printfunc)list_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* Won't be called */ /* tp_compare */
- (reprfunc)list_repr, /* tp_repr */
- 0, /* tp_as_number */
- &immutable_list_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- list_nohash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- list_doc, /* tp_doc */
- (traverseproc)list_traverse, /* tp_traverse */
- 0, /* tp_clear */
- list_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- immutable_list_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_init */
- /* NOTE: This is *not* the standard list_type struct! */
};
--- 2345,2348 ----