From da4de6cb1097471b2659c102d55a646cbc9e0f41 Mon Sep 17 00:00:00 2001 From: Toon Schoenmakers Date: Tue, 25 Nov 2014 11:45:47 +0100 Subject: Fixed a memory leak when returning a Php::Object with an already allocated Base --- include/object.h | 22 +++++++++++----------- zend/callable.cpp | 6 +++--- zend/callable.h | 2 +- zend/object.cpp | 12 ++++++------ zend/value.cpp | 3 --- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/include/object.h b/include/object.h index 29f4110..9387408 100644 --- a/include/object.h +++ b/include/object.h @@ -82,17 +82,17 @@ public: * @param arg8 Optional argument 9 * @param arg9 Optional argument 10 */ - Object(const char *name) : Value(Type::Object) { if (instantiate(name)) call("__construct"); } - Object(const char *name, Value p0) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0); } - Object(const char *name, Value p0, Value p1) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1); } - Object(const char *name, Value p0, Value p1, Value p2) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7, p8); } - Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9) : Value(Type::Object) { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); } + Object(const char *name) : Value() { if (instantiate(name)) call("__construct"); } + Object(const char *name, Value p0) : Value() { if (instantiate(name)) call("__construct", p0); } + Object(const char *name, Value p0, Value p1) : Value() { if (instantiate(name)) call("__construct", p0, p1); } + Object(const char *name, Value p0, Value p1, Value p2) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7, p8); } + Object(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9) : Value() { if (instantiate(name)) call("__construct", p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); } /** * Destructor diff --git a/zend/callable.cpp b/zend/callable.cpp index 7505bbf..f0dc3e8 100644 --- a/zend/callable.cpp +++ b/zend/callable.cpp @@ -51,12 +51,12 @@ void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS) { // get the result Value result(callable->invoke(params)); - + // we're ready if the return value is not even used if (!return_value_used) return; - + // @todo php 5.6 has a RETVAL_ZVAL_FAST macro that can be used instead (and is faster) - + // return a full copy of the zval, and do not destruct it RETVAL_ZVAL(result._val, 1, 0); } diff --git a/zend/callable.h b/zend/callable.h index 9958a2a..bd74f27 100644 --- a/zend/callable.h +++ b/zend/callable.h @@ -144,7 +144,7 @@ protected: { // fill members info->name = arg.name(); - info->name_len = ::strlen(arg.name()); + info->name_len = ::strlen(arg.name()); #if PHP_VERSION_ID >= 50400 diff --git a/zend/object.cpp b/zend/object.cpp index a4eaf1e..4af6204 100644 --- a/zend/object.cpp +++ b/zend/object.cpp @@ -17,7 +17,7 @@ namespace Php { * @param name Name of the class to instantiate * @param base Implementation of the class */ -Object::Object(const char *name, Base *base) : Value(Type::Object) +Object::Object(const char *name, Base *base) : Value() { // does the object already have a handle? if (base->implementation()) @@ -29,7 +29,7 @@ Object::Object(const char *name, Base *base) : Value(Type::Object) { // we need the tsrm_ls variable TSRMLS_FETCH(); - + // this is a brand new object that should be allocated, the C++ instance // is already there (created by the extension) but it is not yet stored // in PHP, find out the classname first (we use the FatalError class @@ -38,14 +38,14 @@ Object::Object(const char *name, Base *base) : Value(Type::Object) // by the extension). auto *entry = zend_fetch_class(name, ::strlen(name), ZEND_FETCH_CLASS_SILENT TSRMLS_CC); if (!entry) throw FatalError(std::string("Unknown class name ") + name); - + // construct an implementation (this will also set the implementation // member in the base object) new ObjectImpl(entry, base TSRMLS_CC); - + // now we can store it operator=(Value(base)); - + // install the object handlers Z_OBJVAL_P(_val).handlers = ClassImpl::objectHandlers(entry); } @@ -56,7 +56,7 @@ Object::Object(const char *name, Base *base) : Value(Type::Object) * or when it is a string holding a classname * @param that An other object */ -Object::Object(const Value &value) : Value(Type::Object) +Object::Object(const Value &value) : Value() { // when a string is passed in, we are going to make a new instance of the // passed in string diff --git a/zend/value.cpp b/zend/value.cpp index 946a41d..501feb7 100644 --- a/zend/value.cpp +++ b/zend/value.cpp @@ -210,9 +210,6 @@ Value::Value(const Base *object) // store the handlers in the zval too (cast is necessary for php 5.3) Z_OBJ_HT_P(_val) = (zend_object_handlers*)obj_bucket->bucket.obj.handlers; - - // run the copy constructor - zval_copy_ctor(_val); } /** -- cgit v1.2.3