From f843d679ae78a623f2050f971bd0dc3496ce217d Mon Sep 17 00:00:00 2001 From: Xuefer Date: Wed, 12 Nov 2014 18:55:52 +0000 Subject: [PATCH] fix some xcache_get leak by refcount git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1576 c26eb9a1-5813-0410-bd6c-c2e55f420ca7 --- processor/foot.m4 | 6 +- processor/processor.m4 | 12 ++-- tests/xcache_var_object.phpt | 5 +- tests/xcache_var_object_5.1.phpt | 101 ++++++++++++++++++++++++++++ tests/xcache_var_reference.phpt | 5 +- tests/xcache_var_reference_4.phpt | 60 +++++++++++++++++ tests/xcache_var_reference_5.1.phpt | 60 +++++++++++++++++ 7 files changed, 239 insertions(+), 10 deletions(-) create mode 100644 tests/xcache_var_object_5.1.phpt create mode 100644 tests/xcache_var_reference_4.phpt create mode 100644 tests/xcache_var_reference_5.1.phpt diff --git a/processor/foot.m4 b/processor/foot.m4 index 0bfe239..27eef0c 100644 --- a/processor/foot.m4 +++ b/processor/foot.m4 @@ -124,9 +124,6 @@ EXPORTED_FUNCTION(`void xc_processor_restore_var(zval *dst, zval **dst_ptr, cons if (processor.handle_reference) { zend_hash_init(&processor.zvalptrs, 0, NULL, NULL, 0); - if (dst_ptr) { - zval_ptr_dtor(dst_ptr); - } } processor.index_to_ce = index_to_ce; @@ -144,11 +141,14 @@ EXPORTED_FUNCTION(`void xc_processor_restore_var(zval *dst, zval **dst_ptr, cons } } #endif + zval_ptr_dtor(&dst); if (dst_ptr) { xc_restore_zval_ptr(&processor, dst_ptr, &src->value TSRMLS_CC); + Z_ADDREF(**dst_ptr); } else { xc_restore_zval(&processor, dst, src->value TSRMLS_CC); + Z_ADDREF(*dst); } if (processor.handle_reference) { zend_hash_destroy(&processor.zvalptrs); diff --git a/processor/processor.m4 b/processor/processor.m4 index b202bda..8977fa7 100644 --- a/processor/processor.m4 +++ b/processor/processor.m4 @@ -306,7 +306,6 @@ DEF_STRUCT_P_FUNC(`zval_ptr', , `dnl {{{ RELOCATE_EX(zval, pzv) ') if (zend_hash_add(&processor->zvalptrs, (char *) &SRC()[0], sizeof(SRC()[0]), (void *) &pzv, sizeof(pzv), NULL) == SUCCESS) { /* first add, go on */ - IFSTORE(`Z_SET_REFCOUNT(**DST(), 1);') dnl IFSTORE(`fprintf(stderr, "mark[%p] = %p\n", (void *) SRC()[0], (void *) pzv);') } else { @@ -319,6 +318,8 @@ DEF_STRUCT_P_FUNC(`zval_ptr', , `dnl {{{ ') IFDPRINT(`INDENT()`'fprintf(stderr, "[%p] ", (void *) SRC()[0]);') STRUCT_P_EX(zval, DST()[0], SRC()[0], `[0]', `', ` ') + dnl don't set refcount in zval processor + IFSTORE(`Z_SET_REFCOUNT(**DST(), 1);') RELOCATE_EX(zval, DST()[0]) } while (0); ') @@ -1418,21 +1419,23 @@ DEF_STRUCT_P_FUNC(`xc_entry_var_t', , `dnl {{{ IFDPRINT(`INDENT()`'fprintf(stderr, "zval:value");') STRUCT_P_EX(zval_ptr, DST(`value'), SRC(`value'), `value', `', `&') + DONE(value) #if 0 IFSTORE(` { HashTable *ht; zval **zv; - assert(Z_TYPE_P(SRC(`value')) == IS_ARRAY); - ht = Z_ARRVAL_P(SRC(`value')); + assert(Z_TYPE_P(DST(`value')) == IS_ARRAY); + ht = Z_ARRVAL_P(DST(`value')); assert(ht->nNumOfElements == 1); fprintf(stderr, "key %s\n", ht->pListHead->arKey); zv = (zval **) ht->pListHead->pData; - fprintf(stderr, "%d\n", Z_TYPE_PP(zv)); assert(Z_TYPE_PP(zv) == IS_ARRAY); assert(Z_ARRVAL_PP(zv) == ht); + fprintf(stderr, "refcount=%d\n", Z_REFCOUNT(*DST(`value'))); + fprintf(stderr, "refcount=%d\n", Z_REFCOUNT(**zv)); } ') #endif @@ -1482,7 +1485,6 @@ DEF_STRUCT_P_FUNC(`xc_entry_var_t', , `dnl {{{ ') PROCESS(zend_bool, have_references) - DONE(value) ') dnl }}} dnl ==================================================== diff --git a/tests/xcache_var_object.phpt b/tests/xcache_var_object.phpt index 1a2f323..aec1ea3 100644 --- a/tests/xcache_var_object.phpt +++ b/tests/xcache_var_object.phpt @@ -1,8 +1,11 @@ --TEST-- -xcache_set/get test for object +xcache_set/get test for object PHP 5.2+ --SKIPIF-- =')) { + echo 'skip for PHP 5.2+ only'; +} ?> --INI-- xcache.test = 1 diff --git a/tests/xcache_var_object_5.1.phpt b/tests/xcache_var_object_5.1.phpt new file mode 100644 index 0000000..a74cced --- /dev/null +++ b/tests/xcache_var_object_5.1.phpt @@ -0,0 +1,101 @@ +--TEST-- +xcache_set/get test for object 5.1- +--SKIPIF-- + +--INI-- +xcache.test = 1 +xcache.size = 32M +xcache.var_size = 2M +--FILE-- +a = $a; +$b->b = $b; +$b->array = array($b, $a); +$b->stdclass = $stdclass; + +var_dump(xcache_set("a", $a)); +unset($a); +var_dump($a = xcache_get("a")); + +var_dump(xcache_set("b", $b)); +unset($b); +var_dump($b = xcache_get("b")); + +$b->test = 1; +var_dump($b->b->test); +?> +--EXPECT-- +bool(true) +object(a)#4 (0) { +} +bool(true) +object(b)#7 (4) { + ["a"]=> + object(a)#6 (0) { + } + ["b"]=> + object(b)#7 (4) { + ["a"]=> + object(a)#6 (0) { + } + ["b"]=> + *RECURSION* + ["array"]=> + array(2) { + [0]=> + *RECURSION* + [1]=> + object(a)#6 (0) { + } + } + ["stdclass"]=> + object(stdClass)#5 (0) { + } + } + ["array"]=> + array(2) { + [0]=> + object(b)#7 (4) { + ["a"]=> + object(a)#6 (0) { + } + ["b"]=> + *RECURSION* + ["array"]=> + array(2) { + [0]=> + *RECURSION* + [1]=> + object(a)#6 (0) { + } + } + ["stdclass"]=> + object(stdClass)#5 (0) { + } + } + [1]=> + object(a)#6 (0) { + } + } + ["stdclass"]=> + object(stdClass)#5 (0) { + } +} +int(1) diff --git a/tests/xcache_var_reference.phpt b/tests/xcache_var_reference.phpt index f632aa2..a59cde9 100644 --- a/tests/xcache_var_reference.phpt +++ b/tests/xcache_var_reference.phpt @@ -1,8 +1,11 @@ --TEST-- -xcache_set/get test for reference +xcache_set/get test for reference for PHP 5.2+ --SKIPIF-- =')) { + echo 'skip for PHP 5.2+ only'; +} ?> --INI-- xcache.test = 1 diff --git a/tests/xcache_var_reference_4.phpt b/tests/xcache_var_reference_4.phpt new file mode 100644 index 0000000..5ffaec8 --- /dev/null +++ b/tests/xcache_var_reference_4.phpt @@ -0,0 +1,60 @@ +--TEST-- +xcache_set/get test for reference for PHP 4 +--SKIPIF-- + +--INI-- +xcache.test = 1 +xcache.size = 32M +xcache.var_size = 2M +--FILE-- + +--EXPECT-- +bool(true) +array(1) { + [0]=> + &array(2) { + ["ref"]=> + &array(2) { + ["ref"]=> + *RECURSION* + ["array"]=> + array(1) { + [0]=> + *RECURSION* + } + } + ["array"]=> + array(1) { + [0]=> + &array(2) { + ["ref"]=> + *RECURSION* + ["array"]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +int(1) +int(1) diff --git a/tests/xcache_var_reference_5.1.phpt b/tests/xcache_var_reference_5.1.phpt new file mode 100644 index 0000000..3907650 --- /dev/null +++ b/tests/xcache_var_reference_5.1.phpt @@ -0,0 +1,60 @@ +--TEST-- +xcache_set/get test for reference for PHP 5.{0,1} +--SKIPIF-- +=') && version_compare(phpversion(), '5.2', '<'))) { + echo 'skip for PHP 5.{0,1} only'; +} +?> +--INI-- +xcache.test = 1 +xcache.size = 32M +xcache.var_size = 2M +--FILE-- + +--EXPECT-- +bool(true) +array(1) { + [0]=> + &array(2) { + ["ref"]=> + &array(2) { + ["ref"]=> + *RECURSION* + ["array"]=> + array(1) { + [0]=> + *RECURSION* + } + } + ["array"]=> + array(1) { + [0]=> + &array(2) { + ["ref"]=> + *RECURSION* + ["array"]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +int(1) +int(1)