]> granicus.if.org Git - php/commitdiff
Fix #55819 crash on mb_ereg_replace_callback
authorXinchen Hui <laruence@php.net>
Fri, 7 Oct 2011 04:24:04 +0000 (04:24 +0000)
committerXinchen Hui <laruence@php.net>
Fri, 7 Oct 2011 04:24:04 +0000 (04:24 +0000)
Need hirokawa to review this.

ext/mbstring/php_mbregex.c

index 64db8396e84cff9f621854704a73299d65e2c327..f3fd96a5569a04ad7716f09bbf9eecbe337c4b2e 100644 (file)
@@ -793,11 +793,12 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
 
        char *replace;
        int replace_len;
-       zval **arg_replace_zval;
+
+       zend_fcall_info arg_replace_fci;
+       zend_fcall_info_cache arg_replace_fci_cache;
 
        char *string;
        int string_len;
-       zval **arg_string_zval;
 
        char *p;
        php_mb_regex_t *re;
@@ -828,20 +829,24 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
                char *option_str = NULL;
                int option_str_len = 0;
 
-               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|s",
-                                                                 &arg_pattern_zval,
-                                                                 &arg_replace_zval,
-                                                                 &arg_string_zval,
-                                                                 &option_str, &option_str_len) == FAILURE) {
-                       RETURN_FALSE;
+               if (!is_callable) {
+                       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
+                                               &arg_pattern_zval,
+                                               &replace, &replace_len,
+                                               &string, &string_len,
+                                               &option_str, &option_str_len) == FAILURE) {
+                               RETURN_FALSE;
+                       }
+               } else {
+                       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zfs|s",
+                                               &arg_pattern_zval,
+                                               &arg_replace_fci, &arg_replace_fci_cache,
+                                               &string, &string_len,
+                                               &option_str, &option_str_len) == FAILURE) {
+                               RETURN_FALSE;
+                       }
                }
 
-               replace = Z_STRVAL_PP(arg_replace_zval);
-               replace_len = Z_STRLEN_PP(arg_replace_zval);
-
-               string = Z_STRVAL_PP(arg_string_zval);
-               string_len = Z_STRLEN_PP(arg_string_zval);
-
                if (option_str != NULL) {
                        _php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval);
                } else {
@@ -876,15 +881,6 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
        }
 
        if (is_callable) {
-               char *callback_name;
-               if (!zend_is_callable(*arg_replace_zval, 0, &callback_name TSRMLS_CC)) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires argument 2, '%s', to be a valid callback", callback_name);
-                       efree(callback_name);
-                       MAKE_COPY_ZVAL(arg_string_zval, return_value);
-                       RETURN_FALSE;
-               }
-               efree(callback_name);
-
                if (eval) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option 'e' cannot be used with replacement callback");
                        RETURN_FALSE;
@@ -973,8 +969,10 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
                                /* null terminate buffer */
                                smart_str_0(&eval_buf);
                                
-                               if (call_user_function_ex(EG(function_table), NULL, *arg_replace_zval, &retval_ptr, 1, args, 0, 
-                                                                                 NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
+                               arg_replace_fci.param_count = 1;
+                               arg_replace_fci.params = args;
+                               arg_replace_fci.retval_ptr_ptr = &retval_ptr;
+                               if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr) {
                                        convert_to_string_ex(&retval_ptr);
                                        smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
                                        eval_buf.len = 0;