Press "Enter" to skip to content

A PHP Session Warning

The full warning text is as follows:

PHP Warning:  Unknown: Your script possibly relies on a session side-effect
which existed until PHP 4.2.3. Please be advised that the session extension does
not consider global variables as a source of data, unless register_globals is enabled.
You can disable this functionality and this warning by setting session.bug_compat_42
or session.bug_compat_warn to off, respectively. in Unknown on

There are many solutions to this problem online, but they are all answers given without understanding the why. So what is the real cause, and how do you solve it?
First, remember this: starting with PHP 4.2, register_globals defaulted to OFF.
After 4.2.3, to stay compatible with the old behaviour, PHP introduced bug_compat_42. When this option is enabled (it is by default), PHP allows variables in SESSION to be used automatically as global variables. It's just that if bug_compat_warn is also enabled, the use of this feature is reported.
Look at a piece of code:

<?php
session_start();
var_dump($_SESSION);
$name = 'laruence';
$_SESSION['name'] = null;
?>

The code above, with bug_compat_42 enabled and register_globals off, produces the following output across two page refreshes:

//first time:
	array(0) {}
//second time
	array(1) { ["a"]=> string(8) "laruence" }

Why isn't the second time NULL? Because with bug_compat_42 enabled, PHP treats the variable a as a reference to $_SESSION['a'], and on session_close it writes the value of a back.
During this process, if bug_compat_warn is enabled, the warning at the start of this article is thrown.
So, that it is.

So what exactly are the conditions under which it gives the warning? Once we know them, we can avoid this warning.
In PHPSRC/ext/session/session.c, we have all the answers we want:

static void php_session_save_current_state(TSRMLS_D) /* {{{ */
{
	int ret = FAILURE;
	IF_SESSION_VARS() {
		//if the Session array exists
		if (PS(bug_compat) && !PG(register_globals)) {
			HashTable *ht = Z_ARRVAL_P(PS(http_session_vars));
			HashPosition pos;
			zval **val;
			int do_warn = 0;
			zend_hash_internal_pointer_reset_ex(ht, &pos);
			while (zend_hash_get_current_data_ex(ht
						, (void **) &val, &pos) != FAILURE) {
				if (Z_TYPE_PP(val) == IS_NULL) { //variable is null
					if (migrate_global(ht, &pos TSRMLS_CC)) {//write the variable back
						do_warn = 1;
					}
				}
				zend_hash_move_forward_ex(ht, &pos);
			}
			if (do_warn && PS(bug_compat_warn)) {
				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Your script possibly
 relies on a session side-effect which existed until PHP 4.2.3 ..........");
				//rest omitted

So, as you can see, you won't see this warning if bug_compat_42 is off (this feature is rarely used these days, and enabling it can sometimes cause more confusion), or if bug_compat_warn is off, or if register_globals is enabled.
In addition, with bug_compat_42 enabled you may also run into the following NOTICE..

PHP Notice:  Unknown: The session bug compatibility code will not try to
locate the global variable $324324 due to its numeric nature in Unknown on line 0

This is a warning that can be triggered when you use a numeric index in $_SESSION.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.