Skip to content

Commit b741d33

Browse files
committed
fix bug #61359: json_encode() calls too many reallocs
1 parent 4420b43 commit b741d33

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ PHP NEWS
5252
pattern). (Gustavo)
5353
. Fixed bug #60785 (memory leak in IntlDateFormatter constructor). (Gustavo)
5454

55+
- JSON:
56+
. Fixed bug #61359 (json_encode() calls too many reallocs). (Stas)
57+
5558
- libxml:
5659
. Fixed bug #62266 (Custom extension segfaults during xmlParseFile with FPM
5760
SAPI). (Gustavo)

ext/json/json.c

+12-9
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
311311
smart_str_appendc(buf, ':');
312312

313313
json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
314-
314+
315315
php_json_encode(buf, *data, options TSRMLS_CC);
316316
} else {
317317
if (need_comma) {
@@ -329,7 +329,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
329329
smart_str_appendc(buf, ':');
330330

331331
json_pretty_print_char(buf, options, ' ' TSRMLS_CC);
332-
332+
333333
php_json_encode(buf, *data, options TSRMLS_CC);
334334
}
335335
}
@@ -340,7 +340,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
340340
}
341341
}
342342
}
343-
343+
344344
--JSON_G(encoder_depth);
345345
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
346346
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
360360
int pos = 0, ulen = 0;
361361
unsigned short us;
362362
unsigned short *utf16;
363+
size_t newlen;
363364

364365
if (len == 0) {
365366
smart_str_appendl(buf, "\"\"", 2);
@@ -387,9 +388,9 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
387388
}
388389
return;
389390
}
390-
391+
391392
}
392-
393+
393394
utf16 = (options & PHP_JSON_UNESCAPED_UNICODE) ? NULL : (unsigned short *) safe_emalloc(len, sizeof(unsigned short), 0);
394395
ulen = utf8_to_utf16(utf16, s, len);
395396
if (ulen <= 0) {
@@ -408,6 +409,8 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
408409
len = ulen;
409410
}
410411

412+
/* pre-allocate for string length plus 2 quotes */
413+
smart_str_alloc(buf, len+2, 0);
411414
smart_str_appendc(buf, '"');
412415

413416
while (pos < len)
@@ -520,13 +523,13 @@ static void json_encode_serializable_object(smart_str *buf, zval *val, int optio
520523
zend_class_entry *ce = Z_OBJCE_P(val);
521524
zval *retval = NULL, fname;
522525
HashTable* myht;
523-
526+
524527
if (Z_TYPE_P(val) == IS_ARRAY) {
525528
myht = HASH_OF(val);
526529
} else {
527530
myht = Z_OBJPROP_P(val);
528-
}
529-
531+
}
532+
530533
if (myht && myht->nApplyCount > 1) {
531534
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
532535
smart_str_appendl(buf, "null", 4);
@@ -539,7 +542,7 @@ static void json_encode_serializable_object(smart_str *buf, zval *val, int optio
539542
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Failed calling %s::jsonSerialize()", ce->name);
540543
smart_str_appendl(buf, "null", sizeof("null") - 1);
541544
return;
542-
}
545+
}
543546

544547
if (EG(exception)) {
545548
/* Error already raised */

0 commit comments

Comments
 (0)