ID: 17490 Comment by: -b2 dot p7 at telus dot net Reported By: weyrick at roadsend dot com Status: No Feedback Bug Type: Strings related Operating System: linux rh7.2 PHP Version: 4.2.1 New Comment:
I have found the cause of my problem above. It only occurred when there was an apostrophe (') in the data but it didn't occur every time there was an apostrophe. When it was a problem, I discovered the underlying data already had the apostrophe escaped, like so: (\'). This resulted in an extra character being counted by the serialize function because it was counting the backslash but MySQL was not adding it to the database entry. I don't know whether this should be considered a bug or just a coding "gotcha". I've added it here for others who may have a similar problem as it is easy to code around. Previous Comments: ------------------------------------------------------------------------ [2003-06-02 14:55:29] -b2 dot p7 at telus dot net RedHat Linux 7.2, Apache 1.3.27, PHP 4.1.2, MySQL 3.23.56 Same problem as above... the character count recorded does not match the actual count: s:102 below should be s:101 I have about 800 items in a mysql database that have all been serialized with the same code and after reviewing about one-quarter of them I have found three with this error. Example from DB: O:8:"rss_item":3:{s:5:"title";s:58:"Calgarian smashes three world running records for amputees";s:4:"link";s:87:"http://www.cbc.ca/cgi-bin/templates/sportsView.cgi?/news/2003/06/01/Sports/connor030601";s:11:"description";s:102:"Calgary´s Earle Connor enjoyed a career day at a track meet in Leverkusen, Germany, on Sunday.";} If there is a patch specific to this, I'd appreciate hearing about it. ------------------------------------------------------------------------ [2003-05-12 15:10:00] memeyou at memeyou dot net i get similar behavior in CYGWIN. i also noticed the same compile warning: /bin/sh /php4-STABLE-200305100130/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/standard/ -I/php4-STABLE-200305100130/ext/standard/ -DPHP_ATOM_INC -I/php4-STABLE-200305100130/include -I/php4-STABLE-200305100130/main -I/php4-STABLE-200305100130 -I/usr/local/apache2/include -I/php4-STABLE-200305100130/Zend -I/php4-STABLE-200305100130/ext/xml/expat -I/php4-STABLE-200305100130/TSRM -g -O2 -prefer-pic -c /php4-STABLE-200305100130/ext/standard/var_unserializer.c -o ext/standard/var_unserializer.lo /php4-STABLE-200305100130/ext/standard/var_unserializer.c: In function `php_var_unserialize': /php4-STABLE-200305100130/ext/standard/var_unserializer.c:308: warning: comparison is always false due to limited range of data type ------------------------------------------------------------------------ [2002-10-26 01:00:07] php-bugs at lists dot php dot net No feedback was provided for this bug for over 2 weeks, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open". ------------------------------------------------------------------------ [2002-10-16 12:55:35] dougqh at incogen dot com I just noticed that problem I am describing with serializing arrays/objects looks very similar to bug 14293. http://bugs.php.net/bug.php?id=14293 ------------------------------------------------------------------------ [2002-10-16 11:03:15] dougqh at incogen dot com I tried the latest CVS snap shot as requested to no avail. I actually reworked the serializer to fix the problem. I have not submitted my changes because of some odd behavior, compiler warnings, and other things I wanted to clean up first. I have a question about the array serialization, which appears to be the culprit. I posted this to the PHP-dev list a couple times and received no replies. My email to the list is provided below. Any insights would be appreciated. The cause of the problem appears to be that zend_hash_num_elements was returning a number smaller than the actual number of elements being iterated across using the zend_hash_*_ex functions. This caused the serializer to store a number of elements smaller than the actual number of elements written. This in turn leads to the unserializer failing later. I would like to know if there is some reason why zend_hash_num_elements would be expected to return a value smaller than the number of actual elements iterated across using the zend_hash_*_ex functions. This problem is rare, but was happening sporadically. Below is the section of code that is displaying this behavior. If you see any obvious errors please let me know. static inline void php_var_serialize_hash_all( smart_str *buf, zval **struc, HashTable *var_hash TSRMLS_DC ) { int numElements; int cur; int actualCount; smart_str tmp = {0}; numElements = zend_hash_num_elements( HASH_OF( *struc ) ); /* There is a problem with the value returned by zend_hash_num_elements not returning a value equivalent to the number elements actually iterated across using zend_hash_*_ex functions */ /* Solution iterate filling a temporary buffer and remembering the count - then copy the temporary buffer into the actual buffer */ if ( numElements > 0 ) { char *key; zval **data; ulong index; uint key_len; HashPosition pos; for ( /* initialize */ zend_hash_internal_pointer_reset_ex( HASH_OF( *struc ), &pos ), actualCount = 0; /* test */; /* advance */ zend_hash_move_forward_ex( HASH_OF( *struc ), &pos ), ++actualCount ) { cur = zend_hash_get_current_key_ex( HASH_OF( *struc ), &key, &key_len, &index, 0, &pos ); if ( cur == HASH_KEY_NON_EXISTANT ) break; switch ( cur ) { case HASH_KEY_IS_LONG: php_var_serialize_long( &tmp, index ); break; case HASH_KEY_IS_STRING: php_var_serialize_string( &tmp, key, key_len - 1 ); break; } /* we should still add element even if it's not OK, since we already wrote the length of the array before */ if ( ( zend_hash_get_current_data_ex( HASH_OF( *struc ), ( void ** ) &data, &pos ) != SUCCESS ) || ( ! data ) || ( data == struc ) ) { php_var_serialize_null( &tmp ); } else { php_var_serialize_intern( &tmp, data, var_hash TSRMLS_CC ); } } } else { actualCount = 0; } smart_str_append_long( buf, actualCount ); smart_str_appendc( buf, TYPE_VALUE_DELIMITER_CHAR ); smart_str_appendc( buf, OPEN_HASH_CHAR ); smart_str_appendl( buf, tmp.c, tmp.len ); smart_str_appendc( buf, CLOSE_HASH_CHAR ); /* clean up tmp */ smart_str_free_ex( &tmp, 1 ); } ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/17490 -- Edit this bug report at http://bugs.php.net/?id=17490&edit=1