Skip to content

Commit 0acb52f

Browse files
author
Ilia Alshanetsky
committed
Fixed bug #21228 (broken check for ob_gzhandler).
Fixed a bug that made ob_start return incorrect return value.
1 parent 67f0a6f commit 0acb52f

File tree

3 files changed

+44
-31
lines changed

3 files changed

+44
-31
lines changed

ext/zlib/php_zlib.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ PHP_FUNCTION(gzencode);
5454
PHP_FUNCTION(ob_gzhandler);
5555

5656
int php_enable_output_compression(int buffer_size TSRMLS_DC);
57+
int php_ob_gzhandler_check(TSRMLS_DC);
5758

5859
php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
5960
extern php_stream_ops php_stream_gzio_ops;

ext/zlib/zlib.c

+28-18
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,34 @@ PHP_FUNCTION(gzencode)
890890
}
891891
/* }}} */
892892

893+
/* {{{ php_ob_gzhandler_check
894+
*/
895+
int php_ob_gzhandler_check(TSRMLS_DC)
896+
{
897+
/* check for wrong usages */
898+
if (OG(ob_nesting_level>0)) {
899+
if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
900+
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");
901+
return FAILURE;
902+
}
903+
if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
904+
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'");
905+
return FAILURE;
906+
}
907+
if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) {
908+
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'");
909+
return FAILURE;
910+
}
911+
if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC)) {
912+
return FAILURE;
913+
}
914+
}
915+
916+
return SUCCESS;
917+
}
918+
919+
/* }}} */
920+
893921
/* {{{ proto string ob_gzhandler(string str, int mode)
894922
Encode str based on accept-encoding setting - designed to be called from ob_start() */
895923
PHP_FUNCTION(ob_gzhandler)
@@ -904,24 +932,6 @@ PHP_FUNCTION(ob_gzhandler)
904932
ZEND_WRONG_PARAM_COUNT();
905933
}
906934

907-
/* check for wrong usages */
908-
if (OG(ob_nesting_level>1)) {
909-
if (php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
910-
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used twice");
911-
RETURN_FALSE;
912-
}
913-
if (php_ob_handler_used("mb_output_handler" TSRMLS_CC)) {
914-
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'mb_output_handler'");
915-
RETURN_FALSE;
916-
}
917-
if (php_ob_handler_used("URL-Rewriter" TSRMLS_CC)) {
918-
php_error_docref("ref.outcontrol" TSRMLS_CC, E_WARNING, "output handler 'ob_gzhandler' cannot be used after 'URL-Rewriter'");
919-
RETURN_FALSE;
920-
}
921-
if (php_ob_init_conflict("ob_gzhandler", "zlib output compression" TSRMLS_CC))
922-
RETURN_FALSE;
923-
}
924-
925935
if (ZLIBG(ob_gzhandler_status)==-1
926936
|| zend_hash_find(&EG(symbol_table), "HTTP_SERVER_VARS", sizeof("HTTP_SERVER_VARS"), (void **) &data)==FAILURE
927937
|| Z_TYPE_PP(data)!=IS_ARRAY

main/output.c

+15-13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "ext/standard/head.h"
2525
#include "ext/standard/basic_functions.h"
2626
#include "ext/standard/url_scanner_ex.h"
27+
#ifdef HAVE_ZLIB
28+
#include "ext/zlib/php_zlib.h"
29+
#endif
2730
#include "SAPI.h"
2831

2932
#define OB_DEFAULT_HANDLER_NAME "default output handler"
@@ -405,6 +408,11 @@ PHPAPI int php_ob_init_conflict(char *handler_new, char *handler_set TSRMLS_DC)
405408
static int php_ob_init_named(uint initial_size, uint block_size, char *handler_name, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
406409
{
407410
if (OG(ob_nesting_level)>0) {
411+
#ifdef HAVE_ZLIB
412+
if (!strncmp(handler_name, "ob_gzhandler", sizeof("ob_gzhandler")) && php_ob_gzhandler_check(TSRMLS_CC)) {
413+
return FAILURE;
414+
}
415+
#endif
408416
if (OG(ob_nesting_level)==1) { /* initialize stack */
409417
zend_stack_init(&OG(ob_buffers));
410418
}
@@ -420,7 +428,7 @@ static int php_ob_init_named(uint initial_size, uint block_size, char *handler_n
420428
OG(active_ob_buffer).status = 0;
421429
OG(active_ob_buffer).internal_output_handler = NULL;
422430
OG(active_ob_buffer).handler_name = estrdup(handler_name&&handler_name[0]?handler_name:OB_DEFAULT_HANDLER_NAME);
423-
OG(active_ob_buffer).erase = erase;
431+
OG(active_ob_buffer).erase = erase;
424432
OG(php_body_write) = php_b_body_write;
425433
return SUCCESS;
426434
}
@@ -445,38 +453,33 @@ static zval* php_ob_handler_from_string(const char *handler_name TSRMLS_DC)
445453
*/
446454
static int php_ob_init(uint initial_size, uint block_size, zval *output_handler, uint chunk_size, zend_bool erase TSRMLS_DC)
447455
{
448-
int res, result, len;
456+
int result, len;
449457
char *handler_name, *next_handler_name;
450458
HashPosition pos;
451459
zval **tmp;
452460
zval *handler_zval;
453461

454462
if (output_handler && output_handler->type == IS_STRING) {
455-
result = 0;
456463
handler_name = Z_STRVAL_P(output_handler);
457464
while ((next_handler_name=strchr(handler_name, ',')) != NULL) {
458465
len = next_handler_name-handler_name;
459466
next_handler_name = estrndup(handler_name, len);
460467
handler_zval = php_ob_handler_from_string(next_handler_name TSRMLS_CC);
461-
res = php_ob_init_named(initial_size, block_size, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
462-
result &= res;
463-
if (!res==SUCCESS) {
468+
result = php_ob_init_named(initial_size, block_size, next_handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
469+
if (result != SUCCESS) {
464470
zval_dtor(handler_zval);
465471
FREE_ZVAL(handler_zval);
466472
}
467473
handler_name += len+1;
468474
efree(next_handler_name);
469475
}
470476
handler_zval = php_ob_handler_from_string(handler_name TSRMLS_CC);
471-
res = php_ob_init_named(initial_size, block_size, handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
472-
result &= res;
473-
if (!res==SUCCESS) {
477+
result = php_ob_init_named(initial_size, block_size, handler_name, handler_zval, chunk_size, erase TSRMLS_CC);
478+
if (result != SUCCESS) {
474479
zval_dtor(handler_zval);
475480
FREE_ZVAL(handler_zval);
476481
}
477-
result = result ? SUCCESS : FAILURE;
478482
} else if (output_handler && output_handler->type == IS_ARRAY) {
479-
result = 0;
480483
/* do we have array(object,method) */
481484
if (zend_is_callable(output_handler, 1, &handler_name)) {
482485
SEPARATE_ZVAL(&output_handler);
@@ -487,11 +490,10 @@ static int php_ob_init(uint initial_size, uint block_size, zval *output_handler,
487490
/* init all array elements recursively */
488491
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(output_handler), &pos);
489492
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(output_handler), (void **)&tmp, &pos) == SUCCESS) {
490-
result &= php_ob_init(initial_size, block_size, *tmp, chunk_size, erase TSRMLS_CC);
493+
result = php_ob_init(initial_size, block_size, *tmp, chunk_size, erase TSRMLS_CC);
491494
zend_hash_move_forward_ex(Z_ARRVAL_P(output_handler), &pos);
492495
}
493496
}
494-
result = result ? SUCCESS : FAILURE;
495497
} else if (output_handler && output_handler->type == IS_OBJECT) {
496498
php_error_docref(NULL TSRMLS_CC, E_ERROR, "No method name given: use ob_start(array($object,'method')) to specify instance $object and the name of a method of class %s to use as output handler", Z_OBJCE_P(output_handler)->name);
497499
result = FAILURE;

0 commit comments

Comments
 (0)