@@ -312,7 +312,9 @@ call_with_frame(const char *funcname, int lineno, PyObject* func, PyObject* args
312312{
313313 PyObject * res ;
314314
315+ Py_INCREF (func );
315316 res = PyObject_Call (func , args , NULL );
317+ Py_DECREF (func );
316318 if (res == NULL ) {
317319 _PyTraceback_Add (funcname , __FILE__ , lineno );
318320 XML_StopParser (self -> itself , XML_FALSE );
@@ -352,19 +354,25 @@ call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len)
352354 if (!have_handler (self , CharacterData ))
353355 return -1 ;
354356
355- args = PyTuple_New (1 );
356- if (args == NULL )
357- return -1 ;
358- temp = (conv_string_len_to_unicode (buffer , len ));
357+ /* Copy the buffer before tuple allocation can trigger a GC callback. */
358+ temp = conv_string_len_to_unicode (buffer , len );
359359 if (temp == NULL ) {
360- Py_DECREF (args );
361360 flag_error (self );
362361 XML_SetCharacterDataHandler (self -> itself ,
363362 noop_character_data_handler );
364363 return -1 ;
365364 }
365+ args = PyTuple_New (1 );
366+ if (args == NULL ) {
367+ Py_DECREF (temp );
368+ return -1 ;
369+ }
366370 PyTuple_SET_ITEM (args , 0 , temp );
367371 /* temp is now a borrowed reference; consider it unused. */
372+ if (!have_handler (self , CharacterData )) {
373+ Py_DECREF (args );
374+ return 0 ;
375+ }
368376 self -> in_callback = 1 ;
369377 temp = call_with_frame ("CharacterData" , __LINE__ ,
370378 self -> handlers [CharacterData ], args , self );
@@ -384,12 +392,13 @@ call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len)
384392static int
385393flush_character_buffer (xmlparseobject * self )
386394{
387- int rc ;
388395 if (self -> buffer == NULL || self -> buffer_used == 0 )
389396 return 0 ;
390- rc = call_character_handler (self , self -> buffer , self -> buffer_used );
397+ int len = self -> buffer_used ;
398+ /* The callback may change buffering or install a new handler, which
399+ also flushes. Do not expose the same pending data a second time. */
391400 self -> buffer_used = 0 ;
392- return rc ;
401+ return call_character_handler ( self , self -> buffer , len ) ;
393402}
394403
395404static void
@@ -400,27 +409,22 @@ my_CharacterDataHandler(void *userData, const XML_Char *data, int len)
400409 if (PyErr_Occurred ())
401410 return ;
402411
403- if (self -> buffer == NULL )
412+ if (self -> buffer != NULL &&
413+ len > (self -> buffer_size - self -> buffer_used )) {
414+ if (flush_character_buffer (self ) < 0 )
415+ return ;
416+ /* The callback may replace the handler or disable buffering. */
417+ if (!have_handler (self , CharacterData ))
418+ return ;
419+ }
420+ if (self -> buffer == NULL ||
421+ len > (self -> buffer_size - self -> buffer_used )) {
404422 call_character_handler (self , data , len );
423+ }
405424 else {
406- if (len > (self -> buffer_size - self -> buffer_used )) {
407- if (flush_character_buffer (self ) < 0 )
408- return ;
409- /* handler might have changed; drop the rest on the floor
410- * if there isn't a handler anymore
411- */
412- if (!have_handler (self , CharacterData ))
413- return ;
414- }
415- if (len > self -> buffer_size ) {
416- call_character_handler (self , data , len );
417- self -> buffer_used = 0 ;
418- }
419- else {
420- memcpy (self -> buffer + self -> buffer_used ,
421- data , len * sizeof (XML_Char ));
422- self -> buffer_used += len ;
423- }
425+ memcpy (self -> buffer + self -> buffer_used ,
426+ data , len * sizeof (XML_Char ));
427+ self -> buffer_used += len ;
424428 }
425429}
426430
@@ -451,7 +455,9 @@ my_StartElementHandler(void *userData,
451455 max += 2 ;
452456 }
453457 /* Build the container. */
454- if (self -> ordered_attributes )
458+ /* Intern-dictionary comparisons can change the mode mid-loop. */
459+ int ordered_attributes = self -> ordered_attributes ;
460+ if (ordered_attributes )
455461 container = PyList_New (max );
456462 else
457463 container = PyDict_New ();
@@ -474,7 +480,7 @@ my_StartElementHandler(void *userData,
474480 Py_DECREF (n );
475481 return ;
476482 }
477- if (self -> ordered_attributes ) {
483+ if (ordered_attributes ) {
478484 PyList_SET_ITEM (container , i , n );
479485 PyList_SET_ITEM (container , i + 1 , v );
480486 }
@@ -500,6 +506,10 @@ my_StartElementHandler(void *userData,
500506 return ;
501507 }
502508 /* Container is now a borrowed reference; ignore it. */
509+ if (!have_handler (self , StartElement )) {
510+ Py_DECREF (args );
511+ return ;
512+ }
503513 self -> in_callback = 1 ;
504514 rv = call_with_frame ("StartElement" , __LINE__ ,
505515 self -> handlers [StartElement ], args , self );
@@ -534,6 +544,10 @@ my_ ## NAME ## Handler PARAMS { \
534544 flag_error(self); \
535545 return RETURN_VARIABLE; \
536546 } \
547+ if (!have_handler(self, NAME)) { \
548+ Py_DECREF(args); \
549+ return RETURN_VARIABLE; \
550+ } \
537551 self->in_callback = 1; \
538552 PyObject *rv = call_with_frame( \
539553 #NAME, __LINE__, \
@@ -679,6 +693,9 @@ my_ElementDeclHandler(void *userData,
679693 flag_error (self );
680694 goto finally ;
681695 }
696+ if (!have_handler (self , ElementDecl )) {
697+ goto finally ;
698+ }
682699 self -> in_callback = 1 ;
683700 rv = call_with_frame ("ElementDecl" , __LINE__ ,
684701 self -> handlers [ElementDecl ], args , self );
0 commit comments