Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions ext/session/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
/* Leave the record alone, the request decodes it without these limits */
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");
Expand Down
19 changes: 9 additions & 10 deletions ext/session/tests/rfc1867_incomplete_class_reserved_props.phpt
Original file line number Diff line number Diff line change
@@ -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--
Expand All @@ -23,7 +23,9 @@ file_put_contents($worker, '<?php');
* __PHP_Incomplete_Class, which stores the class name of each object and the
* payload of C:/E: entries under these three property names. Data that already
* carries one of them cannot be told apart from that bookkeeping, so the decode
* has to fail rather than let the two meanings be confused. */
* has to fail rather than let the two meanings be confused. The handler then
* skips the update and leaves the record to the request, which decodes it
* without these limits. */
$cases = [
'control' => '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";}',
Expand Down Expand Up @@ -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:'),
Expand All @@ -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
Loading