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