diff options
Diffstat (limited to 'bug72402.patch')
-rw-r--r-- | bug72402.patch | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/bug72402.patch b/bug72402.patch new file mode 100644 index 0000000..5e7243f --- /dev/null +++ b/bug72402.patch @@ -0,0 +1,284 @@ +From 5b597a2e5b28e2d5a52fc1be13f425f08f47cb62 Mon Sep 17 00:00:00 2001 +From: Stanislav Malyshev <stas@php.net> +Date: Sat, 18 Jun 2016 21:48:39 -0700 +Subject: [PATCH] Fix bug #72402: _php_mb_regex_ereg_replace_exec - double free + +--- + ext/mbstring/php_mbregex.c | 65 ++++++++++++++++++++-------------------- + ext/mbstring/tests/bug72402.phpt | 17 +++++++++++ + 2 files changed, 49 insertions(+), 33 deletions(-) + create mode 100644 ext/mbstring/tests/bug72402.phpt + +diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c +index d73c848..6cdee23 100644 +--- a/ext/mbstring/php_mbregex.c ++++ b/ext/mbstring/php_mbregex.c +@@ -32,7 +32,7 @@ + #include "ext/standard/info.h" + #include "php_mbregex.h" + #include "mbstring.h" +- ++ + #include "php_onig_compat.h" /* must come prior to the oniguruma header */ + #include <oniguruma.h> + #undef UChar +@@ -55,7 +55,7 @@ struct _zend_mb_regex_globals { + #define MBREX(g) (MBSTRG(mb_regex_globals)->g) + + /* {{{ static void php_mb_regex_free_cache() */ +-static void php_mb_regex_free_cache(php_mb_regex_t **pre) ++static void php_mb_regex_free_cache(php_mb_regex_t **pre) + { + onig_free(*pre); + } +@@ -78,7 +78,7 @@ static int _php_mb_regex_globals_ctor(zend_mb_regex_globals *pglobals TSRMLS_DC) + /* }}} */ + + /* {{{ _php_mb_regex_globals_dtor */ +-static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) ++static void _php_mb_regex_globals_dtor(zend_mb_regex_globals *pglobals TSRMLS_DC) + { + zend_hash_destroy(&pglobals->ht_rc); + } +@@ -466,7 +466,7 @@ static php_mb_regex_t *php_mbregex_compile_pattern(const char *pattern, int patl + retval = *rc; + } + out: +- return retval; ++ return retval; + } + /* }}} */ + +@@ -483,7 +483,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + --len_left; + *(p++) = 'i'; + } +- ++len_req; ++ ++len_req; + } + + if ((option & ONIG_OPTION_EXTEND) != 0) { +@@ -491,7 +491,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + --len_left; + *(p++) = 'x'; + } +- ++len_req; ++ ++len_req; + } + + if ((option & (ONIG_OPTION_MULTILINE | ONIG_OPTION_SINGLELINE)) == +@@ -500,14 +500,14 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + --len_left; + *(p++) = 'p'; + } +- ++len_req; ++ ++len_req; + } else { + if ((option & ONIG_OPTION_MULTILINE) != 0) { + if (len_left > 0) { + --len_left; + *(p++) = 'm'; + } +- ++len_req; ++ ++len_req; + } + + if ((option & ONIG_OPTION_SINGLELINE) != 0) { +@@ -515,22 +515,22 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + --len_left; + *(p++) = 's'; + } +- ++len_req; ++ ++len_req; + } +- } ++ } + if ((option & ONIG_OPTION_FIND_LONGEST) != 0) { + if (len_left > 0) { + --len_left; + *(p++) = 'l'; + } +- ++len_req; ++ ++len_req; + } + if ((option & ONIG_OPTION_FIND_NOT_EMPTY) != 0) { + if (len_left > 0) { + --len_left; + *(p++) = 'n'; + } +- ++len_req; ++ ++len_req; + } + + c = 0; +@@ -566,7 +566,7 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + --len_left; + *(p++) = '\0'; + } +- ++len_req; ++ ++len_req; + if (len < len_req) { + return len_req; + } +@@ -577,11 +577,11 @@ static size_t _php_mb_regex_get_option_string(char *str, size_t len, OnigOptionT + + /* {{{ _php_mb_regex_init_options */ + static void +-_php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) ++_php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, OnigSyntaxType **syntax, int *eval) + { + int n; + char c; +- int optm = 0; ++ int optm = 0; + + *syntax = ONIG_SYNTAX_RUBY; + +@@ -636,13 +636,13 @@ _php_mb_regex_init_options(const char *parg, int narg, OnigOptionType *option, O + *syntax = ONIG_SYNTAX_POSIX_EXTENDED; + break; + case 'e': +- if (eval != NULL) *eval = 1; ++ if (eval != NULL) *eval = 1; + break; + default: + break; + } + } +- if (option != NULL) *option|=optm; ++ if (option != NULL) *option|=optm; + } + } + /* }}} */ +@@ -860,11 +860,11 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp + } else { + /* FIXME: this code is not multibyte aware! */ + convert_to_long_ex(arg_pattern_zval); +- pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); ++ pat_buf[0] = (char)Z_LVAL_PP(arg_pattern_zval); + pat_buf[1] = '\0'; + + arg_pattern = pat_buf; +- arg_pattern_len = 1; ++ arg_pattern_len = 1; + } + /* create regex pattern buffer */ + re = php_mbregex_compile_pattern(arg_pattern, arg_pattern_len, options, MBREX(current_mbctype), syntax TSRMLS_CC); +@@ -934,7 +934,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp + } + } + } +- ++ + if (eval) { + zval v; + /* null terminate buffer */ +@@ -953,32 +953,31 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp + eval_buf.len = 0; + zval_dtor(&v); + } else if (is_callable) { +- zval *retval_ptr; ++ zval *retval_ptr = NULL; + zval **args[1]; + zval *subpats; + int i; +- ++ + MAKE_STD_ZVAL(subpats); + array_init(subpats); +- ++ + for (i = 0; i < regs->num_regs; i++) { + add_next_index_stringl(subpats, string + regs->beg[i], regs->end[i] - regs->beg[i], 1); +- } +- ++ } ++ + args[0] = &subpats; + /* null terminate buffer */ + smart_str_0(&eval_buf); +- ++ + 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) { ++ if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr && retval_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; + zval_ptr_dtor(&retval_ptr); + } else { +- efree(description); + if (!EG(exception)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function"); + } +@@ -991,7 +990,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp + pos = (OnigUChar *)string + n; + } else { + if (pos < string_lim) { +- smart_str_appendl(&out_buf, pos, 1); ++ smart_str_appendl(&out_buf, pos, 1); + } + pos++; + } +@@ -1013,7 +1012,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp + smart_str_free(&eval_buf); + + if (err <= -2) { +- smart_str_free(&out_buf); ++ smart_str_free(&out_buf); + RETVAL_FALSE; + } else { + smart_str_appendc(&out_buf, '\0'); +@@ -1063,7 +1062,7 @@ PHP_FUNCTION(mb_split) + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &arg_pattern, &arg_pattern_len, &string, &string_len, &count) == FAILURE) { + RETURN_FALSE; +- } ++ } + + if (count > 0) { + count--; +@@ -1317,7 +1316,7 @@ PHP_FUNCTION(mb_ereg_search_init) + if (zend_parse_parameters(argc TSRMLS_CC, "z|ss", &arg_str, &arg_pattern, &arg_pattern_len, &arg_options, &arg_options_len) == FAILURE) { + return; + } +- ++ + if (argc > 1 && arg_pattern_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty pattern"); + RETURN_FALSE; +@@ -1416,7 +1415,7 @@ PHP_FUNCTION(mb_ereg_search_setpos) + /* }}} */ + + /* {{{ php_mb_regex_set_options */ +-static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) ++static void _php_mb_regex_set_options(OnigOptionType options, OnigSyntaxType *syntax, OnigOptionType *prev_options, OnigSyntaxType **prev_syntax TSRMLS_DC) + { + if (prev_options != NULL) { + *prev_options = MBREX(regex_default_options); +diff --git a/ext/mbstring/tests/bug72402.phpt b/ext/mbstring/tests/bug72402.phpt +new file mode 100644 +index 0000000..abb290b +--- /dev/null ++++ b/ext/mbstring/tests/bug72402.phpt +@@ -0,0 +1,17 @@ ++--TEST-- ++Bug #72402: _php_mb_regex_ereg_replace_exec - double free ++--SKIPIF-- ++<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?> ++--FILE-- ++<?php ++function throwit() { ++ throw new Exception('it'); ++} ++$var10 = "throwit"; ++try { ++ $var14 = mb_ereg_replace_callback("", $var10, ""); ++} catch(Exception $e) {} ++?> ++DONE ++--EXPECT-- ++DONE +\ No newline at end of file |