mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Update NEWS & UPGRADING Add fallbacks for older oniguruma versions Add mbstring.regex_stack_limit to php.ini-* Implement RF bug #72777 - ensure stack limits on mbstring functions.
This commit is contained in:
commit
077ce33aa9
7 changed files with 127 additions and 8 deletions
|
@ -60,6 +60,17 @@
|
||||||
# include "php_onig_compat.h"
|
# include "php_onig_compat.h"
|
||||||
# include <oniguruma.h>
|
# include <oniguruma.h>
|
||||||
# undef UChar
|
# undef UChar
|
||||||
|
#if ONIGURUMA_VERSION_INT < 60800
|
||||||
|
typedef void OnigMatchParam;
|
||||||
|
#define onig_new_match_param() (NULL)
|
||||||
|
#define onig_initialize_match_param(x)
|
||||||
|
#define onig_set_match_stack_limit_size_of_match_param(x, y)
|
||||||
|
#define onig_free_match_param(x)
|
||||||
|
#define onig_search_with_param(reg, str, end, start, range, region, option, mp) \
|
||||||
|
onig_search(reg, str, end, start, range, region, option)
|
||||||
|
#define onig_match_with_param(re, str, end, at, region, option, mp) \
|
||||||
|
onig_match(re, str, end, at, region, option)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
# include "ext/pcre/php_pcre.h"
|
# include "ext/pcre/php_pcre.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1031,9 +1042,18 @@ static void *_php_mb_compile_regex(const char *pattern)
|
||||||
/* {{{ _php_mb_match_regex */
|
/* {{{ _php_mb_match_regex */
|
||||||
static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len)
|
static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len)
|
||||||
{
|
{
|
||||||
return onig_search((php_mb_regex_t *)opaque, (const OnigUChar *)str,
|
OnigMatchParam *mp = onig_new_match_param();
|
||||||
(const OnigUChar*)str + str_len, (const OnigUChar *)str,
|
int err;
|
||||||
(const OnigUChar*)str + str_len, NULL, ONIG_OPTION_NONE) >= 0;
|
onig_initialize_match_param(mp);
|
||||||
|
if (!ZEND_LONG_UINT_OVFL(MBSTRG(regex_stack_limit))) {
|
||||||
|
onig_set_match_stack_limit_size_of_match_param(mp, (unsigned int)MBSTRG(regex_stack_limit));
|
||||||
|
}
|
||||||
|
/* search */
|
||||||
|
err = onig_search_with_param((php_mb_regex_t *)opaque, (const OnigUChar *)str,
|
||||||
|
(const OnigUChar*)str + str_len, (const OnigUChar *)str,
|
||||||
|
(const OnigUChar*)str + str_len, NULL, ONIG_OPTION_NONE, mp);
|
||||||
|
onig_free_match_param(mp);
|
||||||
|
return err >= 0;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -1506,6 +1526,9 @@ PHP_INI_BEGIN()
|
||||||
PHP_INI_ALL,
|
PHP_INI_ALL,
|
||||||
OnUpdateBool,
|
OnUpdateBool,
|
||||||
strict_detection, zend_mbstring_globals, mbstring_globals)
|
strict_detection, zend_mbstring_globals, mbstring_globals)
|
||||||
|
#if HAVE_MBREGEX
|
||||||
|
STD_PHP_INI_ENTRY("mbstring.regex_stack_limit", "100000",PHP_INI_ALL, OnUpdateLong, regex_stack_limit, zend_mbstring_globals, mbstring_globals)
|
||||||
|
#endif
|
||||||
PHP_INI_END()
|
PHP_INI_END()
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ ZEND_BEGIN_MODULE_GLOBALS(mbstring)
|
||||||
void *http_output_conv_mimetypes;
|
void *http_output_conv_mimetypes;
|
||||||
#if HAVE_MBREGEX
|
#if HAVE_MBREGEX
|
||||||
struct _zend_mb_regex_globals *mb_regex_globals;
|
struct _zend_mb_regex_globals *mb_regex_globals;
|
||||||
|
zend_long regex_stack_limit;
|
||||||
#endif
|
#endif
|
||||||
zend_string *last_used_encoding_name;
|
zend_string *last_used_encoding_name;
|
||||||
const mbfl_encoding *last_used_encoding;
|
const mbfl_encoding *last_used_encoding;
|
||||||
|
|
|
@ -34,6 +34,18 @@
|
||||||
#include <oniguruma.h>
|
#include <oniguruma.h>
|
||||||
#undef UChar
|
#undef UChar
|
||||||
|
|
||||||
|
#if ONIGURUMA_VERSION_INT < 60800
|
||||||
|
typedef void OnigMatchParam;
|
||||||
|
#define onig_new_match_param() (NULL)
|
||||||
|
#define onig_initialize_match_param(x)
|
||||||
|
#define onig_set_match_stack_limit_size_of_match_param(x, y)
|
||||||
|
#define onig_free_match_param(x)
|
||||||
|
#define onig_search_with_param(reg, str, end, start, range, region, option, mp) \
|
||||||
|
onig_search(reg, str, end, start, range, region, option)
|
||||||
|
#define onig_match_with_param(re, str, end, at, region, option, mp) \
|
||||||
|
onig_match(re, str, end, at, region, option)
|
||||||
|
#endif
|
||||||
|
|
||||||
ZEND_EXTERN_MODULE_GLOBALS(mbstring)
|
ZEND_EXTERN_MODULE_GLOBALS(mbstring)
|
||||||
|
|
||||||
struct _zend_mb_regex_globals {
|
struct _zend_mb_regex_globals {
|
||||||
|
@ -853,6 +865,23 @@ PHP_FUNCTION(mb_regex_encoding)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ _php_mb_onig_search */
|
||||||
|
static int _php_mb_onig_search(regex_t* reg, const OnigUChar* str, const OnigUChar* end, const OnigUChar* start,
|
||||||
|
const OnigUChar* range, OnigRegion* region, OnigOptionType option) {
|
||||||
|
OnigMatchParam *mp = onig_new_match_param();
|
||||||
|
int err;
|
||||||
|
onig_initialize_match_param(mp);
|
||||||
|
if (!ZEND_LONG_UINT_OVFL(MBSTRG(regex_stack_limit))) {
|
||||||
|
onig_set_match_stack_limit_size_of_match_param(mp, (unsigned int)MBSTRG(regex_stack_limit));
|
||||||
|
}
|
||||||
|
/* search */
|
||||||
|
err = onig_search_with_param(reg, str, end, start, range, region, option, mp);
|
||||||
|
onig_free_match_param(mp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
/* {{{ _php_mb_regex_ereg_exec */
|
/* {{{ _php_mb_regex_ereg_exec */
|
||||||
static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
|
static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
|
||||||
{
|
{
|
||||||
|
@ -914,7 +943,7 @@ static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
|
||||||
regs = onig_region_new();
|
regs = onig_region_new();
|
||||||
|
|
||||||
/* actually execute the regular expression */
|
/* actually execute the regular expression */
|
||||||
if (onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, (OnigUChar *)(string + string_len), regs, 0) < 0) {
|
if (_php_mb_onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, (OnigUChar *)(string + string_len), regs, 0) < 0) {
|
||||||
RETVAL_FALSE;
|
RETVAL_FALSE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1124,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
|
||||||
string_lim = (OnigUChar*)(string + string_len);
|
string_lim = (OnigUChar*)(string + string_len);
|
||||||
regs = onig_region_new();
|
regs = onig_region_new();
|
||||||
while (err >= 0) {
|
while (err >= 0) {
|
||||||
err = onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0);
|
err = _php_mb_onig_search(re, (OnigUChar *)string, (OnigUChar *)string_lim, pos, (OnigUChar *)string_lim, regs, 0);
|
||||||
if (err <= -2) {
|
if (err <= -2) {
|
||||||
OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
|
OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
|
||||||
onig_error_code_to_str(err_str, err);
|
onig_error_code_to_str(err_str, err);
|
||||||
|
@ -1276,7 +1305,7 @@ PHP_FUNCTION(mb_split)
|
||||||
/* churn through str, generating array entries as we go */
|
/* churn through str, generating array entries as we go */
|
||||||
while (count != 0 && (size_t)(pos - (OnigUChar *)string) < string_len) {
|
while (count != 0 && (size_t)(pos - (OnigUChar *)string) < string_len) {
|
||||||
size_t beg, end;
|
size_t beg, end;
|
||||||
err = onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), pos, (OnigUChar *)(string + string_len), regs, 0);
|
err = _php_mb_onig_search(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), pos, (OnigUChar *)(string + string_len), regs, 0);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1333,6 +1362,7 @@ PHP_FUNCTION(mb_ereg_match)
|
||||||
OnigSyntaxType *syntax;
|
OnigSyntaxType *syntax;
|
||||||
OnigOptionType option = 0;
|
OnigOptionType option = 0;
|
||||||
int err;
|
int err;
|
||||||
|
OnigMatchParam *mp;
|
||||||
|
|
||||||
{
|
{
|
||||||
char *option_str = NULL;
|
char *option_str = NULL;
|
||||||
|
@ -1361,8 +1391,14 @@ PHP_FUNCTION(mb_ereg_match)
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp = onig_new_match_param();
|
||||||
|
onig_initialize_match_param(mp);
|
||||||
|
if(MBSTRG(regex_stack_limit) > 0 && MBSTRG(regex_stack_limit) < UINT_MAX) {
|
||||||
|
onig_set_match_stack_limit_size_of_match_param(mp, (unsigned int)MBSTRG(regex_stack_limit));
|
||||||
|
}
|
||||||
/* match */
|
/* match */
|
||||||
err = onig_match(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, NULL, 0);
|
err = onig_match_with_param(re, (OnigUChar *)string, (OnigUChar *)(string + string_len), (OnigUChar *)string, NULL, 0, mp);
|
||||||
|
onig_free_match_param(mp);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
RETVAL_TRUE;
|
RETVAL_TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1425,7 +1461,7 @@ _php_mb_regex_ereg_search_exec(INTERNAL_FUNCTION_PARAMETERS, int mode)
|
||||||
}
|
}
|
||||||
MBREX(search_regs) = onig_region_new();
|
MBREX(search_regs) = onig_region_new();
|
||||||
|
|
||||||
err = onig_search(MBREX(search_re), str, str + len, str + pos, str + len, MBREX(search_regs), 0);
|
err = _php_mb_onig_search(MBREX(search_re), str, str + len, str + pos, str + len, MBREX(search_regs), 0);
|
||||||
if (err == ONIG_MISMATCH) {
|
if (err == ONIG_MISMATCH) {
|
||||||
MBREX(search_pos) = len;
|
MBREX(search_pos) = len;
|
||||||
RETVAL_FALSE;
|
RETVAL_FALSE;
|
||||||
|
|
24
ext/mbstring/tests/mbregex_stack_limit.phpt
Normal file
24
ext/mbstring/tests/mbregex_stack_limit.phpt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
Test oniguruma stack limit
|
||||||
|
--SKIPIF--
|
||||||
|
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$s = str_repeat(' ', 30000);
|
||||||
|
|
||||||
|
ini_set('mbstring.regex_stack_limit', 10000);
|
||||||
|
var_dump(mb_ereg('\\s+$', $s));
|
||||||
|
|
||||||
|
ini_set('mbstring.regex_stack_limit', 30000);
|
||||||
|
var_dump(mb_ereg('\\s+$', $s));
|
||||||
|
|
||||||
|
ini_set('mbstring.regex_stack_limit', 30001);
|
||||||
|
var_dump(mb_ereg('\\s+$', $s));
|
||||||
|
|
||||||
|
echo 'OK';
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
int(1)
|
||||||
|
OK
|
25
ext/mbstring/tests/mbregex_stack_limit2.phpt
Normal file
25
ext/mbstring/tests/mbregex_stack_limit2.phpt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
--TEST--
|
||||||
|
Test oniguruma stack limit
|
||||||
|
--SKIPIF--
|
||||||
|
<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function mb_trim( $string, $chars = "", $chars_array = array() )
|
||||||
|
{
|
||||||
|
for( $x=0; $x<iconv_strlen( $chars ); $x++ ) $chars_array[] = preg_quote( iconv_substr( $chars, $x, 1 ) );
|
||||||
|
$encoded_char_list = implode( "|", array_merge( array( "\s","\t","\n","\r", "\0", "\x0B" ), $chars_array ) );
|
||||||
|
|
||||||
|
$string = mb_ereg_replace( "^($encoded_char_list)*", "", $string );
|
||||||
|
$string = mb_ereg_replace( "($encoded_char_list)*$", "", $string );
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_set('mbstring.regex_stack_limit', 10000);
|
||||||
|
var_dump(mb_trim(str_repeat(' ', 10000)));
|
||||||
|
|
||||||
|
echo 'OK';
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: mb_ereg_replace(): mbregex search failure in php_mbereg_replace_exec(): match-stack limit over in %s on line %d
|
||||||
|
string(0) ""
|
||||||
|
OK
|
|
@ -1712,6 +1712,11 @@ zend.assertions = 1
|
||||||
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
|
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
|
||||||
;mbstring.http_output_conv_mimetype=
|
;mbstring.http_output_conv_mimetype=
|
||||||
|
|
||||||
|
; This directive specifies maximum stack depth for mbstring regular expressions. It is similar
|
||||||
|
; to the pcre.recursion_limit for PCRE.
|
||||||
|
; Default: 100000
|
||||||
|
;mbstring.regex_stack_limit=100000
|
||||||
|
|
||||||
[gd]
|
[gd]
|
||||||
; Tell the jpeg decode to ignore warnings and try to create
|
; Tell the jpeg decode to ignore warnings and try to create
|
||||||
; a gd image. The warning will then be displayed as notices
|
; a gd image. The warning will then be displayed as notices
|
||||||
|
|
|
@ -1719,6 +1719,11 @@ zend.assertions = -1
|
||||||
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
|
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
|
||||||
;mbstring.http_output_conv_mimetype=
|
;mbstring.http_output_conv_mimetype=
|
||||||
|
|
||||||
|
; This directive specifies maximum stack depth for mbstring regular expressions. It is similar
|
||||||
|
; to the pcre.recursion_limit for PCRE.
|
||||||
|
; Default: 100000
|
||||||
|
;mbstring.regex_stack_limit=100000
|
||||||
|
|
||||||
[gd]
|
[gd]
|
||||||
; Tell the jpeg decode to ignore warnings and try to create
|
; Tell the jpeg decode to ignore warnings and try to create
|
||||||
; a gd image. The warning will then be displayed as notices
|
; a gd image. The warning will then be displayed as notices
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue