Skip to content

Commit f4c3fde

Browse files
Deprecate returning non-string values from a user output handler
https://wiki.php.net/rfc/deprecations_php_8_4
1 parent aea3ade commit f4c3fde

File tree

4 files changed

+41
-14
lines changed

4 files changed

+41
-14
lines changed

UPGRADING

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ PHP 8.5 UPGRADE NOTES
258258
4. Deprecated Functionality
259259
========================================
260260

261+
- Core:
262+
. Returning a non-string from a user output handler is deprecated. The
263+
deprecation warning will bypass user output handlers to ensure it is
264+
visible.
265+
RFC: https://wiki.php.net/rfc/deprecations_php_8_4
266+
261267
- Hash:
262268
. The MHASH_* constants have been deprecated. These have been overlooked
263269
when the mhash*() function family has been deprecated per

main/output.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
948948
if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
949949
zval ob_args[2];
950950
zval retval;
951+
ZVAL_UNDEF(&retval);
951952

952953
/* ob_data */
953954
ZVAL_STRINGL(&ob_args[0], handler->buffer.data, handler->buffer.used);
@@ -959,17 +960,33 @@ static inline php_output_handler_status_t php_output_handler_op(php_output_handl
959960
handler->func.user->fci.params = ob_args;
960961
handler->func.user->fci.retval = &retval;
961962

962-
#define PHP_OUTPUT_USER_SUCCESS(retval) ((Z_TYPE(retval) != IS_UNDEF) && !(Z_TYPE(retval) == IS_FALSE))
963-
if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && PHP_OUTPUT_USER_SUCCESS(retval)) {
964-
/* user handler may have returned TRUE */
965-
status = PHP_OUTPUT_HANDLER_NO_DATA;
966-
if (Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) {
967-
convert_to_string(&retval);
968-
if (Z_STRLEN(retval)) {
969-
context->out.data = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
970-
context->out.used = Z_STRLEN(retval);
971-
context->out.free = 1;
972-
status = PHP_OUTPUT_HANDLER_SUCCESS;
963+
if (SUCCESS == zend_call_function(&handler->func.user->fci, &handler->func.user->fcc) && Z_TYPE(retval) != IS_UNDEF) {
964+
if (Z_TYPE(retval) != IS_STRING) {
965+
// Make sure that we don't get lost in an output buffer
966+
int old_flags = OG(flags);
967+
OG(flags) = old_flags & (~PHP_OUTPUT_ACTIVATED);
968+
php_error_docref(
969+
NULL,
970+
E_DEPRECATED,
971+
"Returning a non-string result from user output handler %s is deprecated",
972+
ZSTR_VAL(handler->name)
973+
);
974+
OG(flags) = old_flags;
975+
}
976+
if (Z_TYPE(retval) == IS_FALSE) {
977+
/* call failed, pass internal buffer along */
978+
status = PHP_OUTPUT_HANDLER_FAILURE;
979+
} else {
980+
/* user handler may have returned TRUE */
981+
status = PHP_OUTPUT_HANDLER_NO_DATA;
982+
if (Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) {
983+
convert_to_string(&retval);
984+
if (Z_STRLEN(retval)) {
985+
context->out.data = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
986+
context->out.used = Z_STRLEN(retval);
987+
context->out.free = 1;
988+
status = PHP_OUTPUT_HANDLER_SUCCESS;
989+
}
973990
}
974991
}
975992
} else {

tests/output/bug60768.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Bug #60768 Output buffer not discarded
55

66
global $storage;
77

8-
ob_start(function($buffer) use (&$storage) { $storage .= $buffer; }, 20);
8+
ob_start(function($buffer) use (&$storage) { $storage .= $buffer; return ''; }, 20);
99

1010
echo str_repeat("0", 20); // fill in the buffer
1111

tests/output/ob_start_basic_002.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,23 @@ foreach ($callbacks as $callback) {
3535
}
3636

3737
?>
38-
--EXPECT--
38+
--EXPECTF--
3939
--> Use callback 'return_empty_string':
4040

4141

4242
--> Use callback 'return_false':
4343
My output.
44+
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_false is deprecated in %s on line %d
45+
4446

4547
--> Use callback 'return_null':
4648

4749

50+
51+
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_null is deprecated in %s on line %d
4852
--> Use callback 'return_string':
4953
I stole your output.
5054

5155
--> Use callback 'return_zero':
5256
0
53-
57+
Deprecated: ob_end_flush(): Returning a non-string result from user output handler return_zero is deprecated in %s on line %d

0 commit comments

Comments
 (0)