Skip to content

Commit 4338079

Browse files
committed
Unify non-opcache behavior
1 parent 6b0cabc commit 4338079

19 files changed

+208
-94
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Deprecation promoted to exception during inheritance
3+
--SKIPIF--
4+
<?php
5+
if (getenv('SKIP_PRELOAD')) die('skip Error handler not active during preloading');
6+
?>
7+
--FILE--
8+
<?php
9+
10+
set_error_handler(function($code, $message) {
11+
throw new Exception($message);
12+
});
13+
14+
try {
15+
class C extends DateTime {
16+
public function getTimezone() {}
17+
public function getTimestamp() {}
18+
};
19+
} catch (Exception $e) {
20+
printf("%s: %s\n", $e::class, $e->getMessage());
21+
}
22+
23+
var_dump(new C());
24+
25+
?>
26+
--EXPECTF--
27+
Exception: Return type of C::getTimezone() should either be compatible with DateTime::getTimezone(): DateTimeZone|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice
28+
object(C)#%d (3) {
29+
["date"]=>
30+
string(%d) "%s"
31+
["timezone_type"]=>
32+
int(3)
33+
["timezone"]=>
34+
string(3) "UTC"
35+
}

Zend/zend_inheritance.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,8 +3543,6 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
35433543
}
35443544
#endif
35453545

3546-
bool orig_record_errors = EG(record_errors);
3547-
35483546
if (ce->ce_flags & ZEND_ACC_IMMUTABLE && is_cacheable) {
35493547
if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
35503548
zend_class_entry *ret = zend_inheritance_cache_get(ce, parent, traits_and_interfaces);
@@ -3556,16 +3554,21 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
35563554
Z_CE_P(zv) = ret;
35573555
return ret;
35583556
}
3559-
3560-
/* Make sure warnings (such as deprecations) thrown during inheritance
3561-
* will be recorded in the inheritance cache. */
3562-
zend_begin_record_errors();
35633557
} else {
35643558
is_cacheable = 0;
35653559
}
35663560
proto = ce;
35673561
}
35683562

3563+
/* Delay and record warnings (such as deprecations) thrown during
3564+
* inheritance, so they will be recorded in the inheritance cache.
3565+
* Warnings must be delayed in all cases so that we get a consistent
3566+
* behavior regardless of cacheability. */
3567+
bool orig_record_errors = EG(record_errors);
3568+
if (!orig_record_errors) {
3569+
zend_begin_record_errors();
3570+
}
3571+
35693572
zend_try {
35703573
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
35713574
/* Lazy class loading */
@@ -3917,10 +3920,12 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
39173920
orig_linking_class = CG(current_linking_class);
39183921
CG(current_linking_class) = is_cacheable ? ce : NULL;
39193922

3923+
bool orig_record_errors = EG(record_errors);
3924+
39203925
zend_try{
39213926
CG(zend_lineno) = ce->info.user.line_start;
39223927

3923-
if (is_cacheable) {
3928+
if (!orig_record_errors) {
39243929
zend_begin_record_errors();
39253930
}
39263931

@@ -3942,13 +3947,13 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
39423947

39433948
CG(current_linking_class) = orig_linking_class;
39443949
} zend_catch {
3945-
EG(record_errors) = false;
3946-
zend_free_recorded_errors();
3950+
if (!orig_record_errors) {
3951+
EG(record_errors) = false;
3952+
zend_free_recorded_errors();
3953+
}
39473954
zend_bailout();
39483955
} zend_end_try();
39493956

3950-
EG(record_errors) = false;
3951-
39523957
if (is_cacheable) {
39533958
HashTable *ht = (HashTable*)ce->inheritance_cache;
39543959
zend_class_entry *new_ce;
@@ -3966,6 +3971,11 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
39663971
}
39673972
}
39683973

3974+
if (!orig_record_errors) {
3975+
zend_emit_recorded_errors();
3976+
zend_free_recorded_errors();
3977+
}
3978+
39693979
if (ZSTR_HAS_CE_CACHE(ce->name)) {
39703980
ZSTR_SET_CE_CACHE(ce->name, ce);
39713981
}

Zend/zend_language_scanner.l

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,17 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
650650
}
651651
}
652652
} else {
653+
bool orig_record_errors = EG(record_errors);
654+
if (!orig_record_errors) {
655+
zend_begin_record_errors();
656+
}
657+
653658
op_array = zend_compile(ZEND_USER_FUNCTION);
659+
660+
if (!orig_record_errors) {
661+
zend_emit_recorded_errors();
662+
zend_free_recorded_errors();
663+
}
654664
}
655665

656666
zend_restore_lexical_state(&original_lex_state);

ext/opcache/tests/gh17422/001.phpt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
--TEST--
22
GH-17422 (OPcache bypasses the user-defined error handler for deprecations)
3-
--INI--
4-
opcache.enable=1
5-
opcache.enable_cli=1
6-
--EXTENSIONS--
7-
opcache
83
--FILE--
94
<?php
105

11-
require __DIR__ . "/shutdown.inc";
12-
136
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
147
echo "set_error_handler: {$errstr}", PHP_EOL;
158
});
@@ -22,11 +15,3 @@ warning();
2215
--EXPECT--
2316
set_error_handler: "continue" targeting switch is equivalent to "break"
2417
OK: warning
25-
array(3) {
26-
[0]=>
27-
string(7) "001.php"
28-
[1]=>
29-
string(12) "shutdown.inc"
30-
[2]=>
31-
string(11) "warning.inc"
32-
}

ext/opcache/tests/gh17422/002.phpt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
--TEST--
22
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Throwing error handler
3-
--INI--
4-
opcache.enable=1
5-
opcache.enable_cli=1
6-
--EXTENSIONS--
7-
opcache
83
--FILE--
94
<?php
105

11-
require __DIR__ . "/shutdown.inc";
12-
136
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
147
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
158
});
@@ -26,11 +19,3 @@ warning();
2619
--EXPECT--
2720
Caught: "continue" targeting switch is equivalent to "break"
2821
OK: warning
29-
array(3) {
30-
[0]=>
31-
string(7) "002.php"
32-
[1]=>
33-
string(12) "shutdown.inc"
34-
[2]=>
35-
string(11) "warning.inc"
36-
}

ext/opcache/tests/gh17422/003.phpt

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
--TEST--
22
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Fatal Error
3-
--INI--
4-
opcache.enable=1
5-
opcache.enable_cli=1
6-
memory_limit=2M
7-
--EXTENSIONS--
8-
opcache
93
--FILE--
104
<?php
115

12-
require __DIR__ . "/shutdown.inc";
13-
146
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
15-
str_repeat('x', 1024 * 1024 * 1024);
7+
function fatal_error() {}
8+
function fatal_error() {}
169
});
1710

1811
require __DIR__ . "/warning.inc";
@@ -21,12 +14,4 @@ warning();
2114

2215
?>
2316
--EXPECTF--
24-
Fatal error: Allowed memory size of 2097152 bytes exhausted %s on line 6
25-
array(3) {
26-
[0]=>
27-
string(7) "003.php"
28-
[1]=>
29-
string(12) "shutdown.inc"
30-
[2]=>
31-
string(11) "warning.inc"
32-
}
17+
Fatal error: Cannot redeclare function fatal_error() (previously declared in %s:%d) in %s on line %d

ext/opcache/tests/gh17422/004.phpt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
--TEST--
22
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - eval
3-
--INI--
4-
opcache.enable=1
5-
opcache.enable_cli=1
6-
memory_limit=2M
7-
--EXTENSIONS--
8-
opcache
93
--FILE--
104
<?php
115

12-
require __DIR__ . "/shutdown.inc";
13-
146
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
157
eval(
168
<<<'PHP'
@@ -27,12 +19,4 @@ warning();
2719

2820
?>
2921
--EXPECTF--
30-
Fatal error: Cannot redeclare %Swarning() (previously declared in %s(8) : eval()'d code:1) in %swarning.inc on line 2
31-
array(3) {
32-
[0]=>
33-
string(7) "004.php"
34-
[1]=>
35-
string(12) "shutdown.inc"
36-
[2]=>
37-
string(11) "warning.inc"
38-
}
22+
Fatal error: Cannot redeclare function warning() %s

ext/opcache/tests/gh17422/005.phpt

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
--TEST--
22
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - require
3-
--INI--
4-
opcache.enable=1
5-
opcache.enable_cli=1
6-
memory_limit=2M
7-
--EXTENSIONS--
8-
opcache
93
--FILE--
104
<?php
115

12-
require __DIR__ . "/shutdown.inc";
13-
146
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
157
require_once __DIR__ . "/dummy.inc";
168
});
@@ -22,13 +14,3 @@ dummy();
2214
?>
2315
--EXPECT--
2416
OK: dummy
25-
array(4) {
26-
[0]=>
27-
string(7) "005.php"
28-
[1]=>
29-
string(9) "dummy.inc"
30-
[2]=>
31-
string(12) "shutdown.inc"
32-
[3]=>
33-
string(11) "warning.inc"
34-
}

ext/opcache/tests/gh17422/006.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - File cache
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_cache={TMP}
7+
opcache.file_cache_only=1
8+
opcache.record_warnings=1
9+
--EXTENSIONS--
10+
opcache
11+
--FILE--
12+
<?php
13+
14+
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
15+
echo "set_error_handler: {$errstr}", PHP_EOL;
16+
});
17+
18+
require __DIR__ . "/warning.inc";
19+
20+
warning();
21+
22+
?>
23+
--EXPECT--
24+
set_error_handler: "continue" targeting switch is equivalent to "break"
25+
OK: warning

ext/opcache/tests/gh17422/007.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
GH-17422 (OPcache bypasses the user-defined error handler for deprecations) - Fatal after warning
3+
--FILE--
4+
<?php
5+
6+
set_error_handler(static function (int $errno, string $errstr, string $errfile, int $errline) {
7+
echo "set_error_handler: {$errstr}", PHP_EOL;
8+
});
9+
10+
require __DIR__ . "/warning-fatal.inc";
11+
12+
warning();
13+
14+
?>
15+
--EXPECTF--
16+
Warning: "continue" targeting switch is equivalent to "break" in %s on line %d
17+
18+
Fatal error: Cannot redeclare function warning() (previously declared in %s:%d) in %s on line %d

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