]> granicus.if.org Git - php/commitdiff
- MFH: Fix #43450 (Memory leak on some functions with implicit object
authorJohannes Schlüter <johannes@php.net>
Fri, 21 Dec 2007 20:56:33 +0000 (20:56 +0000)
committerJohannes Schlüter <johannes@php.net>
Fri, 21 Dec 2007 20:56:33 +0000 (20:56 +0000)
  __toString() call) (Davic C.)

Zend/tests/bug43450.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c

diff --git a/Zend/tests/bug43450.phpt b/Zend/tests/bug43450.phpt
new file mode 100644 (file)
index 0000000..926e146
--- /dev/null
@@ -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
index 56ff4ab1b26d397304f8c982529f23a77c8787eb..f68598107e16b7aa1414b1fafb5c3ab3e14cc50b 100644 (file)
@@ -1191,6 +1191,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);
@@ -1199,6 +1202,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;
@@ -1213,15 +1219,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;