From: Dmitry Shulga Date: February 3 2011 9:28am Subject: bzr commit into mysql-5.1 branch (Dmitry.Shulga:3575) Bug#58026 List-Archive: http://lists.mysql.com/commits/130304 X-Bug: 58026 Message-Id: <201102030928.p137Artg015532@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============6575022765474974675==" --===============6575022765474974675== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/mysql-5.1-bug58026/ based on revid:georgi.kodinov@stripped 3575 Dmitry Shulga 2011-02-03 Fixed bug#58026 - massive recursion and crash in regular expression handling. The problem was that parsing of nested regular expression involved recursive calls. Such recursion didn't take into account the amount of available stack space, which ended up leading to stack overflow crashes. @ mysql-test/t/not_embedded_server.test Added test for bug#58026. @ regex/my_regex.h added pointer to function as last argument of my_regex_init() for check enough memory in stack. @ regex/regcomp.c p_ere() was modified: added call to function for check enough memory in stack. Function for check available stack space specified by global variable my_regex_enough_mem_in_stack. This variable set to NULL for embedded mysqld and to a pointer to function check_enough_stack_size otherwise. @ regex/reginit.c my_regex_init was modified: pass a pointer to a function for check enough memory in stack space. Reset this pointer to NULL in my_regex_end. @ sql/mysqld.cc Added function check_enough_stack_size() for check enough memory in stack. Passed this function as second argument to my_regex_init. For embedded mysqld passed NULL as second argument. modified: mysql-test/r/not_embedded_server.result mysql-test/t/not_embedded_server.test regex/my_regex.h regex/regcomp.c regex/reginit.c sql/mysqld.cc === modified file 'mysql-test/r/not_embedded_server.result' --- a/mysql-test/r/not_embedded_server.result 2009-04-30 10:29:19 +0000 +++ b/mysql-test/r/not_embedded_server.result 2011-02-03 09:28:04 +0000 @@ -4,3 +4,7 @@ select 1; SHOW VARIABLES like 'slave_skip_errors'; Variable_name Value slave_skip_errors OFF +# +# Bug#58026: massive recursion and crash in regular expression handling +# +SELECT '1' RLIKE RPAD('1', 10000, '('); === modified file 'mysql-test/t/not_embedded_server.test' --- a/mysql-test/t/not_embedded_server.test 2009-04-30 10:29:19 +0000 +++ b/mysql-test/t/not_embedded_server.test 2011-02-03 09:28:04 +0000 @@ -42,4 +42,14 @@ select 1; SHOW VARIABLES like 'slave_skip_errors'; +--echo # +--echo # Bug#58026: massive recursion and crash in regular expression handling +--echo # + +--disable_result_log +--error ER_STACK_OVERRUN_NEED_MORE +SELECT '1' RLIKE RPAD('1', 10000, '('); +--enable_result_log + + # End of 5.1 tests === modified file 'regex/my_regex.h' --- a/regex/my_regex.h 2005-09-29 00:08:24 +0000 +++ b/regex/my_regex.h 2011-02-03 09:28:04 +0000 @@ -28,6 +28,7 @@ typedef struct { /* === regcomp.c === */ +typedef int (*my_regex_stack_check_t)(); extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset); #define REG_BASIC 0000 #define REG_EXTENDED 0001 @@ -76,7 +77,8 @@ extern void my_regfree(my_regex_t *); /* === reginit.c === */ -extern void my_regex_init(CHARSET_INFO *cs); /* Should be called for multithread progs */ +/* Should be called for multithread progs */ +extern void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func); extern void my_regex_end(void); /* If one wants a clean end */ #ifdef __cplusplus === modified file 'regex/regcomp.c' --- a/regex/regcomp.c 2010-07-09 19:37:52 +0000 +++ b/regex/regcomp.c 2011-02-03 09:28:04 +0000 @@ -31,6 +31,9 @@ struct parse { CHARSET_INFO *charset; /* for ctype things */ }; +/* Check if there is enough stack space for recursion. */ +my_regex_stack_check_t my_regex_enough_mem_in_stack= NULL; + #include "regcomp.ih" static char nuls[10]; /* place to point scanner in event of error */ @@ -117,7 +120,7 @@ CHARSET_INFO *charset; # define GOODFLAGS(f) ((f)&~REG_DUMP) #endif - my_regex_init(charset); /* Init cclass if neaded */ + my_regex_init(charset, NULL); /* Init cclass if neaded */ preg->charset=charset; cflags = GOODFLAGS(cflags); if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) @@ -222,7 +225,15 @@ int stop; /* character this ERE should /* do a bunch of concatenated expressions */ conc = HERE(); while (MORE() && (c = PEEK()) != '|' && c != stop) - p_ere_exp(p); + { + if (my_regex_enough_mem_in_stack && + my_regex_enough_mem_in_stack()) + { + SETERROR(REG_ESPACE); + return; + } + p_ere_exp(p); + } if(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */ if (!EAT('|')) === modified file 'regex/reginit.c' --- a/regex/reginit.c 2008-02-18 22:29:39 +0000 +++ b/regex/reginit.c 2011-02-03 09:28:04 +0000 @@ -4,10 +4,12 @@ #include #include #include "cclass.h" +#include "my_regex.h" static my_bool regex_inited=0; +extern my_regex_stack_check_t my_regex_enough_mem_in_stack; -void my_regex_init(CHARSET_INFO *cs) +void my_regex_init(CHARSET_INFO *cs, my_regex_stack_check_t func) { char buff[CCLASS_LAST][256]; int count[CCLASS_LAST]; @@ -16,6 +18,7 @@ void my_regex_init(CHARSET_INFO *cs) if (!regex_inited) { regex_inited=1; + my_regex_enough_mem_in_stack= func; bzero((uchar*) &count,sizeof(count)); for (i=1 ; i<= 255; i++) @@ -74,6 +77,7 @@ void my_regex_end() int i; for (i=0; i < CCLASS_LAST ; i++) free((char*) cclasses[i].chars); + my_regex_enough_mem_in_stack= NULL; regex_inited=0; } } === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2011-02-02 17:05:28 +0000 +++ b/sql/mysqld.cc 2011-02-03 09:28:04 +0000 @@ -3034,6 +3034,19 @@ sizeof(load_default_groups)/sizeof(load_ #endif +#ifndef EMBEDDED_LIBRARY +static +int +check_enough_stack_size() +{ + uchar stack_top; + + return check_stack_overrun(current_thd, STACK_MIN_SIZE, + &stack_top); +} +#endif + + /** Initialize one of the global date/time format variables. @@ -3415,7 +3428,11 @@ static int init_common_variables(const c #endif mysys_uses_curses=0; #ifdef USE_REGEX - my_regex_init(&my_charset_latin1); +#ifndef EMBEDDED_LIBRARY + my_regex_init(&my_charset_latin1, check_enough_stack_size); +#else + my_regex_init(&my_charset_latin1, NULL); +#endif #endif /* Process a comma-separated character set list and choose --===============6575022765474974675== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.shulga@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.shulga@stripped\ # 4hfgs9hnlsgydhjj # target_branch: file:///Users/shulga/projects/mysql/mysql-5.1-\ # bug58026/ # testament_sha1: 729a6a71fdb434f6738e742ba5acc47a2a9e7ddf # timestamp: 2011-02-03 15:28:17 +0600 # source_branch: file:///Users/shulga/projects/mysql/5.1-bugteam-\ # bug58026/ # base_revision_id: georgi.kodinov@stripped\ # 43bd41beoas8nlcd # # Begin bundle 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 HQ8vt1RjH/xdyRThQkHgEhu8 --===============6575022765474974675==--