pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/51b4ade30615dccaa7f591456528821f4320d5ff

Fix obscure breakage (relative to 2.3) in listsort: the test for list · python/cpython@51b4ade · GitHub
Skip to content

Commit 51b4ade

Browse files
committed
Fix obscure breakage (relative to 2.3) in listsort: the test for list
mutation during list.sort() used to rely on that listobject.c always NULL'ed ob_item when ob_size fell to 0. That's no longer true, so the test for list mutation during a sort is no longer reliable. Changed the test to rely instead on that listobject.c now never NULLs-out ob_item after (if ever) ob_item gets a non-NULL value. This new assumption is also documented now, as a required invariant in listobject.h. The new assumption allowed some real simplification to some of the hairier code in listsort(), so is a Good Thing on that count.
1 parent 014f103 commit 51b4ade

2 files changed

Lines changed: 15 additions & 26 deletions

File tree

Include/listobject.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ typedef struct {
3030
* 0 <= ob_size <= allocated
3131
* len(list) == ob_size
3232
* ob_item == NULL implies ob_size == allocated == 0
33+
* If ob_item ever becomes non-NULL, it remains non-NULL for the
34+
* life of the list object. The check for mutation in list.sort()
35+
* relies on this odd detail.
3336
*/
3437
int allocated;
3538
} PyListObject;

Objects/listobject.c

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,7 +1906,6 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
19061906
int minrun;
19071907
int saved_ob_size, saved_allocated;
19081908
PyObject **saved_ob_item;
1909-
PyObject **empty_ob_item;
19101909
PyObject *compare = NULL;
19111910
PyObject *result = NULL; /* guilty until proved innocent */
19121911
int reverse = 0;
@@ -1941,9 +1940,8 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
19411940
saved_ob_size = self->ob_size;
19421941
saved_ob_item = self->ob_item;
19431942
saved_allocated = self->allocated;
1944-
self->ob_size = 0;
1945-
self->ob_item = empty_ob_item = PyMem_NEW(PyObject *, 0);
1946-
self->allocated = 0;
1943+
self->ob_size = self->allocated = 0;
1944+
self->ob_item = NULL;
19471945

19481946
if (keyfunc != NULL) {
19491947
for (i=0 ; i < saved_ob_size ; i++) {
@@ -1957,18 +1955,6 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
19571955
saved_ob_item[i] = value;
19581956
Py_DECREF(kvpair);
19591957
}
1960-
if (self->ob_item != empty_ob_item
1961-
|| self->ob_size) {
1962-
/* If the list changed *as well* we
1963-
have two errors. We let the first
1964-
one "win", but we shouldn't let
1965-
what's in the list currently
1966-
leak. */
1967-
(void)list_ass_slice(
1968-
self, 0, self->ob_size,
1969-
(PyObject *)NULL);
1970-
}
1971-
19721958
goto dsu_fail;
19731959
}
19741960
kvpair = build_sortwrapper(key, value);
@@ -2044,14 +2030,12 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
20442030
}
20452031
}
20462032

2047-
if (self->ob_item != empty_ob_item || self->ob_size) {
2048-
/* The user mucked with the list during the sort. */
2049-
(void)list_ass_slice(self, 0, self->ob_size, (PyObject *)NULL);
2050-
if (result != NULL) {
2051-
PyErr_SetString(PyExc_ValueError,
2052-
"list modified during sort");
2053-
result = NULL;
2054-
}
2033+
if (self->ob_item != NULL && result != NULL) {
2034+
/* The user mucked with the list during the sort,
2035+
* and we don't already have another error to report.
2036+
*/
2037+
PyErr_SetString(PyExc_ValueError, "list modified during sort");
2038+
result = NULL;
20552039
}
20562040

20572041
if (reverse && saved_ob_size > 1)
@@ -2060,8 +2044,10 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
20602044
merge_freemem(&ms);
20612045

20622046
dsu_fail:
2063-
if (self->ob_item == empty_ob_item)
2064-
PyMem_FREE(empty_ob_item);
2047+
if (self->ob_item != NULL) {
2048+
(void)list_ass_slice(self, 0, self->ob_size, (PyObject *)NULL);
2049+
PyMem_FREE(self->ob_item);
2050+
}
20652051
self->ob_size = saved_ob_size;
20662052
self->ob_item = saved_ob_item;
20672053
self->allocated = saved_allocated;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy