History | Log In     View a printable version of the current page. Get help!  
Issue Details (XML | Word)

Key: OSC-314
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Harald Ponce de Leon
Reporter: Tassilo Kirsch
Votes: 1
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
osCommerce Core

register_globals compatibility layer for PHP 4.3+ doesn't (always) work

Created: 05/Sep/07 03:07 PM   Updated: 10/Dec/09 12:46 PM
Component/s: Core Framework
Affects Version/s: 2.2 RC 1
Fix Version/s: 2.2 RC 2

Environment: PHP 4.3 and higher on all platforms


 Description  « Hide
Error was probably introduced with:

07/03/2007 osCommerce Online Merchant 2.2 RC1
* Add a register_globals compatibility layer for PHP 4.3+ servers.
  [r1583, r1584, r1597, r1599, r1647]

Affected:

/admin/functions/sessions.php
$Id: sessions.php,v 1.9 2003/06/23 01:20:05 hpdl Exp $

  function tep_session_register($variable) {
    if (PHP_VERSION < 4.3) {
      return session_register($variable);
    } else {
      if (isset($GLOBALS[$variable])) {
        $_SESSION[$variable] =& $GLOBALS[$variable];
      } else {
        $_SESSION[$variable] = null;
      }
      $GLOBALS[$variable] =& $_SESSION[$variable];
    }

    return false;
  }

/functions/sessions.php
$Id: sessions.php,v 1.19 2003/07/02 22:10:34 hpdl Exp $

  function tep_session_register($variable) {
    global $session_started;

    if ($session_started == true) {
      if (PHP_VERSION < 4.3) {
        return session_register($variable);
      } else {
        $_SESSION[$variable] = (isset($GLOBALS[$variable])) ? $GLOBALS[$variable] : null;

        $GLOBALS[$variable] =& $_SESSION[$variable];
      }
    }

    return false;
  }

// identical in both files:

 function tep_session_is_registered($variable) {
    if (PHP_VERSION < 4.3) {
      return session_is_registered($variable);
    } else {
      return isset($_SESSION[$variable]);
    }
  }


Description:

There are actually two issues here.

The first one is that tep_session_register doesn't work as expected if
called from within a function/method *and*
called with a variable which has been declared using "global $variable" *and*
called with a variable which hasn't been set in the global scope before tep_session_register is called

Example:

function foo() {
  global $variable;
  tep_session_register('variable');
  $variable = 'Hello World';
}

foo();
print_r($_SESSION);
echo var_dump($_SESSION['variable']);

will output:
Array
(
    [variable] =>
}
NULL

Replacing $_SESSION with $GLOBALS will produce the same output


Real life example: messageStack->add_session()
You can see the effect of this error on the My Account page:
Call edit account.
Change something.
You're back at My Account.
Call edit account.
Change something.
You're back at My Account, but this time, a "account successfully updated" message is shown.
Call edit account.
Change something.
You're back at My Account, no message is shown
Call edit account.
Change something.
You're back at My Account, and the message is back, too
Continue until you get bored...


Finally, the fix:

  function tep_session_register($variable) {
    global $session_started;

    if ($session_started == true) {
      if (PHP_VERSION < 4.3) {
        return session_register($variable);
      } else {
        $_SESSION[$variable] =& $GLOBALS[$variable];
        return true; // just for the sake of consistency
      }
    }

    return false;
  }

should do the trick.


The second issue is that tep_session_is_registered doesn't handle null values correctly.

Example:

tep_session_register('variable');
print_r($_SESSION);
if (tep_session_is_registered('variable') {
  echo 'registered<br>';
} else {
  echo 'not registered<br>';
}
$variable = 'Hello';
echo $_SESSION['variable'] . '<br>';
if (tep_session_is_registered('variable') {
  echo 'registered';
} else {
  echo 'not registered';
}

will output

Array
(
    [variable] =>
}
not registered // <- this is wrong, $variable *is* registered, it just has a value of null right now
Hallo
registered // and now it's suddenly registered

Fix:
 function tep_session_is_registered($variable) {
    if (PHP_VERSION < 4.3) {
      return session_is_registered($variable);
    } else {
      return array_key_exists($variable, $_SESSION);
    }
  }

This is also for the sake of consistency, since session_is_registered also returns true for previously registered null values.

 All   Comments   Change History      Sort Order:
Greg Kendall [17/Dec/07 05:18 AM]
PRAISE TO YOU, Tassilo Kirsch, for this magnificent detailed explanation and a working fix. You saved me a whole lot of headaches. Nothing's worse than an error that is intermittent and nearly impossible to trace. Finding your solution was a huge relief. Now my message_stack is NOT unreliable anymore. And Sessions behave like they should. Thanks, and thanks some more!!! =)

Harald Ponce de Leon [20/Dec/07 04:11 PM]
Thanks for the help with this issue. The changes have been committed in r1741 with the addition of enabling session.bug_compat_42 and disabling session.bug_compat_warn via ini_set() calls if PHP >= 4.3 is used and if register_globals is disabled.

http://svn.oscommerce.com/fisheye/changelog/osCommerce/?cs=1741

Birol Aygün [10/Dec/09 12:46 PM]
I have replaced function "tep_session_is_registered" with what you provided. Using php 4.4, osC 2.2 (not sure which RC). But I still get the following error:

Parse error: syntax error, unexpected T_STRING in ...../admin/includes/functions/sessions.php on line 71

Line 71 is:
function tep_session_is_registered($variable) {
    if (PHP_VERSION < 4.3) {
      return session_is_registered($variable);
    } else {
      return array_key_exists($variable, $_SESSION);
    }
  }

I initially had register_globals On. Then I made it Off. Tried a lot of other stuff. Nothing is changed. I get the same exact msg.