diff options
Diffstat (limited to 'ext/standard/var.c')
-rw-r--r-- | ext/standard/var.c | 68 |
1 files changed, 51 insertions, 17 deletions
diff --git a/ext/standard/var.c b/ext/standard/var.c index 472cd62d8f..cc033aada7 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -31,9 +31,14 @@ #include "zend_smart_str.h" #include "basic_functions.h" #include "php_incomplete_class.h" +/* }}} */ + +struct php_serialize_data { + HashTable ht; + uint32_t n; +}; #define COMMON (is_ref ? "&" : "") -/* }}} */ static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */ { @@ -171,7 +176,7 @@ again: break; case IS_RESOURCE: { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc)); - php_printf("%sresource(%pd) of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown"); + php_printf("%sresource(%d) of type (%s)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown"); break; } case IS_REFERENCE: @@ -436,8 +441,7 @@ static void php_object_element_export(zval *zv, zend_ulong index, zend_string *k PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */ { HashTable *myht; - char *tmp_str; - size_t tmp_len; + char tmp_str[PHP_DOUBLE_MAX_LENGTH]; zend_string *ztmp, *ztmp2; zend_ulong index; zend_string *key; @@ -458,8 +462,8 @@ again: smart_str_append_long(buf, Z_LVAL_P(struc)); break; case IS_DOUBLE: - tmp_len = spprintf(&tmp_str, 0,"%.*H", PG(serialize_precision), Z_DVAL_P(struc)); - smart_str_appendl(buf, tmp_str, tmp_len); + php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str); + smart_str_appends(buf, tmp_str); /* Without a decimal point, PHP treats a number literal as an int. * This check even works for scientific notation, because the * mantissa always contains a decimal point. @@ -469,7 +473,6 @@ again: if (zend_finite(Z_DVAL_P(struc)) && NULL == strchr(tmp_str, '.')) { smart_str_appendl(buf, ".0", 2); } - efree(tmp_str); break; case IS_STRING: ztmp = php_addcslashes(Z_STR_P(struc), 0, "'\\", 2); @@ -844,16 +847,13 @@ again: return; case IS_DOUBLE: { - char *s; - - smart_str_appendl(buf, "d:", 2); - s = (char *) safe_emalloc(PG(serialize_precision), 1, MAX_LENGTH_OF_DOUBLE + 1); - php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', s); - smart_str_appends(buf, s); - smart_str_appendc(buf, ';'); - efree(s); - return; - } + char tmp_str[PHP_DOUBLE_MAX_LENGTH]; + smart_str_appendl(buf, "d:", 2); + php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str); + smart_str_appends(buf, tmp_str); + smart_str_appendc(buf, ';'); + return; + } case IS_STRING: php_var_serialize_string(buf, Z_STRVAL_P(struc), Z_STRLEN_P(struc)); @@ -998,6 +998,35 @@ PHPAPI void php_var_serialize(smart_str *buf, zval *struc, php_serialize_data_t } /* }}} */ +PHPAPI php_serialize_data_t php_var_serialize_init() { + struct php_serialize_data *d; + /* fprintf(stderr, "SERIALIZE_INIT == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ + if (BG(serialize_lock) || !BG(serialize).level) { + d = emalloc(sizeof(struct php_serialize_data)); + zend_hash_init(&d->ht, 16, NULL, ZVAL_PTR_DTOR, 0); + d->n = 0; + if (!BG(serialize_lock)) { + BG(serialize).data = d; + BG(serialize).level = 1; + } + } else { + d = BG(serialize).data; + ++BG(serialize).level; + } + return d; +} + +PHPAPI void php_var_serialize_destroy(php_serialize_data_t d) { + /* fprintf(stderr, "SERIALIZE_DESTROY == lock: %u, level: %u\n", BG(serialize_lock), BG(serialize).level); */ + if (BG(serialize_lock) || BG(serialize).level == 1) { + zend_hash_destroy(&d->ht); + efree(d); + } + if (!BG(serialize_lock) && !--BG(serialize).level) { + BG(serialize).data = NULL; + } +} + /* {{{ proto string serialize(mixed variable) Returns a string representation of variable (which can later be unserialized) */ PHP_FUNCTION(serialize) @@ -1084,6 +1113,11 @@ PHP_FUNCTION(unserialize) in case nesting calls to unserialize */ var_push_dtor(&var_hash, return_value); + /* Ensure return value is a value */ + if (Z_ISREF_P(return_value)) { + zend_unwrap_reference(return_value); + } + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); if (class_hash) { zend_hash_destroy(class_hash); |