summaryrefslogtreecommitdiff
path: root/ext/spl/php_spl.c
diff options
context:
space:
mode:
authorGustavo André dos Santos Lopes <cataphract@php.net>2011-03-27 04:21:06 +0000
committerGustavo André dos Santos Lopes <cataphract@php.net>2011-03-27 04:21:06 +0000
commitc2fe893985f619fdb4f8d17c16405e8ce7926db5 (patch)
tree4101c77fce358b27a85f569b8255301c8e142489 /ext/spl/php_spl.c
parent3acdca47030e6dc973cffc0063d45e1bef354a3e (diff)
downloadphp-git-c2fe893985f619fdb4f8d17c16405e8ce7926db5.tar.gz
- Fixed bug #54384: Several SPL classes crash when parent constructor is
not called. #Merge to 5.3 pending (slight BC break on AppendIterator, as it's no #longer possible to defer the call to the parent constructor until #after the constructor is performed). #Bugs fixed in an atypical way for SPL. The parent constructor call #check is performed at construction time by using a wrapper constructor #instead of a check on the beginning of each instance method. #Perhaps this should be uniformized in trunk; this method was mainly #applied only to the ones crashing, except a few iterators (at least #AppendIterator and RecursiveIteratorIterator).
Diffstat (limited to 'ext/spl/php_spl.c')
-rwxr-xr-xext/spl/php_spl.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 10b3e43fff..cd9a548d8f 100755
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -51,14 +51,30 @@ ZEND_DECLARE_MODULE_GLOBALS(spl)
#define SPL_DEFAULT_FILE_EXTENSIONS ".inc,.php"
+static void construction_wrapper(INTERNAL_FUNCTION_PARAMETERS);
+
/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(spl)
{
+ zend_function *cwf = &spl_globals->constr_wrapper_fun;
spl_globals->autoload_extensions = NULL;
spl_globals->autoload_extensions_len = 0;
spl_globals->autoload_functions = NULL;
spl_globals->autoload_running = 0;
+ spl_globals->validating_fun = NULL;
+
+ cwf->type = ZEND_INTERNAL_FUNCTION;
+ cwf->common.function_name = "internal_construction_wrapper";
+ cwf->common.scope = NULL; /* to be filled */
+ cwf->common.fn_flags = ZEND_ACC_PRIVATE;
+ cwf->common.prototype = NULL;
+ cwf->common.num_args = 0; /* not necessarily true but not enforced */
+ cwf->common.required_num_args = 0;
+ cwf->common.arg_info = NULL;
+
+ cwf->internal_function.handler = construction_wrapper;
+ cwf->internal_function.module = &spl_module_entry;
}
/* }}} */
@@ -776,6 +792,75 @@ int spl_build_class_list_string(zval **entry, char **list TSRMLS_DC) /* {{{ */
return ZEND_HASH_APPLY_KEEP;
} /* }}} */
+zend_function *php_spl_get_constructor_helper(zval *object, int (*validating_fun)(void *object_data TSRMLS_DC) TSRMLS_DC) /* {{{ */
+{
+ if (Z_OBJCE_P(object)->type == ZEND_INTERNAL_CLASS) {
+ return std_object_handlers.get_constructor(object TSRMLS_CC);
+ } else {
+ SPL_G(validating_fun) = validating_fun;
+ SPL_G(constr_wrapper_fun).common.scope = Z_OBJCE_P(object);
+ return &SPL_G(constr_wrapper_fun);
+ }
+}
+/* }}} */
+
+static void construction_wrapper(INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
+{
+ zval *this = getThis();
+ void *object_data;
+ zend_class_entry *this_ce;
+ zend_function *zf;
+ zend_fcall_info fci = {0};
+ zend_fcall_info_cache fci_cache = {0};
+ zval *retval_ptr = NULL;
+
+ object_data = zend_object_store_get_object(this TSRMLS_CC);
+ zf = zend_get_std_object_handlers()->get_constructor(this TSRMLS_CC);
+ this_ce = Z_OBJCE_P(this);
+
+ fci.size = sizeof(fci);
+ fci.function_table = &this_ce->function_table;
+ /* fci.function_name = ; not necessary */
+ /* fci.symbol_table = ; not necessary */
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = ZEND_NUM_ARGS();
+ if (fci.param_count > 0) {
+ fci.params = emalloc(fci.param_count * sizeof *fci.params);
+ if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), fci.params) == FAILURE) {
+ zend_throw_exception(NULL, "Unexpected error fetching arguments", 0 TSRMLS_CC);
+ return;
+ }
+ }
+ fci.object_ptr = this;
+ fci.no_separation = 0;
+
+ fci_cache.initialized = 1;
+ fci_cache.called_scope = EG(current_execute_data)->called_scope;
+ fci_cache.calling_scope = EG(current_execute_data)->current_scope;
+ fci_cache.function_handler = zf;
+ fci_cache.object_ptr = this;
+
+ if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == FAILURE) {
+ if (!EG(exception)) {
+ zend_throw_exception(NULL, "Error calling parent constructor", 0 TSRMLS_CC);
+ }
+ goto cleanup;
+ }
+ if (!EG(exception) && SPL_G(validating_fun)(object_data TSRMLS_CC) == 0)
+ zend_throw_exception_ex(spl_ce_LogicException, 0 TSRMLS_CC,
+ "In the constructor of %s, parent::__construct() must be called "
+ "and its exceptions cannot be cleared", this_ce->name);
+
+cleanup:
+ if (fci.params != NULL) {
+ efree(fci.params);
+ }
+ if (retval_ptr != NULL) {
+ zval_ptr_dtor(&retval_ptr);
+ }
+}
+/* }}} */
+
/* {{{ PHP_MINFO(spl)
*/
PHP_MINFO_FUNCTION(spl)