diff options
| author | Johannes Schlüter <johannes@php.net> | 2007-12-21 20:58:11 +0000 |
|---|---|---|
| committer | Johannes Schlüter <johannes@php.net> | 2007-12-21 20:58:11 +0000 |
| commit | 42add0f2e1d64ec16f265f80702a1c58fa0f1c23 (patch) | |
| tree | 8614f68ecbf3cb7ea8d15281706edfb3354aac3d /Zend | |
| parent | ab6121f686aeedb213c1affe156c8be23fa8a894 (diff) | |
| download | php-git-42add0f2e1d64ec16f265f80702a1c58fa0f1c23.tar.gz | |
- MFH: Fix #43450 (Memory leak on some functions with implicit object
__toString() call) (Davic C.)
Diffstat (limited to 'Zend')
| -rw-r--r-- | Zend/tests/bug43450.phpt | 35 | ||||
| -rw-r--r-- | Zend/zend_object_handlers.c | 14 |
2 files changed, 49 insertions, 0 deletions
diff --git a/Zend/tests/bug43450.phpt b/Zend/tests/bug43450.phpt new file mode 100644 index 0000000000..926e146f4e --- /dev/null +++ b/Zend/tests/bug43450.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #43450 (Memory leak on some functions with implicit object __toString() call) +--SKIPIF-- +<?php if (!function_exists('memory_get_usage')) die('memory_get_usage() not installed'); ?> +--FILE-- +<?php +error_reporting(E_ALL|E_STRICT); + +class Foo +{ + public function __toString() + { + return __CLASS__; + } +} + +$num_repeats = 100000; + +$start = (memory_get_usage() / 1024) + 16; +for ($i=1;$i<$num_repeats;$i++) +{ + $foo = new Foo(); + md5($foo); +} +$end = memory_get_peak_usage() / 1024; + +if ($start < $end) { + echo 'FAIL'; +} else { + echo 'PASS'; +} + +?> +--EXPECT-- +PASS diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ea96ccad38..85f4f9b4e6 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1105,6 +1105,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } if (Z_TYPE_P(retval) == IS_STRING) { INIT_PZVAL(writeobj); + if (readobj == writeobj) { + zval_dtor(readobj); + } ZVAL_ZVAL(writeobj, retval, 1, 1); if (Z_TYPE_P(writeobj) != type) { convert_to_explicit_type(writeobj, type); @@ -1113,6 +1116,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty } else { zval_ptr_dtor(&retval); INIT_PZVAL(writeobj); + if (readobj == writeobj) { + zval_dtor(readobj); + } ZVAL_EMPTY_STRING(writeobj); zend_error(E_RECOVERABLE_ERROR, "Method %s::__toString() must return a string value", ce->name); return SUCCESS; @@ -1127,15 +1133,23 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ce = Z_OBJCE_P(readobj); zend_error(E_NOTICE, "Object of class %s could not be converted to int", ce->name); INIT_PZVAL(writeobj); + if (readobj == writeobj) { + zval_dtor(readobj); + } ZVAL_LONG(writeobj, 1); return SUCCESS; case IS_DOUBLE: ce = Z_OBJCE_P(readobj); zend_error(E_NOTICE, "Object of class %s could not be converted to double", ce->name); INIT_PZVAL(writeobj); + if (readobj == writeobj) { + zval_dtor(readobj); + } ZVAL_DOUBLE(writeobj, 1); return SUCCESS; default: + INIT_PZVAL(writeobj); + Z_TYPE_P(writeobj) = IS_NULL; break; } return FAILURE; |
