Index: Modules/gcmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/gcmodule.c,v
retrieving revision 2.15.6.1
retrieving revision 2.15.6.2
diff -u -r2.15.6.1 -r2.15.6.2
--- Modules/gcmodule.c	1 Nov 2001 15:34:20 -0000	2.15.6.1
+++ Modules/gcmodule.c	28 Mar 2002 20:41:02 -0000	2.15.6.2
@@ -87,12 +87,14 @@
 static void
 gc_list_remove(PyGC_Head *node)
 {
+	if (node->gc_next == NULL)
+		return;
 	node->gc_prev->gc_next = node->gc_next;
 	node->gc_next->gc_prev = node->gc_prev;
 #ifdef Py_DEBUG
 	node->gc_prev = NULL;
-	node->gc_next = NULL;
 #endif
+	node->gc_next = NULL;
 }
 
 static void 
Index: Objects/dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.76.2.1
retrieving revision 2.76.2.2
diff -u -r2.76.2.1 -r2.76.2.2
--- Objects/dictobject.c	23 May 2001 15:07:55 -0000	2.76.2.1
+++ Objects/dictobject.c	28 Mar 2002 20:41:02 -0000	2.76.2.2
@@ -619,8 +619,8 @@
 {
 	register int i;
 	register dictentry *ep;
-	Py_TRASHCAN_SAFE_BEGIN(mp)
 	PyObject_GC_Fini(mp);
+	Py_TRASHCAN_SAFE_BEGIN(mp)
 	for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
 		if (ep->me_key != NULL) {
 			Py_DECREF(ep->me_key);
Index: Objects/listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92.4.1
retrieving revision 2.92.4.2
diff -u -r2.92.4.1 -r2.92.4.2
--- Objects/listobject.c	6 Jul 2001 17:48:47 -0000	2.92.4.1
+++ Objects/listobject.c	28 Mar 2002 20:41:02 -0000	2.92.4.2
@@ -176,8 +176,8 @@
 list_dealloc(PyListObject *op)
 {
 	int i;
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	PyObject_GC_Fini(op);
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (op->ob_item != NULL) {
 		/* Do it backwards, for Christian Tismer.
 		   There's a simple test case where somehow this reduces
Index: Objects/tupleobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/tupleobject.c,v
retrieving revision 2.48.4.3
retrieving revision 2.48.4.4
diff -u -r2.48.4.3 -r2.48.4.4
--- Objects/tupleobject.c	6 Jul 2001 17:48:47 -0000	2.48.4.3
+++ Objects/tupleobject.c	28 Mar 2002 20:41:02 -0000	2.48.4.4
@@ -143,8 +143,8 @@
 {
 	register int i;
 	register int len =  op->ob_size;
-	Py_TRASHCAN_SAFE_BEGIN(op)
 	PyObject_GC_Fini(op);
+	Py_TRASHCAN_SAFE_BEGIN(op)
 	if (len > 0) {
 		i = len;
 		while (--i >= 0)
Index: Python/ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.238.2.5
retrieving revision 2.238.2.6
diff -u -r2.238.2.5 -r2.238.2.6
--- Python/ceval.c	20 Dec 2001 02:07:36 -0000	2.238.2.5
+++ Python/ceval.c	28 Mar 2002 20:21:21 -0000	2.238.2.6
@@ -414,8 +414,16 @@
 /* Local variable macros */
 
 #define GETLOCAL(i)	(fastlocals[i])
-#define SETLOCAL(i, value)	do { Py_XDECREF(GETLOCAL(i)); \
-				     GETLOCAL(i) = value; } while (0)
+
+/* The SETLOCAL() macro must not DECREF the local variable in-place and
+   then store the new value; it must copy the old value to a temporary
+   value, then store the new value, and then DECREF the temporary value.
+   This is because it is possible that during the DECREF the frame is
+   accessed by other code (e.g. a __del__ method or gc.collect()) and the
+   variable would be pointing to already-freed memory. */
+#define SETLOCAL(i, value)	do { PyObject *tmp = GETLOCAL(i); \
+				     GETLOCAL(i) = value; \
+                                     Py_XDECREF(tmp); } while (0)
 
 /* Start of code */
 
