Skip to content

Unify headers already sent/session already started error handler #16451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
108 changes: 48 additions & 60 deletions ext/session/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ zend_class_entry *php_session_update_timestamp_iface_entry;

#define SESSION_CHECK_ACTIVE_STATE \
if (PS(session_status) == php_session_active) { \
php_error_docref(NULL, E_WARNING, "Session ini settings cannot be changed when a session is active"); \
php_session_session_already_started_error(E_WARNING, "Session ini settings cannot be changed when a session is active"); \
return FAILURE; \
}

#define SESSION_CHECK_OUTPUT_STATE \
if (SG(headers_sent) && stage != ZEND_INI_STAGE_DEACTIVATE) { \
php_error_docref(NULL, E_WARNING, "Session ini settings cannot be changed after headers have already been sent"); \
php_session_headers_already_sent_error(E_WARNING, "Session ini settings cannot be changed after headers have already been sent"); \
return FAILURE; \
}

Expand Down Expand Up @@ -121,6 +121,29 @@ static inline void php_rinit_session_globals(void) /* {{{ */
}
/* }}} */

static inline void php_session_headers_already_sent_error(int severity, const char *message) { /* {{{ */
const char *output_start_filename = php_output_get_start_filename();
int output_start_lineno = php_output_get_start_lineno();
if (output_start_filename != NULL) {
php_error_docref(NULL, severity, "%s (sent from %s on line %d)", message, output_start_filename, output_start_lineno);
} else {
php_error_docref(NULL, severity, "%s", message);
}
}
/* }}} */

static inline void php_session_session_already_started_error(int severity, const char *message) { /* {{{ */
if (PS(session_started_filename) != NULL) {
php_error_docref(NULL, severity, "%s (started from %s on line %"PRIu32")", message, ZSTR_VAL(PS(session_started_filename)), PS(session_started_lineno));
} else if (PS(auto_start)) {
/* This option can't be changed at runtime, so we can assume it's because of this */
php_error_docref(NULL, severity, "%s (session started automatically)", message);
} else {
php_error_docref(NULL, severity, "%s", message);
}
}
/* }}} */

static inline void php_session_cleanup_filename(void) /* {{{ */
{
if (PS(session_started_filename)) {
Expand Down Expand Up @@ -1327,15 +1350,8 @@ static int php_session_cache_limiter(void) /* {{{ */
if (PS(session_status) != php_session_active) return -1;

if (SG(headers_sent)) {
const char *output_start_filename = php_output_get_start_filename();
int output_start_lineno = php_output_get_start_lineno();

php_session_abort();
if (output_start_filename) {
php_error_docref(NULL, E_WARNING, "Session cache limiter cannot be sent after headers have already been sent (output started at %s:%d)", output_start_filename, output_start_lineno);
} else {
php_error_docref(NULL, E_WARNING, "Session cache limiter cannot be sent after headers have already been sent");
}
php_session_headers_already_sent_error(E_WARNING, "Session cache limiter cannot be sent after headers have already been sent");
return -2;
}

Expand Down Expand Up @@ -1404,14 +1420,7 @@ static zend_result php_session_send_cookie(void) /* {{{ */
zend_string *e_id;

if (SG(headers_sent)) {
const char *output_start_filename = php_output_get_start_filename();
int output_start_lineno = php_output_get_start_lineno();

if (output_start_filename) {
php_error_docref(NULL, E_WARNING, "Session cookie cannot be sent after headers have already been sent (output started at %s:%d)", output_start_filename, output_start_lineno);
} else {
php_error_docref(NULL, E_WARNING, "Session cookie cannot be sent after headers have already been sent");
}
php_session_headers_already_sent_error(E_WARNING, "Session cookie cannot be sent after headers have already been sent");
return FAILURE;
}

Expand Down Expand Up @@ -1606,14 +1615,7 @@ PHPAPI zend_result php_session_start(void) /* {{{ */

switch (PS(session_status)) {
case php_session_active:
if (PS(session_started_filename)) {
php_error(E_NOTICE, "Ignoring session_start() because a session has already been started (started from %s on line %"PRIu32")", ZSTR_VAL(PS(session_started_filename)), PS(session_started_lineno));
} else if (PS(auto_start)) {
/* This option can't be changed at runtime, so we can assume it's because of this */
php_error(E_NOTICE, "Ignoring session_start() because a session has already been started automatically");
} else {
php_error(E_NOTICE, "Ignoring session_start() because a session has already been started");
}
php_session_session_already_started_error(E_NOTICE, "Ignoring session_start() because a session has already been started");
return FAILURE;
break;

Expand Down Expand Up @@ -1796,12 +1798,12 @@ PHP_FUNCTION(session_set_cookie_params)
}

if (PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session cookie parameters cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session cookie parameters cannot be changed when a session is active");
RETURN_FALSE;
}

if (SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session cookie parameters cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session cookie parameters cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand Down Expand Up @@ -1968,12 +1970,12 @@ PHP_FUNCTION(session_name)
}

if (name && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session name cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session name cannot be changed when a session is active");
RETURN_FALSE;
}

if (name && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session name cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session name cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand All @@ -1998,12 +2000,12 @@ PHP_FUNCTION(session_module_name)
}

if (name && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session save handler module cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session save handler module cannot be changed when a session is active");
RETURN_FALSE;
}

if (name && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session save handler module cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session save handler module cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand Down Expand Up @@ -2039,12 +2041,12 @@ PHP_FUNCTION(session_module_name)

static bool can_session_handler_be_changed(void) {
if (PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session save handler cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session save handler cannot be changed when a session is active");
return false;
}

if (SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session save handler cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session save handler cannot be changed after headers have already been sent");
return false;
}

Expand Down Expand Up @@ -2279,12 +2281,12 @@ PHP_FUNCTION(session_save_path)
}

if (name && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session save path cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session save path cannot be changed when a session is active");
RETURN_FALSE;
}

if (name && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session save path cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session save path cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand All @@ -2308,12 +2310,12 @@ PHP_FUNCTION(session_id)
}

if (name && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session ID cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session ID cannot be changed when a session is active");
RETURN_FALSE;
}

if (name && PS(use_cookies) && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session ID cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session ID cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand Down Expand Up @@ -2350,12 +2352,12 @@ PHP_FUNCTION(session_regenerate_id)
}

if (PS(session_status) != php_session_active) {
php_error_docref(NULL, E_WARNING, "Session ID cannot be regenerated when there is no active session");
php_session_session_already_started_error(E_WARNING, "Session ID cannot be regenerated when there is no active session");
RETURN_FALSE;
}

if (SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session ID cannot be regenerated after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session ID cannot be regenerated after headers have already been sent");
RETURN_FALSE;
}

Expand Down Expand Up @@ -2521,12 +2523,12 @@ PHP_FUNCTION(session_cache_limiter)
}

if (limiter && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session cache limiter cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session cache limiter cannot be changed when a session is active");
RETURN_FALSE;
}

if (limiter && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session cache limiter cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session cache limiter cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand All @@ -2551,12 +2553,12 @@ PHP_FUNCTION(session_cache_expire)
}

if (!expires_is_null && PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Session cache expiration cannot be changed when a session is active");
php_session_session_already_started_error(E_WARNING, "Session cache expiration cannot be changed when a session is active");
RETURN_LONG(PS(cache_expire));
}

if (!expires_is_null && SG(headers_sent)) {
php_error_docref(NULL, E_WARNING, "Session cache expiration cannot be changed after headers have already been sent");
php_session_headers_already_sent_error(E_WARNING, "Session cache expiration cannot be changed after headers have already been sent");
RETURN_FALSE;
}

Expand Down Expand Up @@ -2637,14 +2639,7 @@ PHP_FUNCTION(session_start)
}

if (PS(session_status) == php_session_active) {
if (PS(session_started_filename)) {
php_error_docref(NULL, E_NOTICE, "Ignoring session_start() because a session is already active (started from %s on line %"PRIu32")", ZSTR_VAL(PS(session_started_filename)), PS(session_started_lineno));
} else if (PS(auto_start)) {
/* This option can't be changed at runtime, so we can assume it's because of this */
php_error_docref(NULL, E_NOTICE, "Ignoring session_start() because a session is already automatically active");
} else {
php_error_docref(NULL, E_NOTICE, "Ignoring session_start() because a session is already active");
}
php_session_session_already_started_error(E_NOTICE, "Ignoring session_start() because a session is already active");
RETURN_TRUE;
}

Expand All @@ -2654,14 +2649,7 @@ PHP_FUNCTION(session_start)
* module is unable to rewrite output.
*/
if (PS(use_cookies) && SG(headers_sent)) {
/* It's the header sent to blame, not the session in this case */
const char *output_start_filename = php_output_get_start_filename();
int output_start_lineno = php_output_get_start_lineno();
if (output_start_filename != NULL) {
php_error_docref(NULL, E_WARNING, "Session cannot be started after headers have already been sent (sent from %s on line %d)", output_start_filename, output_start_lineno);
} else {
php_error_docref(NULL, E_WARNING, "Session cannot be started after headers have already been sent");
}
php_session_headers_already_sent_error(E_WARNING, "Session cannot be started after headers have already been sent");
RETURN_FALSE;
}

Expand Down
4 changes: 2 additions & 2 deletions ext/session/tests/014.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ session_destroy();
--EXPECTF--
<a href="/link">

Warning: ini_set(): Session ini settings cannot be changed when a session is active in %s on line %d
Warning: ini_set(): Session ini settings cannot be changed when a session is active (started from %s on line %d) in %s on line %d
<a href="/link">

Warning: ini_set(): Session ini settings cannot be changed when a session is active in %s on line %d
Warning: ini_set(): Session ini settings cannot be changed when a session is active (started from %s on line %d) in %s on line %d
<a href="/link">
2 changes: 1 addition & 1 deletion ext/session/tests/bug73100.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ try {
--EXPECTF--
bool(true)

Warning: session_module_name(): Session save handler module cannot be changed when a session is active in %s on line %d
Warning: session_module_name(): Session save handler module cannot be changed when a session is active (started from %s on line %d) in %s on line %d
bool(true)
session_module_name(): Argument #1 ($module) cannot be "user"
===DONE===
2 changes: 1 addition & 1 deletion ext/session/tests/session_cache_limiter_variation1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ string(7) "nocache"
bool(true)
string(7) "nocache"

Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active in %s on line %d
Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active (started from %s on line %d) in %s on line %d
bool(false)
string(7) "nocache"
bool(true)
Expand Down
2 changes: 1 addition & 1 deletion ext/session/tests/session_cache_limiter_variation2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ string(7) "nocache"
bool(true)
string(7) "nocache"

Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active in %s on line %d
Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active (started from %s on line %d) in %s on line %d
bool(false)
string(7) "nocache"
bool(true)
Expand Down
2 changes: 1 addition & 1 deletion ext/session/tests/session_cache_limiter_variation3.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ string(7) "nocache"
bool(true)
string(7) "nocache"

Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active in %s on line %d
Warning: session_cache_limiter(): Session cache limiter cannot be changed when a session is active (started from %s on line %d) in %s on line %d
bool(false)
string(7) "nocache"
bool(true)
Expand Down
2 changes: 1 addition & 1 deletion ext/session/tests/session_id_error2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ string(4) "test"
string(10) "1234567890"
bool(true)

Warning: session_id(): Session ID cannot be changed when a session is active in %s on line %d
Warning: session_id(): Session ID cannot be changed when a session is active (started from %s on line %d) in %s on line %d
bool(false)
bool(true)
string(0) ""
Expand Down
Loading