diff --git a/NEWS b/NEWS index 425455c5bcce4..55875b8dd3b50 100644 --- a/NEWS +++ b/NEWS @@ -35,6 +35,10 @@ PHP NEWS . Fixed bug GH-13138 (Randomizer::pickArrayKeys() does not detect broken engines). (timwolla) +- Session: + . Fixed bug GH-12504 (Corrupted session written when there's a fatal error + in autoloader). (nielsdos) + - Streams: . Fixed bug GH-13071 (Copying large files using mmap-able source streams may exhaust available memory and fail). (nielsdos) diff --git a/ext/session/session.c b/ext/session/session.c index 6998432147f9c..6b63999297205 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -246,18 +246,28 @@ static zend_string *php_session_encode(void) /* {{{ */ } /* }}} */ +static ZEND_COLD void php_session_cancel_decode(void) +{ + php_session_destroy(); + php_session_track_init(); + php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed"); +} + static zend_result php_session_decode(zend_string *data) /* {{{ */ { if (!PS(serializer)) { php_error_docref(NULL, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object"); return FAILURE; } - if (PS(serializer)->decode(ZSTR_VAL(data), ZSTR_LEN(data)) == FAILURE) { - php_session_destroy(); - php_session_track_init(); - php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed"); - return FAILURE; - } + zend_try { + if (PS(serializer)->decode(ZSTR_VAL(data), ZSTR_LEN(data)) == FAILURE) { + php_session_cancel_decode(); + return FAILURE; + } + } zend_catch { + php_session_cancel_decode(); + zend_bailout(); + } zend_end_try(); return SUCCESS; } /* }}} */ diff --git a/ext/session/tests/gh12504.phpt b/ext/session/tests/gh12504.phpt new file mode 100644 index 0000000000000..eb19424eb5005 --- /dev/null +++ b/ext/session/tests/gh12504.phpt @@ -0,0 +1,62 @@ +--TEST-- +GH-12504 (Corrupted session written when there's a fatal error in autoloader) +--EXTENSIONS-- +session +--FILE-- + +--EXPECTF-- +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 + +Warning: Unknown: Failed to decode session object. Session has been destroyed in Unknown on line 0 +In shutdown function +array(0) { +}