@@ -934,6 +934,7 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
934
934
return PHP_OUTPUT_HANDLER_FAILURE ;
935
935
}
936
936
937
+ bool still_have_handler = true;
937
938
/* storable? */
938
939
if (php_output_handler_append (handler , & context -> in ) && !context -> op ) {
939
940
context -> op = original_op ;
@@ -971,7 +972,22 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
971
972
"Returning a non-string result from user output handler %s is deprecated" ,
972
973
ZSTR_VAL (handler -> name )
973
974
);
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
+ }
975
991
}
976
992
if (Z_TYPE (retval ) == IS_FALSE ) {
977
993
/* call failed, pass internal buffer along */
@@ -1013,14 +1029,18 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
1013
1029
status = PHP_OUTPUT_HANDLER_FAILURE ;
1014
1030
}
1015
1031
}
1016
- handler -> flags |= PHP_OUTPUT_HANDLER_STARTED ;
1032
+ if (still_have_handler ) {
1033
+ handler -> flags |= PHP_OUTPUT_HANDLER_STARTED ;
1034
+ }
1017
1035
OG (running ) = NULL ;
1018
1036
}
1019
1037
1020
1038
switch (status ) {
1021
1039
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
+ }
1024
1044
/* discard any output */
1025
1045
if (context -> out .data && context -> out .free ) {
1026
1046
efree (context -> out .data );
@@ -1029,18 +1049,22 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
1029
1049
context -> out .data = handler -> buffer .data ;
1030
1050
context -> out .used = handler -> buffer .used ;
1031
1051
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
+ }
1035
1057
break ;
1036
1058
case PHP_OUTPUT_HANDLER_NO_DATA :
1037
1059
/* handler ate all */
1038
1060
php_output_context_reset (context );
1039
1061
ZEND_FALLTHROUGH ;
1040
1062
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
+ }
1044
1068
break ;
1045
1069
}
1046
1070
@@ -1242,6 +1266,19 @@ static int php_output_stack_pop(int flags)
1242
1266
}
1243
1267
php_output_handler_op (orphan , & context );
1244
1268
}
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
+ }
1245
1282
1246
1283
/* pop it off the stack */
1247
1284
zend_stack_del_top (& OG (handlers ));
@@ -1257,7 +1294,9 @@ static int php_output_stack_pop(int flags)
1257
1294
}
1258
1295
1259
1296
/* destroy the handler (after write!) */
1260
- php_output_handler_free (& orphan );
1297
+ if (still_have_handler ) {
1298
+ php_output_handler_free (& orphan );
1299
+ }
1261
1300
php_output_context_dtor (& context );
1262
1301
1263
1302
return 1 ;
0 commit comments