Some weird behavior I've found - I'm intrigued - can anyone shed any light on this..?
Overview
Spent some time this morning finding the cause of a bug which was resulting in the $_SESSION
array to empty. Eventually got to the bottom of it and found that when defining an index for one of the $_SESSION
variables, an &
was being used for concatination instead of a .
. It only broke when two specific strings were &
ed, other strings resulted in nonsense keys but $_SESSION
didn't empty.
This is running on PHP5.5.9-1ubuntu4.20 and locally on PHP5.6.15.
Try it yourself!
Using the example code below,
$_SESSION
is now empty!Example code
set-session.php
session_start();
$_SESSION = [
'colour' => 'blue',
'shape' => 'round',
'size' => 'medium'
];
check-session.php
session_start();
echo '<pre>';
print_r($_SESSION);
break-session.php
session_start();
$killer_string = 'Admin_CH_1_' & '101_';
$_SESSION[$killer_string] = null;
echo '<pre>';
print_r($_SESSION);
My guess
I'm guessing that the result of the bitwise operation results in a string, in this case $killer_string
, that causes PHP to get angry when it tries to store the $_SESSION
array on the server. Strange that $killer_string
is no longer a killer when used as a key for a sub array in $_SESSION
though.
Ideas?
I know that the code doesn't actually make sense so there's no fault with PHP. However, I am curious as to what is actually going on behind the scenes and what's causing this...
Cheers!
Here's a simplified test case (see it in action):
<?php
header('Content-Type: text/plain');
ob_start();
session_start();
$_SESSION = [
'colour' => 'blue',
'shape' => 'round',
'size' => 'medium',
//'Admin_CH_1_' & '101_' => 'Gone',
chr(0x01) . chr(0x20) . chr(0x21) . chr(0x49) => 'Gone',
];
var_dump($_SESSION);
session_write_close();
session_start();
var_dump($_SESSION);
ob_end_flush();
If you inspect the session file you can see it has zero bytes.
My best guess so far (until someone smarter shares a link to the PHP github repo with the specific internals) is that you are inadvertently pushing the limits of the session serialization code. Such code assumes that keys are non-binary strings. There's certain validation (pure numeric keys trigger a Skipping numeric key notice) but it doesn't cover all possible malformed inputs. At some point it just crashes.
This gets supported by the fact that changing the serialisation method fixes the issue:
ini_set('session.serialize_handler', 'php_serialize');
In the session.serialize_handler
documentation we can read:
Older serialize handlers cannot store numeric index nor string index contains special characters (| and !) in
$_SESSION
. Usephp_serialize
to avoid numeric index or special character errors at script shutdown. Defaults tophp
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With