Hi, Attached is a patch (against HEAD) which adapts the default ("php") session serializer to serialize the whole array using php_var_serialize instead of calling it once per element.
This simplifies the serialization code, and allows unicode session keys, or even ascii keys containing the pipe character. However it would be a significant BC break, as old serialized session records would be unreadable after upgrading. We could mitigate this by providing a script to convert old session files. It also means the serialized data would be a few bytes larger per key, so there's definitely some weighing up to do. Any thoughts? Arpad
Index: ext/session/session.c =================================================================== --- ext/session/session.c (revision 291124) +++ ext/session/session.c (working copy) @@ -783,45 +783,10 @@ { smart_str buf = {0}; php_serialize_data_t var_hash; - PS_ENCODE_VARS; PHP_VAR_SERIALIZE_INIT(var_hash); + php_var_serialize(&buf, &PS(http_session_vars), &var_hash TSRMLS_CC); - PS_UENCODE_LOOP( - if (!struc) { - smart_str_appendc(&buf, PS_UNDEF_MARKER); - } - - if (key_type == HASH_KEY_IS_STRING) { - if (memchr(key.s, PS_DELIMITER, key_length)) { - PHP_VAR_SERIALIZE_DESTROY(var_hash); - smart_str_free(&buf); - return FAILURE; - } - smart_str_appendl(&buf, key.s, key_length); - } else { - /* HASH_KEY_IS_UNICODE */ - char *str = NULL; - int len; - UErrorCode status = U_ZERO_ERROR; - - zend_unicode_to_string_ex(UG(utf8_conv), &str, &len, key.u, key_length, &status); - if (U_FAILURE(status) || memchr(str, PS_DELIMITER, key_length)) { - PHP_VAR_SERIALIZE_DESTROY(var_hash); - smart_str_free(&buf); - if (str) { efree(str); } - return FAILURE; - } - smart_str_appendl(&buf, str, len); - efree(str); - } - smart_str_appendc(&buf, PS_DELIMITER); - - if (struc) { - php_var_serialize(&buf, struc, &var_hash TSRMLS_CC); - } - ); - if (newlen) { *newlen = buf.len; } @@ -835,61 +800,57 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ { - const char *p, *q; - char *name; const char *endptr = val + vallen; - zval *current; - int namelen; - int has_value; + zval **current, *storage; + zstr name; + uint namelen; + zend_uchar utype; + ulong num_key; php_unserialize_data_t var_hash; + HashPosition pos; + if (!vallen) { + return SUCCESS; + } + PHP_VAR_UNSERIALIZE_INIT(var_hash); + ALLOC_INIT_ZVAL(storage); - p = val; + if (!php_var_unserialize(&storage, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash TSRMLS_CC) || Z_TYPE_P(storage) != IS_ARRAY) { + zval_ptr_dtor(&storage); + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + return FAILURE; + } - while (p < endptr) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(storage), &pos); + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(storage), (void **)¤t, &pos) == SUCCESS) { zval **tmp; - has_value = 1; + zval_add_ref(current); - q = p; - while (*q != PS_DELIMITER) { - if (++q >= endptr) goto break_outer_loop; + switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(storage), &name, &namelen, &num_key, 0, &pos)) { + case HASH_KEY_IS_STRING: + utype = IS_STRING; + break; + case HASH_KEY_IS_UNICODE: + utype = IS_UNICODE; + break; + default: + goto skip; } - if (*p == PS_UNDEF_MARKER) { - if (++p >= endptr) goto break_outer_loop; - - has_value = 0; - } - - namelen = q - p; - name = estrndup(p, namelen); - q++; - - if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { + if (zend_u_hash_find(&EG(symbol_table), utype, name, namelen, (void **)&tmp) == SUCCESS) { if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { goto skip; } } - if (has_value) { - ALLOC_INIT_ZVAL(current); - if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { - zend_utf8_hash_update(Z_ARRVAL_P(PS(http_session_vars)), name, namelen + 1, ¤t, sizeof(zval *), NULL); - } else { - zval_ptr_dtor(¤t); - } - } - PS_ADD_VARL(name, namelen); + zend_u_hash_update(Z_ARRVAL_P(PS(http_session_vars)), utype, name, namelen, current, sizeof(current), NULL); skip: - efree(name); - - p = q; + zend_hash_move_forward_ex(Z_ARRVAL_P(storage), &pos); } -break_outer_loop: + zval_ptr_dtor(&storage); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); - return SUCCESS; } /* }}} */
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php