summaryrefslogtreecommitdiff
path: root/ext/standard/var.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/var.c')
-rw-r--r--ext/standard/var.c68
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);