@@ -934,6 +934,7 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
934934 return PHP_OUTPUT_HANDLER_FAILURE ;
935935 }
936936
937+ bool still_have_handler = true;
937938 /* storable? */
938939 if (php_output_handler_append (handler , & context -> in ) && !context -> op ) {
939940 context -> op = original_op ;
@@ -971,7 +972,22 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
971972 "Returning a non-string result from user output handler %s is deprecated" ,
972973 ZSTR_VAL (handler -> name )
973974 );
974- handler -> flags &= (~PHP_OUTPUT_HANDLER_DISABLED );
975+ // Check if the handler is still in the list of handlers to
976+ // determine if the PHP_OUTPUT_HANDLER_DISABLED flag can
977+ // be removed
978+ still_have_handler = false;
979+ int handler_count = php_output_get_level ();
980+ if (handler_count ) {
981+ php_output_handler * * handlers = (php_output_handler * * ) zend_stack_base (& OG (handlers ));
982+ for (int iii = 0 ; iii < handler_count ; ++ iii ) {
983+ php_output_handler * curr_handler = handlers [iii ];
984+ if (curr_handler == handler ) {
985+ handler -> flags &= (~PHP_OUTPUT_HANDLER_DISABLED );
986+ still_have_handler = true;
987+ break ;
988+ }
989+ }
990+ }
975991 }
976992 if (Z_TYPE (retval ) == IS_FALSE ) {
977993 /* call failed, pass internal buffer along */
@@ -1013,14 +1029,18 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
10131029 status = PHP_OUTPUT_HANDLER_FAILURE ;
10141030 }
10151031 }
1016- handler -> flags |= PHP_OUTPUT_HANDLER_STARTED ;
1032+ if (still_have_handler ) {
1033+ handler -> flags |= PHP_OUTPUT_HANDLER_STARTED ;
1034+ }
10171035 OG (running ) = NULL ;
10181036 }
10191037
10201038 switch (status ) {
10211039 case PHP_OUTPUT_HANDLER_FAILURE :
1022- /* disable this handler */
1023- handler -> flags |= PHP_OUTPUT_HANDLER_DISABLED ;
1040+ if (still_have_handler ) {
1041+ /* disable this handler */
1042+ handler -> flags |= PHP_OUTPUT_HANDLER_DISABLED ;
1043+ }
10241044 /* discard any output */
10251045 if (context -> out .data && context -> out .free ) {
10261046 efree (context -> out .data );
@@ -1029,18 +1049,22 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
10291049 context -> out .data = handler -> buffer .data ;
10301050 context -> out .used = handler -> buffer .used ;
10311051 context -> out .free = 1 ;
1032- handler -> buffer .data = NULL ;
1033- handler -> buffer .used = 0 ;
1034- handler -> buffer .size = 0 ;
1052+ if (still_have_handler ) {
1053+ handler -> buffer .data = NULL ;
1054+ handler -> buffer .used = 0 ;
1055+ handler -> buffer .size = 0 ;
1056+ }
10351057 break ;
10361058 case PHP_OUTPUT_HANDLER_NO_DATA :
10371059 /* handler ate all */
10381060 php_output_context_reset (context );
10391061 ZEND_FALLTHROUGH ;
10401062 case PHP_OUTPUT_HANDLER_SUCCESS :
1041- /* no more buffered data */
1042- handler -> buffer .used = 0 ;
1043- handler -> flags |= PHP_OUTPUT_HANDLER_PROCESSED ;
1063+ if (still_have_handler ) {
1064+ /* no more buffered data */
1065+ handler -> buffer .used = 0 ;
1066+ handler -> flags |= PHP_OUTPUT_HANDLER_PROCESSED ;
1067+ }
10441068 break ;
10451069 }
10461070
@@ -1242,6 +1266,19 @@ static int php_output_stack_pop(int flags)
12421266 }
12431267 php_output_handler_op (orphan , & context );
12441268 }
1269+ // If it isn't still in the stack, cannot free it
1270+ bool still_have_handler = false;
1271+ int handler_count = php_output_get_level ();
1272+ if (handler_count ) {
1273+ php_output_handler * * handlers = (php_output_handler * * ) zend_stack_base (& OG (handlers ));
1274+ for (int iii = 0 ; iii < handler_count ; ++ iii ) {
1275+ php_output_handler * curr_handler = handlers [iii ];
1276+ if (curr_handler == orphan ) {
1277+ still_have_handler = true;
1278+ break ;
1279+ }
1280+ }
1281+ }
12451282
12461283 /* pop it off the stack */
12471284 zend_stack_del_top (& OG (handlers ));
@@ -1257,7 +1294,9 @@ static int php_output_stack_pop(int flags)
12571294 }
12581295
12591296 /* destroy the handler (after write!) */
1260- php_output_handler_free (& orphan );
1297+ if (still_have_handler ) {
1298+ php_output_handler_free (& orphan );
1299+ }
12611300 php_output_context_dtor (& context );
12621301
12631302 return 1 ;
0 commit comments