mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Deprecate producing output in a user output handler (#19067)
https://wiki.php.net/rfc/deprecations_php_8_4
This commit is contained in:
parent
964a404451
commit
07f1cfd9b0
21 changed files with 1075 additions and 20 deletions
|
@ -265,6 +265,12 @@ PHP 8.5 UPGRADE NOTES
|
||||||
it is visible; if there are nested output handlers the next one will still
|
it is visible; if there are nested output handlers the next one will still
|
||||||
be used.
|
be used.
|
||||||
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
|
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
|
||||||
|
. Trying to produce output (e.g. with `echo`) within a user output handler
|
||||||
|
is deprecated. The deprecation warning will bypass the handler producing the
|
||||||
|
output to ensure it is visible; if there are nested output handlers the next
|
||||||
|
one will still be used. If a user output handler returns a non-string and
|
||||||
|
produces output, the warning about producing an output is emitted first.
|
||||||
|
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
|
||||||
|
|
||||||
- Hash:
|
- Hash:
|
||||||
. The MHASH_* constants have been deprecated. These have been overlooked
|
. The MHASH_* constants have been deprecated. These have been overlooked
|
||||||
|
|
|
@ -1584,12 +1584,24 @@ PHP_FUNCTION(mb_output_handler)
|
||||||
if (SG(sapi_headers).send_default_content_type || free_mimetype) {
|
if (SG(sapi_headers).send_default_content_type || free_mimetype) {
|
||||||
const char *charset = encoding->mime_name;
|
const char *charset = encoding->mime_name;
|
||||||
if (charset) {
|
if (charset) {
|
||||||
|
/* Don't try to add a header if we are in an output handler;
|
||||||
|
* we aren't supposed to directly access the output globals
|
||||||
|
* from outside of main/output.c, so just try to get the flags
|
||||||
|
* for the currently running handler, will only succeed if
|
||||||
|
* there is a handler running. */
|
||||||
|
int unused;
|
||||||
|
bool in_handler = php_output_handler_hook(
|
||||||
|
PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS,
|
||||||
|
&unused
|
||||||
|
) == SUCCESS;
|
||||||
|
if (!in_handler) {
|
||||||
char *p;
|
char *p;
|
||||||
size_t len = spprintf(&p, 0, "Content-Type: %s; charset=%s", mimetype, charset);
|
size_t len = spprintf(&p, 0, "Content-Type: %s; charset=%s", mimetype, charset);
|
||||||
if (sapi_add_header(p, len, 0) != FAILURE) {
|
if (sapi_add_header(p, len, 0) != FAILURE) {
|
||||||
SG(sapi_headers).send_default_content_type = 0;
|
SG(sapi_headers).send_default_content_type = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MBSTRG(outconv_enabled) = true;
|
MBSTRG(outconv_enabled) = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -934,6 +934,13 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
|
||||||
return PHP_OUTPUT_HANDLER_FAILURE;
|
return PHP_OUTPUT_HANDLER_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* php_output_lock_error() doesn't fail for PHP_OUTPUT_HANDLER_WRITE but
|
||||||
|
* anything that gets written will silently be discarded, remember that we
|
||||||
|
* tried to write so a deprecation warning can be emitted at the end. */
|
||||||
|
if (context->op == PHP_OUTPUT_HANDLER_WRITE && OG(active) && OG(running)) {
|
||||||
|
handler->flags |= PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
bool still_have_handler = true;
|
bool still_have_handler = true;
|
||||||
/* storable? */
|
/* storable? */
|
||||||
if (php_output_handler_append(handler, &context->in) && !context->op) {
|
if (php_output_handler_append(handler, &context->in) && !context->op) {
|
||||||
|
@ -962,16 +969,37 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
|
||||||
handler->func.user->fci.retval = &retval;
|
handler->func.user->fci.retval = &retval;
|
||||||
|
|
||||||
if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && Z_TYPE(retval) != IS_UNDEF) {
|
if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && Z_TYPE(retval) != IS_UNDEF) {
|
||||||
if (Z_TYPE(retval) != IS_STRING) {
|
if (Z_TYPE(retval) != IS_STRING || handler->flags & PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT) {
|
||||||
// Make sure that we don't get lost in the current output buffer
|
// Make sure that we don't get lost in the current output buffer
|
||||||
// by disabling it
|
// by disabling it
|
||||||
handler->flags |= PHP_OUTPUT_HANDLER_DISABLED;
|
handler->flags |= PHP_OUTPUT_HANDLER_DISABLED;
|
||||||
|
// Make sure we keep a reference to the handler name in
|
||||||
|
// case
|
||||||
|
// * The handler produced output *and* returned a non-string
|
||||||
|
// * The first deprecation message causes the handler to
|
||||||
|
// be removed
|
||||||
|
zend_string *handler_name = handler->name;
|
||||||
|
zend_string_addref(handler_name);
|
||||||
|
if (handler->flags & PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT) {
|
||||||
|
// The handler might not always produce output
|
||||||
|
handler->flags &= ~PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT;
|
||||||
|
php_error_docref(
|
||||||
|
NULL,
|
||||||
|
E_DEPRECATED,
|
||||||
|
"Producing output from user output handler %s is deprecated",
|
||||||
|
ZSTR_VAL(handler_name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (Z_TYPE(retval) != IS_STRING) {
|
||||||
php_error_docref(
|
php_error_docref(
|
||||||
NULL,
|
NULL,
|
||||||
E_DEPRECATED,
|
E_DEPRECATED,
|
||||||
"Returning a non-string result from user output handler %s is deprecated",
|
"Returning a non-string result from user output handler %s is deprecated",
|
||||||
ZSTR_VAL(handler->name)
|
ZSTR_VAL(handler_name)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
zend_string_release(handler_name);
|
||||||
|
|
||||||
// Check if the handler is still in the list of handlers to
|
// Check if the handler is still in the list of handlers to
|
||||||
// determine if the PHP_OUTPUT_HANDLER_DISABLED flag can
|
// determine if the PHP_OUTPUT_HANDLER_DISABLED flag can
|
||||||
// be removed
|
// be removed
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#define PHP_OUTPUT_HANDLER_STARTED 0x1000
|
#define PHP_OUTPUT_HANDLER_STARTED 0x1000
|
||||||
#define PHP_OUTPUT_HANDLER_DISABLED 0x2000
|
#define PHP_OUTPUT_HANDLER_DISABLED 0x2000
|
||||||
#define PHP_OUTPUT_HANDLER_PROCESSED 0x4000
|
#define PHP_OUTPUT_HANDLER_PROCESSED 0x4000
|
||||||
|
#define PHP_OUTPUT_HANDLER_PRODUCED_OUTPUT 0x8000
|
||||||
|
|
||||||
#define PHP_OUTPUT_HANDLER_ABILITY_FLAGS(bitmask) ((bitmask) & ~0xf00f)
|
#define PHP_OUTPUT_HANDLER_ABILITY_FLAGS(bitmask) ((bitmask) & ~0xf00f)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
ob_start(): Check behaviour with deprecation converted to exception
|
ob_start(): Check behaviour with deprecation converted to exception [bad return]
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
ob_start(): Check behaviour with deprecation converted to exception
|
ob_start(): Check behaviour with nested deprecation converted to exception [bad return]
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
ob_start(): Check behaviour with multiple nested handlers with had return values
|
ob_start(): Check behaviour with multiple nested handlers with bad return values
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
@ -69,21 +69,38 @@ echo "\n\nLog:\n";
|
||||||
echo implode("\n", $log);
|
echo implode("\n", $log);
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_given_string is deprecated in %s on line %d3
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d2
|
||||||
|
|
||||||
|
|
||||||
Log:
|
Log:
|
||||||
return_zero: <<<Testing...>>>
|
return_zero: <<<Testing...>>>
|
||||||
return_string: <<<
|
return_string: <<<
|
||||||
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d
|
||||||
0>>>
|
0>>>
|
||||||
return_null: <<<I stole your output.>>>
|
return_null: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_string is deprecated in %s on line %d
|
||||||
|
I stole your output.>>>
|
||||||
return_true: <<<
|
return_true: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s on line %d
|
||||||
|
|
||||||
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d
|
||||||
>>>
|
>>>
|
||||||
return_false: <<<
|
return_false: <<<
|
||||||
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d
|
||||||
>>>
|
|
||||||
return_empty_string: <<<
|
|
||||||
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d
|
|
||||||
|
|
||||||
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
||||||
>>>
|
>>>
|
||||||
return_given_string: <<<>>>
|
return_empty_string: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
||||||
|
>>>
|
||||||
|
return_given_string: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d2
|
||||||
|
>>>
|
||||||
|
|
88
tests/output/ob_start_callback_output/exception_handler.phpt
Normal file
88
tests/output/ob_start_callback_output/exception_handler.phpt
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation converted to exception [produce output]
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
|
||||||
|
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||||
|
});
|
||||||
|
|
||||||
|
function first_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "FIRST\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function second_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "SECOND\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function third_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "THIRD\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$cases = [
|
||||||
|
'first_handler',
|
||||||
|
'second_handler',
|
||||||
|
'third_handler',
|
||||||
|
];
|
||||||
|
foreach ($cases as $case) {
|
||||||
|
$log = [];
|
||||||
|
echo "\n\nTesting: $case\n";
|
||||||
|
ob_start($case);
|
||||||
|
echo "Inside of $case\n";
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e . "\n";
|
||||||
|
}
|
||||||
|
echo "\nEnd of $case, log was:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Testing: first_handler
|
||||||
|
FIRST
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler first_handler is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of first_handler, log was:
|
||||||
|
first_handler: <<<Inside of first_handler
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: second_handler
|
||||||
|
SECOND
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler second_handler is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of second_handler, log was:
|
||||||
|
second_handler: <<<Inside of second_handler
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: third_handler
|
||||||
|
THIRD
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler third_handler is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, 41)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of third_handler, log was:
|
||||||
|
third_handler: <<<Inside of third_handler
|
||||||
|
>>>
|
|
@ -0,0 +1,82 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with nested deprecation converted to exception [produce output]
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
|
||||||
|
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||||
|
});
|
||||||
|
|
||||||
|
function first_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "FIRST\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function second_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "SECOND\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function third_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "THIRD\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('first_handler');
|
||||||
|
ob_start('second_handler');
|
||||||
|
ob_start('third_handler');
|
||||||
|
|
||||||
|
echo "In all of them\n\n";
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended third_handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended second_handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended first_handler handler\n\n";
|
||||||
|
|
||||||
|
echo "All handlers are over\n\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
FIRST
|
||||||
|
ob_end_flush(): Producing output from user output handler first_handler is deprecated
|
||||||
|
Ended first_handler handler
|
||||||
|
|
||||||
|
All handlers are over
|
||||||
|
|
||||||
|
third_handler: <<<In all of them
|
||||||
|
|
||||||
|
>>>
|
||||||
|
second_handler: <<<THIRD
|
||||||
|
ob_end_flush(): Producing output from user output handler third_handler is deprecated
|
||||||
|
Ended third_handler
|
||||||
|
|
||||||
|
>>>
|
||||||
|
first_handler: <<<SECOND
|
||||||
|
ob_end_flush(): Producing output from user output handler second_handler is deprecated
|
||||||
|
Ended second_handler
|
||||||
|
|
||||||
|
>>>
|
|
@ -0,0 +1,84 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with functions that trigger output (nested)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
function handle_echo($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "echo\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_var_dump($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
var_dump(__FUNCTION__);
|
||||||
|
return "var_dump\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_var_export($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
var_export(__FUNCTION__);
|
||||||
|
return "var_export\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_phpcredits($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
phpcredits();
|
||||||
|
return "phpcredits\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$cases = [
|
||||||
|
'handle_echo',
|
||||||
|
'handle_var_dump',
|
||||||
|
'handle_var_export',
|
||||||
|
'handle_phpcredits',
|
||||||
|
];
|
||||||
|
foreach ($cases as $case) {
|
||||||
|
$log = [];
|
||||||
|
echo "\n\nTesting: $case";
|
||||||
|
ob_start($case);
|
||||||
|
echo "Inside of $case\n";
|
||||||
|
ob_end_flush();
|
||||||
|
echo "\nEnd of $case, log was:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Testing: handle_echo
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_echo is deprecated in %s on line %d
|
||||||
|
echo
|
||||||
|
|
||||||
|
End of handle_echo, log was:
|
||||||
|
handle_echo: <<<Inside of handle_echo
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: handle_var_dump
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_var_dump is deprecated in %s on line %d
|
||||||
|
var_dump
|
||||||
|
|
||||||
|
End of handle_var_dump, log was:
|
||||||
|
handle_var_dump: <<<Inside of handle_var_dump
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: handle_var_export
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_var_export is deprecated in %s on line %d
|
||||||
|
var_export
|
||||||
|
|
||||||
|
End of handle_var_export, log was:
|
||||||
|
handle_var_export: <<<Inside of handle_var_export
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: handle_phpcredits
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_phpcredits is deprecated in %s on line %d
|
||||||
|
phpcredits
|
||||||
|
|
||||||
|
End of handle_phpcredits, log was:
|
||||||
|
handle_phpcredits: <<<Inside of handle_phpcredits
|
||||||
|
>>>
|
|
@ -0,0 +1,69 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with functions that trigger output (nested)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
function handle_echo($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "echo\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_var_dump($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
var_dump(__FUNCTION__);
|
||||||
|
return "var_dump\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_var_export($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
var_export(__FUNCTION__);
|
||||||
|
return "var_export\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_phpcredits($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
phpcredits();
|
||||||
|
return "phpcredits\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('handle_echo');
|
||||||
|
ob_start('handle_var_dump');
|
||||||
|
ob_start('handle_var_export');
|
||||||
|
ob_start('handle_phpcredits');
|
||||||
|
|
||||||
|
echo "Testing...";
|
||||||
|
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
echo "\n\nLog:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_echo is deprecated in %s on line %d
|
||||||
|
echo
|
||||||
|
|
||||||
|
|
||||||
|
Log:
|
||||||
|
handle_phpcredits: <<<Testing...>>>
|
||||||
|
handle_var_export: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_phpcredits is deprecated in %s on line %d
|
||||||
|
phpcredits
|
||||||
|
>>>
|
||||||
|
handle_var_dump: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_var_export is deprecated in %s on line %d
|
||||||
|
var_export
|
||||||
|
>>>
|
||||||
|
handle_echo: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler handle_var_dump is deprecated in %s on line %d
|
||||||
|
var_dump
|
||||||
|
>>>
|
|
@ -0,0 +1,49 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with handler that doesn't always trigger output
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
function handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
if ($string === "DO ECHO\n") {
|
||||||
|
echo __FUNCTION__;
|
||||||
|
}
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('handler');
|
||||||
|
echo "DO ECHO\n";
|
||||||
|
ob_flush();
|
||||||
|
echo "NO ECHO\n";
|
||||||
|
ob_flush();
|
||||||
|
echo "DO ECHO\n";
|
||||||
|
ob_flush();
|
||||||
|
echo "LAST ONE\n";
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
echo "\n\nLog:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: ob_flush(): Producing output from user output handler handler is deprecated in %s on line %d
|
||||||
|
DO ECHO
|
||||||
|
NO ECHO
|
||||||
|
|
||||||
|
Deprecated: ob_flush(): Producing output from user output handler handler is deprecated in %s on line %d
|
||||||
|
DO ECHO
|
||||||
|
LAST ONE
|
||||||
|
|
||||||
|
|
||||||
|
Log:
|
||||||
|
handler: <<<DO ECHO
|
||||||
|
>>>
|
||||||
|
handler: <<<NO ECHO
|
||||||
|
>>>
|
||||||
|
handler: <<<DO ECHO
|
||||||
|
>>>
|
||||||
|
handler: <<<LAST ONE
|
||||||
|
>>>
|
56
tests/output/ob_start_callback_output/multiple_handlers.phpt
Normal file
56
tests/output/ob_start_callback_output/multiple_handlers.phpt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with multiple nested handlers with output
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
function first_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "FIRST\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function second_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "SECOND\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function third_handler($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "THIRD\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('first_handler');
|
||||||
|
ob_start('second_handler');
|
||||||
|
ob_start('third_handler');
|
||||||
|
|
||||||
|
echo "Testing...";
|
||||||
|
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
echo "\n\nLog:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler first_handler is deprecated in %s on line %d
|
||||||
|
FIRST
|
||||||
|
|
||||||
|
|
||||||
|
Log:
|
||||||
|
third_handler: <<<Testing...>>>
|
||||||
|
second_handler: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler third_handler is deprecated in %s on line %d
|
||||||
|
THIRD
|
||||||
|
>>>
|
||||||
|
first_handler: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler second_handler is deprecated in %s on line %d
|
||||||
|
SECOND
|
||||||
|
>>>
|
|
@ -0,0 +1,153 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation converted to exception [bad return + produce output]
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class NotStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
}
|
||||||
|
class IsStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
public function __toString() {
|
||||||
|
return __CLASS__ . ": " . $this->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
|
||||||
|
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||||
|
});
|
||||||
|
|
||||||
|
function return_null($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_false($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_true($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_zero($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_non_stringable($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return new NotStringable($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_stringable($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return new IsStringable($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cases = [
|
||||||
|
'return_null',
|
||||||
|
'return_false',
|
||||||
|
'return_true',
|
||||||
|
'return_zero',
|
||||||
|
'return_non_stringable',
|
||||||
|
'return_stringable',
|
||||||
|
];
|
||||||
|
foreach ($cases as $case) {
|
||||||
|
$log = [];
|
||||||
|
echo "\n\nTesting: $case\n";
|
||||||
|
ob_start($case);
|
||||||
|
echo "Inside of $case\n";
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e . "\n";
|
||||||
|
}
|
||||||
|
echo "\nEnd of $case, log was:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Testing: return_null
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_null, log was:
|
||||||
|
return_null: <<<Inside of return_null
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: return_false
|
||||||
|
Inside of return_false
|
||||||
|
return_falseErrorException: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_false, log was:
|
||||||
|
return_false: <<<Inside of return_false
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: return_true
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_true, log was:
|
||||||
|
return_true: <<<Inside of return_true
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: return_zero
|
||||||
|
0ErrorException: ob_end_flush(): Producing output from user output handler return_zero is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_zero, log was:
|
||||||
|
return_zero: <<<Inside of return_zero
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: return_non_stringable
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler return_non_stringable is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_non_stringable, log was:
|
||||||
|
return_non_stringable: <<<Inside of return_non_stringable
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Testing: return_stringable
|
||||||
|
ErrorException: ob_end_flush(): Producing output from user output handler return_stringable is deprecated in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 [internal function]: {closure:%s:%d}(8192, 'ob_end_flush():...', %s, %d)
|
||||||
|
#1 %s(%d): ob_end_flush()
|
||||||
|
#2 {main}
|
||||||
|
|
||||||
|
End of return_stringable, log was:
|
||||||
|
return_stringable: <<<Inside of return_stringable
|
||||||
|
>>>
|
|
@ -0,0 +1,149 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with nested deprecation converted to exception [bad return + produce output]
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class NotStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
}
|
||||||
|
class IsStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
public function __toString() {
|
||||||
|
return __CLASS__ . ": " . $this->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) {
|
||||||
|
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||||
|
});
|
||||||
|
|
||||||
|
function return_null($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_false($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_true($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_zero($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_non_stringable($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return new NotStringable($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_stringable($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return new IsStringable($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('return_null');
|
||||||
|
ob_start('return_false');
|
||||||
|
ob_start('return_true');
|
||||||
|
ob_start('return_zero');
|
||||||
|
ob_start('return_non_stringable');
|
||||||
|
ob_start('return_stringable');
|
||||||
|
|
||||||
|
echo "In all of them\n\n";
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_stringable handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_non_stringable handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_zero handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_true handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_false handler\n\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
ob_end_flush();
|
||||||
|
} catch (\ErrorException $e) {
|
||||||
|
echo $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
echo "Ended return_null handler\n\n";
|
||||||
|
|
||||||
|
echo "All handlers are over\n\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
ob_end_flush(): Producing output from user output handler return_null is deprecated
|
||||||
|
Ended return_null handler
|
||||||
|
|
||||||
|
All handlers are over
|
||||||
|
|
||||||
|
return_stringable: <<<In all of them
|
||||||
|
|
||||||
|
>>>
|
||||||
|
return_non_stringable: <<<ob_end_flush(): Producing output from user output handler return_stringable is deprecated
|
||||||
|
Ended return_stringable handler
|
||||||
|
|
||||||
|
>>>
|
||||||
|
return_zero: <<<ob_end_flush(): Producing output from user output handler return_non_stringable is deprecated
|
||||||
|
Ended return_non_stringable handler
|
||||||
|
|
||||||
|
>>>
|
||||||
|
return_true: <<<0ob_end_flush(): Producing output from user output handler return_zero is deprecated
|
||||||
|
Ended return_zero handler
|
||||||
|
|
||||||
|
>>>
|
||||||
|
return_false: <<<ob_end_flush(): Producing output from user output handler return_true is deprecated
|
||||||
|
Ended return_true handler
|
||||||
|
|
||||||
|
>>>
|
||||||
|
return_null: <<<ob_end_flush(): Producing output from user output handler return_true is deprecated
|
||||||
|
Ended return_true handler
|
||||||
|
|
||||||
|
return_falseob_end_flush(): Producing output from user output handler return_false is deprecated
|
||||||
|
Ended return_false handler
|
||||||
|
|
||||||
|
>>>
|
|
@ -0,0 +1,26 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns false + produces output)
|
||||||
|
--INI--
|
||||||
|
memory_limit=2M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
ob_start(function() {
|
||||||
|
// We are out of memory, now trigger a deprecation
|
||||||
|
echo "IN HANDLER\n";
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
// trigger OOM in a resize operation
|
||||||
|
while (1) {
|
||||||
|
$a[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
|
@ -0,0 +1,33 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns stringable object + produces output)
|
||||||
|
--INI--
|
||||||
|
memory_limit=2M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class IsStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
public function __toString() {
|
||||||
|
return __CLASS__ . ": " . $this->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start(function() {
|
||||||
|
// We are out of memory, now trigger a deprecation
|
||||||
|
echo "IN HANDLER\n";
|
||||||
|
return new IsStringable("");
|
||||||
|
});
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
// trigger OOM in a resize operation
|
||||||
|
while (1) {
|
||||||
|
$a[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
|
@ -0,0 +1,35 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns non-stringable object + produces output)
|
||||||
|
--INI--
|
||||||
|
memory_limit=2M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class NotStringable {
|
||||||
|
public function __construct(public string $val) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start(function() {
|
||||||
|
// We are out of memory, now trigger a deprecation
|
||||||
|
echo "IN HANDLER\n";
|
||||||
|
return new NotStringable("");
|
||||||
|
});
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
// trigger OOM in a resize operation
|
||||||
|
while (1) {
|
||||||
|
$a[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Uncaught Error: Object of class NotStringable could not be converted to string in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 {main}
|
||||||
|
thrown in %s on line %d
|
|
@ -0,0 +1,26 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns true + produces output)
|
||||||
|
--INI--
|
||||||
|
memory_limit=2M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
ob_start(function() {
|
||||||
|
// We are out of memory, now trigger a deprecation
|
||||||
|
echo "IN HANDLER\n";
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
// trigger OOM in a resize operation
|
||||||
|
while (1) {
|
||||||
|
$a[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
|
@ -0,0 +1,26 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with deprecation when OOM triggers handler removal (handler returns zero + produces output)
|
||||||
|
--INI--
|
||||||
|
memory_limit=2M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
ob_start(function() {
|
||||||
|
// We are out of memory, now trigger a deprecation
|
||||||
|
echo "IN HANDLER\n";
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
$a = [];
|
||||||
|
// trigger OOM in a resize operation
|
||||||
|
while (1) {
|
||||||
|
$a[] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: main(): Producing output from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: main(): Returning a non-string result from user output handler {closure:%s:%d} is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
|
@ -0,0 +1,115 @@
|
||||||
|
--TEST--
|
||||||
|
ob_start(): Check behaviour with multiple nested handlers with bad return values and output
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$log = [];
|
||||||
|
|
||||||
|
function return_given_string($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_empty_string($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_false($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_true($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_null($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_string($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return "I stole your output.";
|
||||||
|
}
|
||||||
|
|
||||||
|
function return_zero($string) {
|
||||||
|
global $log;
|
||||||
|
$log[] = __FUNCTION__ . ": <<<" . $string . ">>>";
|
||||||
|
echo __FUNCTION__;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start('return_given_string');
|
||||||
|
ob_start('return_empty_string');
|
||||||
|
ob_start('return_false');
|
||||||
|
ob_start('return_true');
|
||||||
|
ob_start('return_null');
|
||||||
|
ob_start('return_string');
|
||||||
|
ob_start('return_zero');
|
||||||
|
|
||||||
|
echo "Testing...";
|
||||||
|
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
ob_end_flush();
|
||||||
|
|
||||||
|
echo "\n\nLog:\n";
|
||||||
|
echo implode("\n", $log);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_given_string is deprecated in %s on line %d0
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d9
|
||||||
|
|
||||||
|
|
||||||
|
Log:
|
||||||
|
return_zero: <<<Testing...>>>
|
||||||
|
return_string: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_zero is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d
|
||||||
|
0>>>
|
||||||
|
return_null: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_string is deprecated in %s on line %d5
|
||||||
|
I stole your output.>>>
|
||||||
|
return_true: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_null is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d
|
||||||
|
>>>
|
||||||
|
return_false: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
||||||
|
>>>
|
||||||
|
return_empty_string: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_false is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_true is deprecated in %s on line %d
|
||||||
|
|
||||||
|
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_true is deprecated in %s on line %d
|
||||||
|
return_false>>>
|
||||||
|
return_given_string: <<<
|
||||||
|
Deprecated: ob_end_flush(): Producing output from user output handler return_empty_string is deprecated in %s on line %d9
|
||||||
|
>>>
|
Loading…
Add table
Add a link
Reference in a new issue