[Python-checkins] python/dist/src/Objects listobject.c,2.166,2.167

mwh at users.sourceforge.net mwh at users.sourceforge.net
Thu Dec 4 06:25:48 EST 2003


Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1:/tmp/cvs-serv21077/Objects

Modified Files:
	listobject.c 
Log Message:
Fixes and tests for various "holding pointers when arbitrary Python code
can run" bugs as discussed in

[ 848856 ] couple of new list.sort bugs



Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.166
retrieving revision 2.167
diff -C2 -d -r2.166 -r2.167
*** listobject.c	28 Nov 2003 21:43:02 -0000	2.166
--- listobject.c	4 Dec 2003 11:25:46 -0000	2.167
***************
*** 1849,1853 ****
  	int reverse = 0;
  	PyObject *keyfunc = NULL;
! 	int i, len = 0;
  	PyObject *key, *value, *kvpair;
  	static char *kwlist[] = {"cmp", "key", "reverse", 0};
--- 1849,1853 ----
  	int reverse = 0;
  	PyObject *keyfunc = NULL;
! 	int i;
  	PyObject *key, *value, *kvpair;
  	static char *kwlist[] = {"cmp", "key", "reverse", 0};
***************
*** 1871,1887 ****
  		Py_XINCREF(compare);
  
  	if (keyfunc != NULL) {
! 		len = PyList_GET_SIZE(self);
! 		for (i=0 ; i < len ; i++) {
! 			value = PyList_GET_ITEM(self, i);
  			key = PyObject_CallFunctionObjArgs(keyfunc, value, 
  							   NULL);
  			if (key == NULL) {
  				for (i=i-1 ; i>=0 ; i--) {
! 					kvpair = PyList_GET_ITEM(self, i);
  					value = sortwrapper_getvalue(kvpair);
! 					PyList_SET_ITEM(self, i, value);
  					Py_DECREF(kvpair);
  				}
  				goto dsu_fail;
  			}
--- 1871,1908 ----
  		Py_XINCREF(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);
+ 
  	if (keyfunc != NULL) {
! 		for (i=0 ; i < saved_ob_size ; i++) {
! 			value = saved_ob_item[i];
  			key = PyObject_CallFunctionObjArgs(keyfunc, value, 
  							   NULL);
  			if (key == NULL) {
  				for (i=i-1 ; i>=0 ; i--) {
! 					kvpair = saved_ob_item[i];
  					value = sortwrapper_getvalue(kvpair);
! 					saved_ob_item[i] = value;
  					Py_DECREF(kvpair);
  				}
+ 				if (self->ob_item != empty_ob_item 
+ 				    || self->ob_size) {
+ 					/* If the list changed *as well* we
+ 					   have two errors.  We let the first
+ 					   one "win", but we shouldn't let
+ 					   what's in the list currently
+ 					   leak. */
+ 					(void)list_ass_slice(
+ 						self, 0, self->ob_size,
+ 						(PyObject *)NULL);
+ 				}
+ 				
  				goto dsu_fail;
  			}
***************
*** 1889,1893 ****
  			if (kvpair == NULL)
  				goto dsu_fail;
! 			PyList_SET_ITEM(self, i, kvpair);
  		}
  	}
--- 1910,1914 ----
  			if (kvpair == NULL)
  				goto dsu_fail;
! 			saved_ob_item[i] = kvpair;
  		}
  	}
***************
*** 1895,1913 ****
  	/* Reverse sort stability achieved by initially reversing the list,
  	applying a stable forward sort, then reversing the final result. */
! 	if (reverse && self->ob_size > 1)
! 		reverse_slice(self->ob_item, self->ob_item + self->ob_size);
  
  	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)
--- 1916,1924 ----
  	/* Reverse sort stability achieved by initially reversing the list,
  	applying a stable forward sort, then reversing the final result. */
! 	if (reverse && saved_ob_size > 1)
! 		reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);
  
  	merge_init(&ms, compare);
  
  	nremaining = saved_ob_size;
  	if (nremaining < 2)
***************
*** 1960,1963 ****
--- 1971,1983 ----
  	result = Py_None;
  fail:
+ 	if (keyfunc != NULL) {
+ 		for (i=0 ; i < saved_ob_size ; i++) {
+ 			kvpair = saved_ob_item[i];
+ 			value = sortwrapper_getvalue(kvpair);
+ 			saved_ob_item[i] = value;
+ 			Py_DECREF(kvpair);
+ 		}
+ 	}
+ 
  	if (self->ob_item != empty_ob_item || self->ob_size) {
  		/* The user mucked with the list during the sort. */
***************
*** 1969,1992 ****
  		}
  	}
- 	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);
  
! 	if (keyfunc != NULL) {
! 		len = PyList_GET_SIZE(self);
! 		for (i=0 ; i < len ; i++) {
! 			kvpair = PyList_GET_ITEM(self, i);
! 			value = sortwrapper_getvalue(kvpair);
! 			PyList_SET_ITEM(self, i, value);
! 			Py_DECREF(kvpair);
! 		}
! 	}
  
! 	if (reverse && self->ob_size > 1)
! 		reverse_slice(self->ob_item, self->ob_item + self->ob_size);
  
  dsu_fail:
  	Py_XDECREF(compare);
  	Py_XINCREF(result);
--- 1989,2003 ----
  		}
  	}
  
! 	if (reverse && saved_ob_size > 1)
! 		reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);
  
! 	merge_freemem(&ms);
  
  dsu_fail:
+ 	if (self->ob_item == empty_ob_item)
+ 		PyMem_FREE(empty_ob_item);
+ 	self->ob_size = saved_ob_size;
+ 	self->ob_item = saved_ob_item;
  	Py_XDECREF(compare);
  	Py_XINCREF(result);





More information about the Python-checkins mailing list