Skip to content

Commit c6a53f9

Browse files
committed
Fix non-reentirant startiong or error recording from error handler
Fixes oss-fuzz #45398
1 parent f16d35c commit c6a53f9

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

Zend/tests/record_errors_001.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Error recording in error handler
3+
--FILE--
4+
<?php
5+
set_error_handler(function($code, $msg) {
6+
echo "Error: $msg\n";
7+
new class extends DateTime {
8+
};
9+
});
10+
new class extends DateTime {
11+
function getTimezone() {}
12+
};
13+
?>
14+
--EXPECT--
15+
Error: Return type of DateTime@anonymous::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice

Zend/zend.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,10 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
13431343
zend_stack loop_var_stack;
13441344
zend_stack delayed_oplines_stack;
13451345
int type = orig_type & E_ALL;
1346+
bool orig_record_errors;
1347+
uint32_t orig_num_errors;
1348+
zend_error_info **orig_errors;
1349+
zend_result res;
13461350

13471351
/* If we're executing a function during SCCP, count any warnings that may be emitted,
13481352
* but don't perform any other error handling. */
@@ -1436,7 +1440,20 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
14361440
CG(in_compilation) = 0;
14371441
}
14381442

1439-
if (call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params) == SUCCESS) {
1443+
orig_record_errors = EG(record_errors);
1444+
orig_num_errors = EG(num_errors);
1445+
orig_errors = EG(errors);
1446+
EG(record_errors) = false;
1447+
EG(num_errors) = 0;
1448+
EG(errors) = NULL;
1449+
1450+
res = call_user_function(CG(function_table), NULL, &orig_user_error_handler, &retval, 4, params);
1451+
1452+
EG(record_errors) = orig_record_errors;
1453+
EG(num_errors) = orig_num_errors;
1454+
EG(errors) = orig_errors;
1455+
1456+
if (res == SUCCESS) {
14401457
if (Z_TYPE(retval) != IS_UNDEF) {
14411458
if (Z_TYPE(retval) == IS_FALSE) {
14421459
zend_error_cb(orig_type, error_filename, error_lineno, message);

0 commit comments

Comments
 (0)