Skip to content

Commit 7a2b88d

Browse files
committed
Always record errors during compilation
1 parent 1dd8bf4 commit 7a2b88d

File tree

10 files changed

+68
-30
lines changed

10 files changed

+68
-30
lines changed

Zend/tests/inheritance/deprecation_to_exception_during_inheritance.phpt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Deprecation promoted to exception should result in fatal error during inheritance
2+
Deprecation promoted to exception during inheritance
33
--SKIPIF--
44
<?php
55
if (getenv('SKIP_PRELOAD')) die('skip Error handler not active during preloading');
@@ -17,7 +17,8 @@ $class = new class extends DateTime {
1717

1818
?>
1919
--EXPECTF--
20-
Fatal error: During inheritance of DateTime: Uncaught Exception: 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 in %s:%d
20+
Fatal error: Uncaught Exception: 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 in %s:%d
2121
Stack trace:
2222
#0 %s(%d): {closure:%s:%d}(8192, 'Return type of ...', '%s', 8)
23-
#1 {main} in %s on line %d
23+
#1 {main}
24+
thrown in %s on line %d

Zend/tests/inheritance/gh15907.phpt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,8 @@ class C implements Serializable {
1414

1515
?>
1616
--EXPECTF--
17-
Fatal error: During inheritance of C, while implementing Serializable: Uncaught Exception: C implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s:%d
18-
%a
17+
Fatal error: Uncaught Exception: C implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s:%d
18+
Stack trace:
19+
#0 %s(%d): {closure:%s:%d}(8192, 'C implements th...', '/home/arnaud/de...', 7)
20+
#1 {main}
21+
thrown in %s on line %d

Zend/zend.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,29 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
14641464
EG(num_errors)++;
14651465
EG(errors) = erealloc(EG(errors), sizeof(zend_error_info*) * EG(num_errors));
14661466
EG(errors)[EG(num_errors)-1] = info;
1467+
1468+
/* Fatal errors must be processed immediately */
1469+
if ((type & E_FATAL_ERRORS) && !(type & E_DONT_BAIL)) {
1470+
EG(record_errors) = false;
1471+
1472+
/* Disable user error handler before emitting recorded errors, as
1473+
* it's unsafe to execute user code after a fatal error. */
1474+
int orig_user_error_handler_error_reporting = EG(user_error_handler_error_reporting);
1475+
EG(user_error_handler_error_reporting) = 0;
1476+
1477+
zend_try {
1478+
zend_emit_recorded_errors();
1479+
} zend_catch {
1480+
} zend_end_try();
1481+
1482+
zend_free_recorded_errors();
1483+
EG(user_error_handler_error_reporting) = orig_user_error_handler_error_reporting;
1484+
1485+
zend_bailout();
1486+
}
1487+
1488+
/* Do not process recorded error */
1489+
return;
14671490
}
14681491

14691492
// Always clear the last backtrace.

Zend/zend_compile.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,6 @@ ZEND_API zend_class_entry *zend_bind_class_in_slot(
13331333

13341334
ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
13351335
if (ce) {
1336-
ZEND_ASSERT(!EG(exception));
13371336
zend_observer_class_linked_notify(ce, Z_STR_P(lcname));
13381337
return ce;
13391338
}

Zend/zend_inheritance.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,10 +1085,7 @@ static void ZEND_COLD emit_incompatible_method_error(
10851085
"Return type of %s should either be compatible with %s, "
10861086
"or the #[\\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice",
10871087
ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
1088-
if (EG(exception)) {
1089-
zend_exception_uncaught_error(
1090-
"During inheritance of %s", ZSTR_VAL(parent_scope->name));
1091-
}
1088+
ZEND_ASSERT(!EG(exception));
10921089
}
10931090
} else {
10941091
zend_error_at(E_COMPILE_ERROR, func_filename(child), func_lineno(child),
@@ -3710,6 +3707,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
37103707
/* Do not leak recorded errors to the next linked class. */
37113708
if (!orig_record_errors) {
37123709
EG(record_errors) = false;
3710+
zend_emit_recorded_errors();
37133711
zend_free_recorded_errors();
37143712
}
37153713
zend_bailout();
@@ -3759,6 +3757,7 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
37593757
}
37603758

37613759
if (!orig_record_errors) {
3760+
zend_emit_recorded_errors();
37623761
zend_free_recorded_errors();
37633762
}
37643763
if (traits_and_interfaces) {

Zend/zend_vm_def.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7926,7 +7926,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
79267926
if (zv) {
79277927
SAVE_OPLINE();
79287928
ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
7929-
if (!ce) {
7929+
if (EG(exception)) {
79307930
HANDLE_EXCEPTION();
79317931
}
79327932
}
@@ -7950,7 +7950,7 @@ ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
79507950
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
79517951
SAVE_OPLINE();
79527952
ce = zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key);
7953-
if (!ce) {
7953+
if (EG(exception)) {
79547954
HANDLE_EXCEPTION();
79557955
}
79567956
}

ext/opcache/ZendAccelerator.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,11 +1812,6 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
18121812
orig_functions_count = EG(function_table)->nNumUsed;
18131813
orig_class_count = EG(class_table)->nNumUsed;
18141814

1815-
/* Override them with ours */
1816-
if (ZCG(accel_directives).record_warnings) {
1817-
zend_begin_record_errors();
1818-
}
1819-
18201815
zend_try {
18211816
orig_compiler_options = CG(compiler_options);
18221817
CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY;
@@ -1845,12 +1840,11 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
18451840

18461841
/* Restore originals */
18471842
CG(active_op_array) = orig_active_op_array;
1848-
EG(record_errors) = 0;
18491843

18501844
if (!op_array) {
18511845
/* compilation failed */
1852-
zend_free_recorded_errors();
18531846
if (do_bailout) {
1847+
zend_free_recorded_errors();
18541848
zend_bailout();
18551849
}
18561850
return NULL;
@@ -1865,10 +1859,6 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
18651859
zend_accel_move_user_functions(CG(function_table), CG(function_table)->nNumUsed - orig_functions_count, &new_persistent_script->script);
18661860
zend_accel_move_user_classes(CG(class_table), CG(class_table)->nNumUsed - orig_class_count, &new_persistent_script->script);
18671861
zend_accel_build_delayed_early_binding_list(new_persistent_script);
1868-
new_persistent_script->num_warnings = EG(num_errors);
1869-
new_persistent_script->warnings = EG(errors);
1870-
EG(num_errors) = 0;
1871-
EG(errors) = NULL;
18721862

18731863
efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
18741864

@@ -1962,8 +1952,16 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int
19621952
persistent_script = opcache_compile_file(file_handle, type, &op_array);
19631953

19641954
if (persistent_script) {
1955+
if (ZCG(accel_directives).record_warnings) {
1956+
persistent_script->num_warnings = EG(num_errors);
1957+
persistent_script->warnings = EG(errors);
1958+
}
1959+
19651960
from_memory = false;
19661961
persistent_script = cache_script_in_file_cache(persistent_script, &from_memory);
1962+
1963+
zend_emit_recorded_errors();
1964+
19671965
return zend_accel_load_script(persistent_script, from_memory);
19681966
}
19691967

@@ -2162,6 +2160,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21622160
return accelerator_orig_compile_file(file_handle, type);
21632161
}
21642162

2163+
zend_begin_record_errors();
2164+
21652165
SHM_PROTECT();
21662166
HANDLE_UNBLOCK_INTERRUPTIONS();
21672167
persistent_script = opcache_compile_file(file_handle, type, &op_array);
@@ -2173,6 +2173,11 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21732173
*/
21742174
from_shared_memory = false;
21752175
if (persistent_script) {
2176+
if (ZCG(accel_directives).record_warnings) {
2177+
persistent_script->num_warnings = EG(num_errors);
2178+
persistent_script->warnings = EG(errors);
2179+
}
2180+
21762181
/* See GH-17246: we disable GC so that user code cannot be executed during the optimizer run. */
21772182
bool orig_gc_state = gc_enable(false);
21782183
persistent_script = cache_script_in_shared_memory(persistent_script, key, &from_shared_memory);
@@ -2185,6 +2190,9 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21852190
if (!persistent_script) {
21862191
SHM_PROTECT();
21872192
HANDLE_UNBLOCK_INTERRUPTIONS();
2193+
EG(record_errors) = false;
2194+
zend_emit_recorded_errors();
2195+
zend_free_recorded_errors();
21882196
return op_array;
21892197
}
21902198
if (from_shared_memory) {
@@ -2198,6 +2206,10 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21982206
persistent_script->dynamic_members.last_used = ZCG(request_time);
21992207
SHM_PROTECT();
22002208
HANDLE_UNBLOCK_INTERRUPTIONS();
2209+
2210+
EG(record_errors) = false;
2211+
zend_emit_recorded_errors();
2212+
zend_free_recorded_errors();
22012213
} else {
22022214

22032215
#ifndef ZEND_WIN32
@@ -2461,9 +2473,6 @@ static zend_class_entry* zend_accel_inheritance_cache_add(zend_class_entry *ce,
24612473
entry->next = proto->inheritance_cache;
24622474
proto->inheritance_cache = entry;
24632475

2464-
EG(num_errors) = 0;
2465-
EG(errors) = NULL;
2466-
24672476
ZCSG(map_ptr_last) = CG(map_ptr_last);
24682477

24692478
zend_shared_alloc_destroy_xlat_table();

ext/opcache/tests/gh17422/003.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ warning();
2222
?>
2323
--EXPECTF--
2424
Fatal error: Allowed memory size of 2097152 bytes exhausted %s on line 6
25-
array(2) {
25+
array(3) {
2626
[0]=>
2727
string(7) "003.php"
2828
[1]=>
2929
string(12) "shutdown.inc"
30+
[2]=>
31+
string(11) "warning.inc"
3032
}

ext/opcache/tests/gh17422/004.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ warning();
2828
?>
2929
--EXPECTF--
3030
Fatal error: Cannot redeclare %Swarning() (previously declared in %s(8) : eval()'d code:1) in %swarning.inc on line 2
31-
array(2) {
31+
array(3) {
3232
[0]=>
3333
string(7) "004.php"
3434
[1]=>
3535
string(12) "shutdown.inc"
36+
[2]=>
37+
string(11) "warning.inc"
3638
}

ext/opcache/zend_persist.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,11 +1355,11 @@ static void zend_accel_persist_class_table(HashTable *class_table)
13551355

13561356
zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) {
13571357
if (warnings) {
1358-
warnings = zend_shared_memdup_free(warnings, num_warnings * sizeof(zend_error_info *));
1358+
warnings = zend_shared_memdup(warnings, num_warnings * sizeof(zend_error_info *));
13591359
for (uint32_t i = 0; i < num_warnings; i++) {
1360-
warnings[i] = zend_shared_memdup_free(warnings[i], sizeof(zend_error_info));
13611360
zend_accel_store_string(warnings[i]->filename);
13621361
zend_accel_store_string(warnings[i]->message);
1362+
warnings[i] = zend_shared_memdup(warnings[i], sizeof(zend_error_info));
13631363
}
13641364
}
13651365
return warnings;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy