diff --git a/ext/session/session.c b/ext/session/session.c index ef97f856499f..d3b4146a1e5f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -526,6 +526,7 @@ static void php_session_save_current_state(bool write) /* Not being able to encode the session data means there is some kind of issue that prevents a write * (e.g. a key containing the '|' character with the default serialization) */ if (UNEXPECTED(val == NULL)) { + PS(mod)->s_close(&PS(mod_data)); return; } diff --git a/ext/session/tests/session_write_close_encode_failure.phpt b/ext/session/tests/session_write_close_encode_failure.phpt new file mode 100644 index 000000000000..1c562f401df2 --- /dev/null +++ b/ext/session/tests/session_write_close_encode_failure.phpt @@ -0,0 +1,76 @@ +--TEST-- +session_write_close() closes the save handler when encoding the session data fails +--EXTENSIONS-- +session +--SKIPIF-- + +--INI-- +session.use_cookies=0 +session.cache_limiter= +session.serialize_handler=php +session.save_handler=files +--FILE-- +getMessage(), PHP_EOL; +} + +$fp = fopen($file, 'r'); +var_dump(flock($fp, LOCK_EX | LOCK_NB)); +fclose($fp); + +class Handler extends SessionHandler +{ + public function close(): bool + { + echo "close\n"; + return parent::close(); + } +} + +session_set_save_handler(new Handler()); +session_start(); +$_SESSION['bad|key'] = 'value'; +var_dump(session_write_close()); +echo "done\n"; +?> +--CLEAN-- + +--EXPECTF-- +Warning: session_write_close(): Failed to write session data. Data contains invalid key "bad|key" in %s on line %d +bool(true) +bool(true) + +Warning: session_write_close(): Failed to write session data. Data contains invalid key "bad|key" in %s on line %d +Exception: Serialization of 'Closure' is not allowed +bool(true) + +Warning: session_write_close(): Failed to write session data. Data contains invalid key "bad|key" in %s on line %d +close +bool(true) +done