Description:
------------
If you store some object in memcache (like a simple array(1=>'a', 2=>'b') ) it will automatically serialize the data, but when you will retreive it it won't be unserialized. You need to change line 1384 of memcache.c.v.1.21 from
else if (flags == MMC_SERIALIZED) {
to
else if (flags & MMC_SERIALIZED) {
Reproduce code:
---------------
<html><body><pre>
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
$memcache = memcache_pconnect('192.168.1.1', 7777);
$key = "test_unserialize_pibm";
$arr = array(1=>'a', 3=>'b');
echo "saving the following array in $key\n";
print_r($arr);
$memcache->set($key, $arr);
$result = $memcache->get($key);
echo "Obtained :\n";
if (is_array($result)) {
print_r($result);
} else {
echo $result."\n";
}
echo "if you obtained " . serialize ($arr) . " you need to fix the memcache bug :)\n";
?>
</pre></body></html>
Expected result:
----------------
saving the following array in test_unserialize_pibm
Array
(
[1] => a
[3] => b
)
Obtained :
Array
(
[1] => a
[3] => b
)
if you obtained a:2:{i:1;s:1:"a";i:3;s:1:"b";} you need to fix the memcache bug :)
Actual result:
--------------
saving the following array in test_unserialize_pibm
Array
(
[1] => a
[3] => b
)
Obtained :
a:2:{i:1;s:1:"a";i:3;s:1:"b";}
if you obtained a:2:{i:1;s:1:"a";i:3;s:1:"b";} you need to fix the memcache bug :)
Comments
[2004-08-20 20:10 UTC] tony2001 at php dot net
Please, try CVS version first. There were some changes concerning serialization/deserialization and this problem may be already solved.
[2004-08-20 20:15 UTC] pbnadeau at gmail dot com
as you can notice, I used the latest cvs version (1.21) to do the test, and give the line to correct..
[2004-08-21 13:24 UTC] tony2001 at php dot net
Copy-pasted the code you provided, I can reproduce this behaviour. Can you please run the tests, placed in memcache/tests? There are some tests, that test similar functionality, and they work for me fine too.
[2004-08-21 18:18 UTC] tony2001 at php dot net
Sorry, "can" should be read as "can't".
So, I can't reproduce it and all the test work fine for me.
[2004-08-23 02:48 UTC] pbnadeau at gmail dot com
Do you want me to run the tests along with the new version, or with the old one ?
[2004-08-23 04:39 UTC] tony2001 at php dot net
With the new one, of course.
[2004-08-23 04:39 UTC] tony2001 at php dot net
With the new one, of course.
[2004-08-23 14:20 UTC] pbnadeau at gmail dot com
I checked all the 16 tests with the new version and they all worked flawlessly.
[2004-08-23 14:34 UTC] tony2001 at php dot net
That's what I'm talking about. Tests 002.phpt & 003.phpt check the functionality you're complaining about.
So if the tests are working fine than how can your code fail?
As I've already said, your code works fine for me, check it out plz one more time.
[2004-08-23 14:36 UTC] pbnadeau at gmail dot com
I asked specifically if I should run it with the new version, as in the patched version with the change I gave you. That's normal that it works. I'll revert to the original memcache (1.21) and see what those test (2 & 3) do..
[2004-08-23 15:47 UTC] pbnadeau at gmail dot com
I closed one of the server to run the test. I first ran it with the newest version and it ran fine, then I put the old php version (with memcache 1.21) and it ran fine too. So I tested it on the original code that was buggy and the error was there for the original mem_cache but not for my corrected version. I ended up grepping the whole site for mem-> and checked them all. It ended up that one $mem->replace was passing a non-null value in the flags section if the compression wasn't required.
Thus, the equal comparison wasn't working. I believe that the code should still be corrected and even modified that if the serialize flag is passed, it won't be kept if it's not done. Here's a test you can do. Running on the original server I get the error as stated before, but it works with my correction.
<html><body><pre>
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
function display($result) {
echo "Obtained :\n";
if (is_array($result)) {
print_r($result);
} else {
echo $result."\n";
}
}
echo "if you obtained " . $arr . " you then everything is right.\n\n";
$memcache = memcache_pconnect('192.168.1.1', 7777);
$key = "test_unserialize_pibm";
$arr = array('userid'=>1721, 'ip'=>'132.203.32.7');
echo "saving the following array in $key\n";
print_r($arr);
$memcache->set($key, $arr, 32, 3600);
display($memcache->get($key));
echo "if you obtained " . serialize ($arr) . " you need to fix the memcache bug :)\n\n";
$key = "test_ask_unserialize";
$arr = serialize($arr);
echo "saving $arr in $key\n";
$memcache->set($key, $arr, 1, 3600);
display($memcache->get($key));
echo "if you obtained $arr then everything is right, else there's something to do!\n\n";
?>
</pre></body></html>
=============================
result with original version:
saving the following array in test_unserialize_pibm
Array
(
[userid] => 1721
[ip] => 132.203.32.7
)
Obtained :
a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";}
if you obtained a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} you need to fix the memcache bug :)
saving a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} in test_ask_unserialize
Obtained :
Array
(
[userid] => 1721
[ip] => 132.203.32.7
)
if you obtained a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} then everything is right, else there's something to do!
=============================
the corrected version gives :
saving the following array in test_unserialize_pibm
Array
(
[userid] => 1721
[ip] => 132.203.32.7
)
Obtained :
Array
(
[userid] => 1721
[ip] => 132.203.32.7
)
if you obtained a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} you need to fix the memcache bug :)
saving a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} in test_ask_unserialize
Obtained :
Array
(
[userid] => 1721
[ip] => 132.203.32.7
)
if you obtained a:2:{s:6:"userid";i:1721;s:2:"ip";s:12:"132.203.32.7";} then everything is right, else there's something to do!
=============================
So, the first behavior, as when a different value than null not containing 1 is passed making it not unserialize the content is corrected. But, when that value contain one, if it wasn't auto-serialized it will unserialize anyway because the first bit was set externally. That one can be kept as a design decision, but that still could lead to special cases.
I've fixed that website so whatever the decision is it will work..
[2004-08-23 15:54 UTC] tony2001 at php dot net
This bug has been fixed in CVS.
In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.
In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
Thank you for the report, and for helping us make PHP better.
Ok, now I got it finally. Fixed in CVS, thanks!