From 3b2480298f61e6b9b3ac3ce3b9f37e2558f838c4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 16 Jun 2021 16:29:53 +0200 Subject: [PATCH] Fix #81142: memory leak when unserialize()ing associative array We should not internalize unserialized array keys, because that easily wastes a lot of memory for a small gain. Instead, we check whether the string is already internalized, and use that; otherwise we use a new string. This patch is based on an idea by @nikic. --- ext/standard/tests/serialize/bug81142.phpt | 12 ++++++++++++ ext/standard/var_unserializer.re | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/serialize/bug81142.phpt diff --git a/ext/standard/tests/serialize/bug81142.phpt b/ext/standard/tests/serialize/bug81142.phpt new file mode 100644 index 0000000000000..88af20cd130ed --- /dev/null +++ b/ext/standard/tests/serialize/bug81142.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #81142 (memory leak when unserialize()ing associative array) +--FILE-- + 1])); +$mem1 = memory_get_usage(); +var_dump($mem1 - $mem0); +?> +--EXPECT-- +int(0) diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index a444cdef5b7e7..2fe202f1ffd74 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -947,7 +947,13 @@ use_double: } else if (len == 1) { ZVAL_INTERNED_STR(rval, ZSTR_CHAR((zend_uchar)*str)); } else if (as_key) { - ZVAL_STR(rval, zend_string_init_interned(str, len, 0)); + zend_string *key = zend_string_init(str, len, 0); + zend_string *ikey = zend_interned_string_find_permanent(key); + if (ikey) { + zend_string_release(key); + key = ikey; + } + ZVAL_STR(rval, key); } else { ZVAL_STRINGL(rval, str, len); }