Hi,

I have come across what appears to be a bug in PHP, but one that I am having difficulty writing test code for. Also, the bug only happens on a Linux build of PHP - the code is working as expected on Windows. This is on both PHP 5.2.0 and the very latest snapshots:

Windows: 5.2.1RC4-dev Jan 19 2007 16:16:57
Linux: PHP Version 5.2.1RC4-dev Jan 22 2007 11:54:28 (php5.2-200701221130.tar.gz)

The configure line is:

'./configure' '--with-apxs2=/usr/local/apache2/bin/apxs' '--with-curl' '--with-freetype-dir=/usr' '--with-gd' '--with-gettext' '--with-jpeg-dir=/usr' '--with-mysql' '--with-openssl' '--with-pdo-mysql' '--with-pear' '--with-png-dir=/usr' '--with-zlib' '--enable-calendar' '--enable-exif' '--enable-gd-native-ttf' '--enable-pdo' '--enable-soap' '--enable-sockets'

and no 3rd party extensions are enabled.

The code that is causing the problem exists within a class in a function called approve_friend. This is called by a "public" page with a parameter provided in GET being passed to the function approve_friend:

$username = filter_input(INPUT_GET, 'username', FILTER_SANITIZE_STRING);
if (!empty($username))
{
  if ($username != $_SESSION['user']['username'])
  {     
    if ($core->user->add_friend($username))
    {
      echo 1;
    }
    else
    {
      echo 2;
    }
  }
}

There is code in place of echo 1 and echo 2 but it's not relevant. Here, the code checks to make sure the username submitted is the not the same as the currently logged in use. If not, it will execute the $core->user->add_friend function.

add_friend runs through as follows:

1. Makes a call to $this->get_user where it gets data for the username $username provided when calling the function. It returns an array.

$friend = $this->get_user(1, NULL, $username);

2. Grabs some data from the session about the currently logged in user

$user['name'] = filter_var($_SESSION['user']['name'], FILTER_SANITIZE_STRING); $user['user_id'] = filter_var($_SESSION['user']['user_id'], FILTER_SANITIZE_NUMBER_INT); $user['username'] = filter_var($_SESSION['user']['username'], FILTER_SANITIZE_STRING); $user['friend_count'] = filter_var($_SESSION['user']['friend_count'], FILTER_SANITIZE_NUMBER_INT);

3. Checks to make sure $friend has a value

if (empty($friend))
{
  return false;
}

4. Checks to make sure that the friend being added is not already added.

if (!empty($_SESSION['user']['friends']))
{
  if (in_array($friend['user_id'], $_SESSION['user']['friends']))
  {
    return false;
  }
}

This is the point at which there is a problem. If I add this code before #4:

print_r($_SESSION['user']['friends']);
echo $friend['user_id']; exit;

Then I get the following output:

Array ( [0] => 3 ) 3

i.e. $_SESSION['user']['friends'] is an array with the key 0 and the value 3 and $friend['user_id'] has a value of 3. Therefore, the in_array() check above will return true and the function will return false. No further code in the function should execute. This is what happens on Windows - 2 is output to the page because the add_friend function has returned false.

Now, after #4, there is more code. This code is only supposed to execute if the friend doesn't already exist - it adds the friend, increments the friend count and sends an e-mail.

// Insert into friends
$core->database->exec('INSERT INTO users_friends SET user_id = "'.$user['user_id'].'", user_friend_id = "'.$friend['user_id'].'", status = 1'); $core->database->exec('INSERT INTO users_friends SET user_id = "'.$friend['user_id'].'", user_friend_id = "'.$user['user_id'].'"');

// Update friend count
$core->database->exec('UPDATE users_insiders SET friend_count = "'.++$user['friend_count'].'" WHERE user_id = "'.$user['user_id'].'"');

// E-mail sending code using phpmailer

return true;

On my Linux server, the function returns false at step #4 as it should do, but it appears to continue executing. The friend count is incremented and the page execution slows temporarily whilst the mail is being sent (not a problem in testing). However, no e-mail actually gets sent.

The key is that the function is returning false but it continues to execute! If I stick in an exit; after the in_array() check at point #4, this doesn't happen. There are no other places where this function is called, and it is only called once.

Strangely, if I force the values of the 2 variables
before the in_array() check:

$_SESSION['user']['friends'] = array(0 => 3);
$friend['user_id'] = 3;

it reacts as expected - the function returns false and no further code is executed.

Anyone have any suggestions?

Regards,

David Mytton

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to