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

Reply via email to