diff --git a/NEWS b/NEWS index 3346d38ea898..4410bfc0001a 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ PHP NEWS registrations are freed while still reachable from the cycle collector. (Ilia Alshanetsky) +- Session: + . Fixed session data loss in the files save handler when writing the session + file fails after it was already truncated. (Ilia Alshanetsky) + 24 Sep 2026, PHP 8.4.26 diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 74e77973405b..a751c8a4daf3 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -236,11 +236,6 @@ static zend_result ps_files_write(ps_files *data, zend_string *key, zend_string return FAILURE; } - /* Truncate file if the amount of new data is smaller than the existing data set. */ - if (ZSTR_LEN(val) < data->st_size) { - php_ignore_value(ftruncate(data->fd, 0)); - } - #ifdef HAVE_PWRITE n = pwrite(data->fd, ZSTR_VAL(val), ZSTR_LEN(val), 0); #else @@ -274,6 +269,10 @@ static zend_result ps_files_write(ps_files *data, zend_string *key, zend_string return FAILURE; } + if (ZSTR_LEN(val) < data->st_size) { + php_ignore_value(ftruncate(data->fd, ZSTR_LEN(val))); + } + return SUCCESS; } diff --git a/ext/session/tests/session_write_failure_keeps_data.phpt b/ext/session/tests/session_write_failure_keeps_data.phpt new file mode 100644 index 000000000000..e6ca96a4a776 --- /dev/null +++ b/ext/session/tests/session_write_failure_keeps_data.phpt @@ -0,0 +1,58 @@ +--TEST-- +Session files handler must not truncate session file when write fails +--EXTENSIONS-- +session +posix +pcntl +--INI-- +error_reporting=E_ALL +display_errors=1 +session.use_strict_mode=0 +--FILE-- + +--CLEAN-- + +--EXPECT-- +int(8207) +bool(true) +bool(true) +done