summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2012-06-30 19:14:30 -0700
committerStanislav Malyshev <stas@php.net>2012-06-30 19:14:30 -0700
commitb741d3315be5cbddae5a895b9dceb2b71d394366 (patch)
treef5004eea8d45360cb4169fa6326c2980f1721889
parent4420b439073a77354293695133d744c1c5297c0f (diff)
downloadphp-git-b741d3315be5cbddae5a895b9dceb2b71d394366.tar.gz
fix bug #61359: json_encode() calls too many reallocs
-rw-r--r--NEWS3
-rw-r--r--ext/json/json.c21
2 files changed, 15 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 44784626c2..6dd1feb777 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,9 @@ PHP NEWS
pattern). (Gustavo)
. Fixed bug #60785 (memory leak in IntlDateFormatter constructor). (Gustavo)
+- JSON:
+ . Fixed bug #61359 (json_encode() calls too many reallocs). (Stas)
+
- libxml:
. Fixed bug #62266 (Custom extension segfaults during xmlParseFile with FPM
SAPI). (Gustavo)
diff --git a/ext/json/json.c b/ext/json/json.c
index b467079610..96690477c9 100644
--- a/ext/json/json.c
+++ b/ext/json/json.c
@@ -311,7 +311,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
smart_str_appendc(buf, ':');
json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
-
+
php_json_encode(buf, *data, options TSRMLS_CC);
} else {
if (need_comma) {
@@ -329,7 +329,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
smart_str_appendc(buf, ':');
json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
-
+
php_json_encode(buf, *data, options TSRMLS_CC);
}
}
@@ -340,7 +340,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
}
}
}
-
+
--JSON_G(encoder_depth);
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
json_pretty_print_indent(buf, options TSRMLS_CC);
@@ -360,6 +360,7 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
int pos = 0, ulen = 0;
unsigned short us;
unsigned short *utf16;
+ size_t newlen;
if (len == 0) {
smart_str_appendl(buf, "\"\"", 2);
@@ -387,9 +388,9 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
}
return;
}
-
+
}
-
+
utf16 = (options & PHP_JSON_UNESCAPED_UNICODE) ? NULL : (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
ulen = utf8_to_utf16(utf16, s, len);
if (ulen <= 0) {
@@ -408,6 +409,8 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
len = ulen;
}
+ /* pre-allocate for string length plus 2 quotes */
+ smart_str_alloc(buf, len+2, 0);
smart_str_appendc(buf, '"');
while (pos < len)
@@ -520,13 +523,13 @@ static void json_encode_serializable_object(smart_str *buf, zval *val, int optio
zend_class_entry *ce = Z_OBJCE_P(val);
zval *retval = NULL, fname;
HashTable* myht;
-
+
if (Z_TYPE_P(val) == IS_ARRAY) {
myht = HASH_OF(val);
} else {
myht = Z_OBJPROP_P(val);
- }
-
+ }
+
if (myht && myht->nApplyCount > 1) {
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
smart_str_appendl(buf, "null", 4);
@@ -539,7 +542,7 @@ static void json_encode_serializable_object(smart_str *buf, zval *val, int optio
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
smart_str_appendl(buf, "null", sizeof("null") - 1);
return;
- }
+ }
if (EG(exception)) {
/* Error already raised */