File tree 3 files changed +82
-6
lines changed
3 files changed +82
-6
lines changed Original file line number Diff line number Diff line change @@ -44,6 +44,10 @@ PHP NEWS
44
44
. Fixed bug GH-13138 (Randomizer::pickArrayKeys() does not detect broken
45
45
engines). (timwolla)
46
46
47
+ - Session:
48
+ . Fixed bug GH-12504 (Corrupted session written when there's a fatal error
49
+ in autoloader). (nielsdos)
50
+
47
51
- Standard:
48
52
. Fixed bug GH-13094 (range(9.9, '0') causes segmentation fault). (nielsdos)
49
53
Original file line number Diff line number Diff line change @@ -258,18 +258,28 @@ static zend_string *php_session_encode(void) /* {{{ */
258
258
}
259
259
/* }}} */
260
260
261
+ static ZEND_COLD void php_session_cancel_decode (void )
262
+ {
263
+ php_session_destroy ();
264
+ php_session_track_init ();
265
+ php_error_docref (NULL , E_WARNING , "Failed to decode session object. Session has been destroyed" );
266
+ }
267
+
261
268
static zend_result php_session_decode (zend_string * data ) /* {{{ */
262
269
{
263
270
if (!PS (serializer )) {
264
271
php_error_docref (NULL , E_WARNING , "Unknown session.serialize_handler. Failed to decode session object" );
265
272
return FAILURE ;
266
273
}
267
- if (PS (serializer )-> decode (ZSTR_VAL (data ), ZSTR_LEN (data )) == FAILURE ) {
268
- php_session_destroy ();
269
- php_session_track_init ();
270
- php_error_docref (NULL , E_WARNING , "Failed to decode session object. Session has been destroyed" );
271
- return FAILURE ;
272
- }
274
+ zend_try {
275
+ if (PS (serializer )-> decode (ZSTR_VAL (data ), ZSTR_LEN (data )) == FAILURE ) {
276
+ php_session_cancel_decode ();
277
+ return FAILURE ;
278
+ }
279
+ } zend_catch {
280
+ php_session_cancel_decode ();
281
+ zend_bailout ();
282
+ } zend_end_try ();
273
283
return SUCCESS ;
274
284
}
275
285
/* }}} */
Original file line number Diff line number Diff line change
1
+ --TEST--
2
+ GH-12504 (Corrupted session written when there's a fatal error in autoloader)
3
+ --EXTENSIONS--
4
+ session
5
+ --FILE--
6
+ <?php
7
+
8
+ class TestSessionHandler implements SessionHandlerInterface
9
+ {
10
+ public function close (): bool
11
+ {
12
+ return true ;
13
+ }
14
+ public function destroy (string $ id ): bool
15
+ {
16
+ return true ;
17
+ }
18
+ public function gc (int $ max_lifetime ): int |false
19
+ {
20
+ return 0 ;
21
+ }
22
+ public function open (string $ path , string $ name ): bool
23
+ {
24
+ return true ;
25
+ }
26
+ public function read (string $ id ): string |false
27
+ {
28
+ // Return a session object that has 3 variables
29
+ return 'before|i:1234;test|O:4:"Test":0:{}after|i:5678; ' ;
30
+ }
31
+ public function write ($ id , $ data ): bool
32
+ {
33
+ echo 'Write session: ' . PHP_EOL ;
34
+ echo $ data . PHP_EOL ;
35
+ return true ;
36
+ }
37
+ }
38
+
39
+ register_shutdown_function (function () {
40
+ echo "In shutdown function \n" ;
41
+ var_dump ($ _SESSION );
42
+ });
43
+
44
+ session_set_save_handler (new TestSessionHandler ());
45
+
46
+ // Autoload class that's in session
47
+ spl_autoload_register (function () {
48
+ // Easiest way to reproduce the issue is to dynamically define a class with a bogus definition
49
+ eval ('class Test {public int $var = null;} ' );
50
+ return true ;
51
+ });
52
+
53
+ session_start ();
54
+
55
+ ?>
56
+ --EXPECTF--
57
+ Fatal error: Default value for property of type int may not be null. Use the nullable type ?int to allow null default value in %s on line %d
58
+
59
+ Warning: Unknown: Failed to decode session object. Session has been destroyed in Unknown on line 0
60
+ In shutdown function
61
+ array(0) {
62
+ }
You can’t perform that action at this time.
0 commit comments