php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #20142 Session and EscapeShellCmd problem
Submitted: 2002-10-28 16:00 UTC Modified: 2003-01-22 19:10 UTC
From: glenn at glenndevore dot com Assigned:
Status: Not a bug Package: Session related
PHP Version: 4.2.3 OS: Win 2K
Private report: No CVE-ID: None
 [2002-10-28 16:00 UTC] glenn at glenndevore dot com
I am using sessions with variables that have passed through EscapeShellCmd().  The EscapeShellCmd function does its job well and appends a \ before each special character.  I am also using user defined session handlers with session_set_save_handler().  Listed below is my script that executes the session_set_save_handler function along with all the functions for the session handlers.  The problem occurs when PHP inserts or updates a value to the session database that has gone through the EscapeShellCmd function and escaped any special characters.  The session separator value counts the backslashes even though they are not posted.  For instance:

/***********************************************/
// If I set a variable 
$test = ?b?lah?;
// And then run the EscapeShellCmd function
$test = EscapeShellCmd($test);
// and then register it as a session variable
session_register(?test?);
// then print the variable to see what it looks like
print $test;    # This outputs: b\?lah
/***********************************************/

It adds the session, but counts the backslash as part of the session separator so that the session variable looks something like this: 

test|s:6:"b'lah";

when it should read:

test|s:5:"b'lah";

Because it says 6, the count of characters is off and all of the session variables become damaged.

If this is not a bug, and there is an easy solution to this please let me know, and I apologize for posting here.  I have asked around and am unable to find an answer.

Thank you for your time and effort.

-Glenn DeVore

P.S. Below is my session handlers script.


/***********************************************/
// This is the session handler script page
/***********************************************/

include("error.inc");
include("db.inc");

// The database connection
// $connection;

// The global variable that holds the table name
// $session_table;

// Returns current time as a number.
// Used for recording the last session access.
//
if (!function_exists('getMicroTime')) {
function getMicroTime()
{
  // microtime() returns the number of seconds
  // since 0:00:00 January 1, 1970 GMT as a
  // microsecond part and a second part.
  // eg: 0.08344800 1000952237
  // Convert the two parts into an array
  $mtime = explode(" ", microtime());

  // Return the addition of the two parts
  // eg: 1000952237.08344800
  return($mtime[1] + $mtime[0]);
}
}


// The session open handler called by PHP whenever
// a session is initialized. Always returns true.
//
if (!function_exists('sessionOpen')) {
function sessionOpen($database_name, $table_name)
{

  // Save the database name in a global variable
  global $connection;
  global $hostName;
  global $username;
  global $password;
  global $session_table;

  if (!($connection = @ mysql_pconnect($hostName,
                                       $username,
                                       $password)))
     showerror();

  if (!mysql_select_db($database_name, $connection))
     showerror();

  // Save the table name in a global variable
  $session_table = $table_name;

  return true;
}
}
// This function is called whenever a session_start()
// call is made and reads the session variables
// Returns "" when a session is not found
//         (serialized)string - session exists
//
if (!function_exists('sessionRead')) {
function sessionRead($sess_id)
{
  // Access the DBMS connection
  global $connection;

  // Access the global variable that holds the name
  // of the table that holds the session variables
  global $session_table;

  // Formulate a query to find the session
  // identified by $sess_id
  $search_query =
    "SELECT * FROM $session_table
      WHERE session_id = '$sess_id'";

  // Execute the query
  if (!($result = @ mysql_query($search_query,
                                $connection)))
     showerror();

  if(mysql_num_rows($result) == 0)
    // No session found - return an empty string
    return "";
  else
  {
    // Found a session - return the serialized string
    $row = mysql_fetch_array($result);
    return $row["session_variable"];
  }
}
}

// This function is called when a session is initialized
// with a session_start() call, when variables are
// registered or unregistered, and when session variables
// are modified. Returns true on success.
//
if (!function_exists('sessionWrite')) {
function sessionWrite($sess_id, $val)
{
  global $connection;
  global $session_table;

  $time_stamp = getMicroTime();

  $search_query =
    "SELECT session_id FROM $session_table
       WHERE session_id = '$sess_id'";

  // Execute the query
  if (!($result = @ mysql_query($search_query,
                                $connection)))
     showerror();

  if(mysql_num_rows($result) == 0)
  {
     // No session found, insert a new one
     $insert_query =
         "INSERT INTO $session_table
          (session_id, session_variable, last_accessed)
           VALUES ('$sess_id', '$val', $time_stamp)";

     if (!mysql_query($insert_query,
                      $connection))
        showerror();
  }
  else
  {
     // Existing session found - Update the
     // session variables
     $update_query =
       "UPDATE $session_table
        SET session_variable = '$val',
            last_accessed = $time_stamp
        WHERE session_id = '$sess_id'";

     if (!mysql_query($update_query,
                      $connection))
        showerror();
  }
  return true;
}
}

// This function is executed on shutdown of the session.
// Always returns true.
//
if (!function_exists('sessionClose')) {
function sessionClose()
{
    return true;
}
}

// This is called whenever the session_destroy()
// function call is made. Returns true if the session
// has successfully been deleted.
//
if (!function_exists('sessionDestroy')) {
function sessionDestroy($sess_id)
{
  global $connection;
  global $session_table;

  $delete_query =
    "DELETE FROM $session_table
      WHERE session_id = '$sess_id'";

  if (!($result = @ mysql_query($delete_query,
                                $connection)))
     showerror();

  return true;
}
}

// This function is called on a session's start up with
// the probability specified in session.gc_probability.
// Performs garbage collection by removing all sessions
// that haven't been updated in the last $max_lifetime
// seconds as set in session.gc_maxlifetime.
// Returns true if the DELETE query succeeded.
//
if (!function_exists('sessionGC')) {
function sessionGC($max_lifetime)
{
  global $connection;
  global $session_table;

  $time_stamp = getMicroTime();

  $delete_query =
    "DELETE FROM $session_table
      WHERE last_accessed < ($time_stamp - $max_lifetime)";

  if (!($result = @ mysql_query($delete_query,
                                $connection)))
     showerror();

  return true;
}
}

// This functiion registers a given URL to have the
// session id sent with the URL, instead of using
// cookies
//
if (!function_exists('registerURL')) {
  function registerURL($URL)
  {
	$sessionId = session_id();
  $registered_URL = $URL . "?PHPSESSION=" . $sessionId;
	return $registered_URL;
  }
}
// Call to register user call back functions.

session_set_save_handler("sessionOpen",
                         "sessionClose",
                         "sessionRead",
                         "sessionWrite",
                         "sessionDestroy",
                         "sessionGC");

/***********************************************/
/***********************************************/

Patches

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-10-28 17:46 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php4-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php4-win32-latest.zip
 [2002-11-14 01:47 UTC] sniper@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 [2002-11-14 20:41 UTC] glenn at glenndevore dot com
I tried using the http://snaps.php.net/win32/php4-win32-latest.zip download, but it crashed my system.  I don't think it was the software.  It was more likely the hardware.  I am currently rebuilding the server and will try again when it is up.  Thank you.
 [2002-11-15 01:37 UTC] sniper@php.net
let's keep this in feedback status then until we get the real feedback.

 [2002-11-25 16:08 UTC] glenn at glenndevore dot com
I have installed the win32 version listed above and still get the same problem.

The session count of characters is still off.
 [2003-01-22 17:48 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

EscapeShellCmd adds \ to the variable, which changes $test from b'lah to b\'lah nothing buggy or unusual about that.
 [2003-01-22 19:10 UTC] glenn at glenndevore dot com
The EscapeShellCmd was not the problem.  The issue was with how sessions are stored.  Please read the post for Oct 28, 2002 for a full explanation.  In a nutshell: The session is saved with a number indicating the length of the variable, however it does not count the / as a character and is thus one less than the actual number of characters in the string, thus confusing the session information and reporting an error.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Aug 16 15:01:28 2024 UTC