@@ -1634,8 +1634,6 @@ merge_compute_minrun(int n)
16341634 return n + r ;
16351635}
16361636
1637- static PyTypeObject immutable_list_type ;
1638-
16391637/* An adaptive, stable, natural mergesort. See listsort.txt.
16401638 * Returns Py_None on success, NULL on error. Even in case of error, the
16411639 * list will be some permutation of its input state (nothing is lost or
@@ -1648,7 +1646,9 @@ listsort(PyListObject *self, PyObject *args)
16481646 PyObject * * lo , * * hi ;
16491647 int nremaining ;
16501648 int minrun ;
1651- PyTypeObject * savetype ;
1649+ int saved_ob_size ;
1650+ PyObject * * saved_ob_item ;
1651+ PyObject * * empty_ob_item ;
16521652 PyObject * compare = NULL ;
16531653 PyObject * result = NULL ; /* guilty until proved innocent */
16541654
@@ -1659,17 +1659,24 @@ listsort(PyListObject *self, PyObject *args)
16591659 }
16601660 merge_init (& ms , compare );
16611661
1662- savetype = self -> ob_type ;
1663- self -> ob_type = & immutable_list_type ;
1662+ /* The list is temporarily made empty, so that mutations performed
1663+ * by comparison functions can't affect the slice of memory we're
1664+ * sorting (allowing mutations during sorting is a core-dump
1665+ * factory, since ob_item may change).
1666+ */
1667+ saved_ob_size = self -> ob_size ;
1668+ saved_ob_item = self -> ob_item ;
1669+ self -> ob_size = 0 ;
1670+ self -> ob_item = empty_ob_item = PyMem_NEW (PyObject * , 0 );
16641671
1665- nremaining = self -> ob_size ;
1672+ nremaining = saved_ob_size ;
16661673 if (nremaining < 2 )
16671674 goto succeed ;
16681675
16691676 /* March over the array once, left to right, finding natural runs,
16701677 * and extending short natural runs to minrun elements.
16711678 */
1672- lo = self -> ob_item ;
1679+ lo = saved_ob_item ;
16731680 hi = lo + nremaining ;
16741681 minrun = merge_compute_minrun (nremaining );
16751682 do {
@@ -1706,13 +1713,25 @@ listsort(PyListObject *self, PyObject *args)
17061713 if (merge_force_collapse (& ms ) < 0 )
17071714 goto fail ;
17081715 assert (ms .n == 1 );
1709- assert (ms .pending [0 ].base == self -> ob_item );
1710- assert (ms .pending [0 ].len == self -> ob_size );
1716+ assert (ms .pending [0 ].base == saved_ob_item );
1717+ assert (ms .pending [0 ].len == saved_ob_size );
17111718
17121719succeed :
17131720 result = Py_None ;
17141721fail :
1715- self -> ob_type = savetype ;
1722+ if (self -> ob_item != empty_ob_item || self -> ob_size ) {
1723+ /* The user mucked with the list during the sort. */
1724+ (void )list_ass_slice (self , 0 , self -> ob_size , (PyObject * )NULL );
1725+ if (result != NULL ) {
1726+ PyErr_SetString (PyExc_ValueError ,
1727+ "list modified during sort" );
1728+ result = NULL ;
1729+ }
1730+ }
1731+ if (self -> ob_item == empty_ob_item )
1732+ PyMem_FREE (empty_ob_item );
1733+ self -> ob_size = saved_ob_size ;
1734+ self -> ob_item = saved_ob_item ;
17161735 merge_freemem (& ms );
17171736 Py_XINCREF (result );
17181737 return result ;
@@ -2328,92 +2347,6 @@ PyTypeObject PyList_Type = {
23282347};
23292348
23302349
2331- /* During a sort, we really can't have anyone modifying the list; it could
2332- cause core dumps. Thus, we substitute a dummy type that raises an
2333- explanatory exception when a modifying operation is used. Caveat:
2334- comparisons may behave differently; but I guess it's a bad idea anyway to
2335- compare a list that's being sorted... */
2336-
2337- static PyObject *
2338- immutable_list_op (void )
2339- {
2340- PyErr_SetString (PyExc_TypeError ,
2341- "a list cannot be modified while it is being sorted" );
2342- return NULL ;
2343- }
2344-
2345- static PyMethodDef immutable_list_methods [] = {
2346- {"append" , (PyCFunction )immutable_list_op , METH_VARARGS },
2347- {"insert" , (PyCFunction )immutable_list_op , METH_VARARGS },
2348- {"extend" , (PyCFunction )immutable_list_op , METH_O },
2349- {"pop" , (PyCFunction )immutable_list_op , METH_VARARGS },
2350- {"remove" , (PyCFunction )immutable_list_op , METH_VARARGS },
2351- {"index" , (PyCFunction )listindex , METH_O },
2352- {"count" , (PyCFunction )listcount , METH_O },
2353- {"reverse" , (PyCFunction )immutable_list_op , METH_VARARGS },
2354- {"sort" , (PyCFunction )immutable_list_op , METH_VARARGS },
2355- {NULL , NULL } /* sentinel */
2356- };
2357-
2358- static int
2359- immutable_list_ass (void )
2360- {
2361- immutable_list_op ();
2362- return -1 ;
2363- }
2364-
2365- static PySequenceMethods immutable_list_as_sequence = {
2366- (inquiry )list_length , /* sq_length */
2367- (binaryfunc )list_concat , /* sq_concat */
2368- (intargfunc )list_repeat , /* sq_repeat */
2369- (intargfunc )list_item , /* sq_item */
2370- (intintargfunc )list_slice , /* sq_slice */
2371- (intobjargproc )immutable_list_ass , /* sq_ass_item */
2372- (intintobjargproc )immutable_list_ass , /* sq_ass_slice */
2373- (objobjproc )list_contains , /* sq_contains */
2374- };
2375-
2376- static PyTypeObject immutable_list_type = {
2377- PyObject_HEAD_INIT (& PyType_Type )
2378- 0 ,
2379- "list (immutable, during sort)" ,
2380- sizeof (PyListObject ),
2381- 0 ,
2382- 0 , /* Cannot happen */ /* tp_dealloc */
2383- (printfunc )list_print , /* tp_print */
2384- 0 , /* tp_getattr */
2385- 0 , /* tp_setattr */
2386- 0 , /* Won't be called */ /* tp_compare */
2387- (reprfunc )list_repr , /* tp_repr */
2388- 0 , /* tp_as_number */
2389- & immutable_list_as_sequence , /* tp_as_sequence */
2390- 0 , /* tp_as_mapping */
2391- list_nohash , /* tp_hash */
2392- 0 , /* tp_call */
2393- 0 , /* tp_str */
2394- PyObject_GenericGetAttr , /* tp_getattro */
2395- 0 , /* tp_setattro */
2396- 0 , /* tp_as_buffer */
2397- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC ,/* tp_flags */
2398- list_doc , /* tp_doc */
2399- (traverseproc )list_traverse , /* tp_traverse */
2400- 0 , /* tp_clear */
2401- list_richcompare , /* tp_richcompare */
2402- 0 , /* tp_weaklistoffset */
2403- 0 , /* tp_iter */
2404- 0 , /* tp_iternext */
2405- immutable_list_methods , /* tp_methods */
2406- 0 , /* tp_members */
2407- 0 , /* tp_getset */
2408- 0 , /* tp_base */
2409- 0 , /* tp_dict */
2410- 0 , /* tp_descr_get */
2411- 0 , /* tp_descr_set */
2412- 0 , /* tp_init */
2413- /* NOTE: This is *not* the standard list_type struct! */
2414- };
2415-
2416-
24172350/*********************** List Iterator **************************/
24182351
24192352typedef struct {
0 commit comments