summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorJohannes Schlüter <johannes@php.net>2007-12-21 20:58:11 +0000
committerJohannes Schlüter <johannes@php.net>2007-12-21 20:58:11 +0000
commit42add0f2e1d64ec16f265f80702a1c58fa0f1c23 (patch)
tree8614f68ecbf3cb7ea8d15281706edfb3354aac3d /Zend
parentab6121f686aeedb213c1affe156c8be23fa8a894 (diff)
downloadphp-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.phpt35
-rw-r--r--Zend/zend_object_handlers.c14
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;