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