]> granicus.if.org Git - php/commitdiff
reimplement php_filter_callback() as exception-safe and without memleaks
authorAntony Dovgal <tony2001@php.net>
Tue, 6 Dec 2005 15:17:38 +0000 (15:17 +0000)
committerAntony Dovgal <tony2001@php.net>
Tue, 6 Dec 2005 15:17:38 +0000 (15:17 +0000)
ext/filter/callback_filter.c

index fe5c1fb39bd06cb737dcafd53ca3dd9940488dfe..c4a40572c9f079c9939a09af49cd62f7259d6a9a 100644 (file)
 
 void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL)
 {
-       char *name;
-       zval *args[1];
+       char *name = NULL;
+       zval *retval_ptr;
+       zval ***args;
+       int status;
 
        if (!option_array || !zend_is_callable(option_array, IS_CALLABLE_CHECK_NO_ACCESS, &name)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argument is expected to be a valid callback");
-               efree(name);
+               if (name) {
+                       efree(name);
+               }
                zval_dtor(value);
                Z_TYPE_P(value) = IS_NULL;
                return;
        }
+       efree(name);
 
-       args[0] = value;
+       args = safe_emalloc(sizeof(zval **), 1, 0);
+       args[0] = &value;
+       
+       status = call_user_function_ex(EG(function_table), NULL, option_array, &retval_ptr, 1, args, 0, NULL TSRMLS_CC);
 
-       call_user_function(EG(function_table), NULL, option_array, value, 1, args TSRMLS_CC);
+       if (status == SUCCESS && retval_ptr != NULL) {
+               zval_dtor(value);
+               *value = *retval_ptr;
+               zval_copy_ctor(value);
+       }
+       else {
+               zval_dtor(value);
+               Z_TYPE_P(value) = IS_NULL;
+       }
+
+       if (retval_ptr) {
+               zval_ptr_dtor(&retval_ptr);
+       }
+       efree(args);
 }
 
 /*