[Python-checkins] python/dist/src/Modules gcmodule.c,2.33.6.5,2.33.6.6

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
2003年4月03日 15:02:34 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv26899
Modified Files:
 Tag: release22-maint
	gcmodule.c 
Log Message:
Fix memory corruption in garbage collection.
The move_finalizers() routine checks each object in the unreachable
list to see if it has a finalizer. If it does, it is moved to the
finalizers list. The collector checks by calling, effectively,
hasattr(obj, "__del__"). The hasattr() call can result in an
arbitrary amount of Python code being run, because it will invoke
getattr hooks on obj.
If a getattr() hook is run from move_finalizers(), it may end up
resurrecting or deallocating objects in the unreachable list. In
fact, it's possible that the hook causes the next object in the list
to be deallocated. That is, the object pointed to by gc->gc.gc_next
may be freed before has_finalizer() returns.
The problem with the previous revision is that it followed
gc->gc.gc_next before calling has_finalizer(). If has_finalizer()
gc->happened to deallocate the object FROM_GC(gc->gc.gc_next), then
the next time through the loop gc would point to freed memory. The
fix is to always follow the next pointer after calling
has_finalizer().
Note that Python 2.3 does not have this problem, because
has_finalizer() checks the tp_del slot and never runs Python code.
Tim, Barry, and I peed away the better part of two days tracking this
down.
Index: gcmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/gcmodule.c,v
retrieving revision 2.33.6.5
retrieving revision 2.33.6.6
diff -C2 -d -r2.33.6.5 -r2.33.6.6
*** gcmodule.c	30 Jun 2002 18:48:53 -0000	2.33.6.5
--- gcmodule.c	3 Apr 2003 23:02:29 -0000	2.33.6.6
***************
*** 277,286 ****
 	for (; gc != unreachable; gc=next) {
 		PyObject *op = FROM_GC(gc);
! 		next = gc->gc.gc_next;
 		if (has_finalizer(op)) {
 			gc_list_remove(gc);
 			gc_list_append(gc, finalizers);
 			gc->gc.gc_refs = GC_MOVED;
 		}
 	}
 }
--- 277,290 ----
 	for (; gc != unreachable; gc=next) {
 		PyObject *op = FROM_GC(gc);
! 		/* has_finalizer() may result in arbitrary Python
! 		 code being run. */
 		if (has_finalizer(op)) {
+ 			next = gc->gc.gc_next;
 			gc_list_remove(gc);
 			gc_list_append(gc, finalizers);
 			gc->gc.gc_refs = GC_MOVED;
 		}
+ 		else
+ 			next = gc->gc.gc_next;
 	}
 }

AltStyle によって変換されたページ (->オリジナル) /