From a45ffe71a56741579f648d969193bd027a783e36 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 22 Oct 2026 06:21:47 +0500 Subject: [PATCH 1/2] Fix GH-24493: Upload progress destroys session on reserved property names --- NEWS | 2 ++ ext/session/session.c | 5 +++++ ...c1867_incomplete_class_reserved_props.phpt | 19 +++++++++---------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 12d15e699f1f..a1848fa9bb1d 100644 --- a/NEWS +++ b/NEWS @@ -104,6 +104,8 @@ PHP NEWS - Session: . Fixed session data loss in the files save handler when writing the session file fails after it was already truncated. (Ilia Alshanetsky) + . Fixed bug GH-24493 (Upload progress handler destroys the session when an + object has an incomplete class property name). (Lazizbek Ergashev) - Standard: . Fixed bug GH-24399 (usleep() and time_nanosleep() ignore queued APCs on diff --git a/ext/session/session.c b/ext/session/session.c index 7a57652f55d1..392dbb7a10e7 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -266,6 +266,11 @@ static zend_string *php_session_encode(void) /* {{{ */ static ZEND_COLD void php_session_cancel_decode(void) { + if (PS(in_rfc1867_update)) { + /* The request decodes the data itself later, without the limits of the upload progress handler */ + php_session_abort(); + return; + } php_session_destroy(); php_session_track_init(); php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed"); diff --git a/ext/session/tests/rfc1867_incomplete_class_reserved_props.phpt b/ext/session/tests/rfc1867_incomplete_class_reserved_props.phpt index 954e46b7116b..ee436d57a8f4 100644 --- a/ext/session/tests/rfc1867_incomplete_class_reserved_props.phpt +++ b/ext/session/tests/rfc1867_incomplete_class_reserved_props.phpt @@ -1,5 +1,5 @@ --TEST-- -session rfc1867: the upload progress update rejects session data whose objects carry the incomplete class bookkeeping property names +session rfc1867: the upload progress update leaves session data alone when its objects carry the incomplete class bookkeeping property names --EXTENSIONS-- session --SKIPIF-- @@ -23,7 +23,9 @@ file_put_contents($worker, ' 'x|O:8:"stdClass":1:{s:1:"a";i:1;}', 'Class_Name' => 'x|O:8:"stdClass":1:{s:27:"__PHP_Incomplete_Class_Name";s:3:"foo";}', @@ -109,9 +111,6 @@ foreach ($cases as $label => $record) { fclose($pipes[2]); proc_close($proc); - /* A refused decode must leave exactly one warning: the handler stops there - * instead of writing the progress into the empty session it was left with, - * which would add a second warning about the save path. */ $kept = file_exists($file) && str_starts_with(file_get_contents($file), $record); printf("%-16s warnings: %d, decode refused: %-5s record kept: %s\n", $label, substr_count($out, 'Warning:'), @@ -131,9 +130,9 @@ foreach (glob("$dir/sess_*") as $f) { ?> --EXPECT-- control warnings: 0, decode refused: false record kept: true -Class_Name warnings: 1, decode refused: true record kept: false -Class_Serialized warnings: 1, decode refused: true record kept: false -Enum_Case warnings: 1, decode refused: true record kept: false -nested warnings: 1, decode refused: true record kept: false +Class_Name warnings: 0, decode refused: false record kept: true +Class_Serialized warnings: 0, decode refused: false record kept: true +Enum_Case warnings: 0, decode refused: false record kept: true +nested warnings: 0, decode refused: false record kept: true mangled warnings: 0, decode refused: false record kept: true -corrupt warnings: 1, decode refused: true record kept: false +corrupt warnings: 0, decode refused: false record kept: true From e3f1a200dbe50555ca979ce4569b649f61d5e62e Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 22 Oct 2026 06:24:49 +0500 Subject: [PATCH 2/2] Shorten comment --- ext/session/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/session/session.c b/ext/session/session.c index 392dbb7a10e7..102f36c9a524 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -267,7 +267,7 @@ static zend_string *php_session_encode(void) /* {{{ */ static ZEND_COLD void php_session_cancel_decode(void) { if (PS(in_rfc1867_update)) { - /* The request decodes the data itself later, without the limits of the upload progress handler */ + /* Leave the record alone, the request decodes it without these limits */ php_session_abort(); return; }