summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-07 10:55:53 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-07 10:55:53 +0200
commit45a79f33051ed70fd69d3b9943a1e5797402430e (patch)
treef87bacb47b746182367bbb1e9840f5cb32cbb783
parente2b543132bdf6cf7c335801139c19cc17dca0c34 (diff)
objects were not destructed correctly (we freed memory that we had allocated ourselves, but the Zend engine seemed to deallocate the same memory too, which caused a crash), and improved returning values from functions, which crashed when one of the own parameters was directly returned (error mentioned in issue #68)
-rw-r--r--include/value.h1
-rw-r--r--zend/callable.cpp17
-rw-r--r--zend/callable.h13
-rw-r--r--zend/objectimpl.h25
4 files changed, 39 insertions, 17 deletions
diff --git a/include/value.h b/include/value.h
index 844f978..95985d7 100644
--- a/include/value.h
+++ b/include/value.h
@@ -949,6 +949,7 @@ protected:
friend class TraverseIterator;
friend class HashMember<int>;
friend class HashMember<std::string>;
+ friend class Callable;
};
/**
diff --git a/zend/callable.cpp b/zend/callable.cpp
index 737b85b..96f5f90 100644
--- a/zend/callable.cpp
+++ b/zend/callable.cpp
@@ -23,7 +23,7 @@ namespace Php {
* @param tsrm_ls
* @return integer
*/
-static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS)
+void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS)
{
// find the function name
const char *name = get_active_function_name(TSRMLS_C);
@@ -31,9 +31,6 @@ static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS)
// uncover the hidden pointer inside the function name
Callable *callable = HiddenPointer<Callable>(name);
- // wrap the return value
- Value result(return_value, true);
-
// construct parameters
ParametersImpl params(this_ptr, ZEND_NUM_ARGS() TSRMLS_CC);
@@ -41,7 +38,15 @@ static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS)
try
{
// get the result
- result = callable->invoke(params);
+ Value result(callable->invoke(params));
+
+ // detach the zval (we don't want it to be destructed)
+ zval *val = result.detach();
+
+ // @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(val, 1, 0);
}
catch (Exception &exception)
{
@@ -64,7 +69,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int
{
// fill the members of the entity, and hide a pointer to the current object in the name
entry->fname = (const char *)_ptr;
- entry->handler = invoke_callable;
+ entry->handler = &Callable::invoke;
entry->arg_info = _argv;
entry->num_args = _argc;
entry->flags = flags;
diff --git a/zend/callable.h b/zend/callable.h
index 9805174..67863a9 100644
--- a/zend/callable.h
+++ b/zend/callable.h
@@ -181,6 +181,19 @@ protected:
info->allow_null = arg.allowNull();
info->pass_by_reference = arg.byReference();
}
+
+ /**
+ * Function that is called by the Zend engine every time that a function gets called
+ * @param ht
+ * @param return_value
+ * @param return_value_ptr
+ * @param this_ptr
+ * @param return_value_used
+ * @param tsrm_ls
+ * @return integer
+ */
+ static void invoke(INTERNAL_FUNCTION_PARAMETERS);
+
};
/**
diff --git a/zend/objectimpl.h b/zend/objectimpl.h
index 41bed53..f66a6ab 100644
--- a/zend/objectimpl.h
+++ b/zend/objectimpl.h
@@ -20,7 +20,7 @@ class ObjectImpl
{
private:
/**
- * Structure with a first element which is a mixed object, so that
+ * Structure with a first element which is a zend_object, so that
* it can be casted to a zend_object
* @var MixedObject
*/
@@ -40,7 +40,7 @@ private:
ObjectImpl *self;
- } _mixed;
+ } *_mixed;
/**
* Pointer to the C++ implementation
@@ -66,15 +66,18 @@ public:
*/
ObjectImpl(zend_class_entry *entry, Base *base TSRMLS_DC)
{
+ // allocate a mixed object (for some reason this does not have to deallocated)
+ _mixed = (MixedObject *)emalloc(sizeof(MixedObject));
+
// copy properties to the mixed object
- _mixed.php.ce = entry;
- _mixed.self = this;
+ _mixed->php.ce = entry;
+ _mixed->self = this;
// store the c++ object
_object = base;
// initialize the object
- zend_object_std_init(&_mixed.php, entry TSRMLS_CC);
+ zend_object_std_init(&_mixed->php, entry TSRMLS_CC);
#if PHP_VERSION_ID < 50399
@@ -82,12 +85,12 @@ public:
zval *tmp;
// initialize the properties, php 5.3 way
- zend_hash_copy(_mixed.php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*));
+ zend_hash_copy(_mixed->php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*));
#else
// version higher than 5.3 have an easier way to initialize
- object_properties_init(&_mixed.php, entry);
+ object_properties_init(&_mixed->php, entry);
#endif
@@ -112,7 +115,7 @@ public:
// the destructor and clone handlers are set to NULL. I dont know why, but they do not
// seem to be necessary...
- _handle = zend_objects_store_put(&_mixed, (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC);
+ _handle = zend_objects_store_put(php(), (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC);
// the object may remember that we are its implementation object
base->_impl = this;
@@ -124,7 +127,7 @@ public:
virtual ~ObjectImpl()
{
// deallocate the cpp object
- delete _object;
+ if (_object) delete _object;
}
/**
@@ -134,7 +137,7 @@ public:
void destruct(TSRMLS_D)
{
// pass on to the default destructor
- zend_objects_free_object_storage(&_mixed.php TSRMLS_CC);
+ zend_objects_free_object_storage(php() TSRMLS_CC);
// destruct the object
delete this;
@@ -184,7 +187,7 @@ public:
*/
zend_object *php()
{
- return &_mixed.php;
+ return &_mixed->php;
}
/**