I have been investigating the cause of bug 17490 which appears to have been a problem with the serializer. I am working with the PHP 4.2.3 source. http://bugs.php.net/bug.php?id=17490
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. Thank you in advance, Douglas Q. Hawkins 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 ); } -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php