From: Dmitry Shulga Date: November 24 2010 9:07am Subject: bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3514) Bug#58026 List-Archive: http://lists.mysql.com/commits/124816 X-Bug: 58026 Message-Id: <201011240908.oAO98UOW014007@rcsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2119161836==" --===============2119161836== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/shulga/projects/mysql/5.1-bugteam-bug58026/ based on revid:davi.arnaut@stripped 3514 Dmitry Shulga 2010-11-24 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 was not take care of available memory, which may lead to stack overflow crashes. @ client/mysqltest.cc Passed NULL pointer to function as last actual argument in call to my_regcomp. In this case check for enough memory in stack doesn't occur. Such checking doesn't need in mysql clients. @ regex/main.c Passed NULL pointer to function as last actual argument in call to my_regcomp. In this case check for enough memory in stack doesn't occur. Such checking doesn't need in regex's regression tests. @ regex/my_regex.h added pointer to function as last argument of my_regcomp() for check enough memory in stack. @ regex/regcomp.c Added pointer to function as last argument of p_ere()/p_ere_exp() that called in order to check that there are enough memory in stack for next recursion call. @ regex/regcomp.ih added pointer to function as last argument of my_regcomp() for check enough memory in stack. @ sql/item_cmpfunc.cc Passed pointer to function check_enough_stack_size() in call to my_regcomp(). The function check_enough_stack_size() will be called in during recursive descendant for regular expression parsing. modified: client/mysqltest.cc regex/main.c regex/my_regex.h regex/regcomp.c regex/regcomp.ih sql/item_cmpfunc.cc === modified file 'client/mysqltest.cc' --- a/client/mysqltest.cc 2010-11-19 09:29:08 +0000 +++ b/client/mysqltest.cc 2010-11-24 09:07:00 +0000 @@ -7593,7 +7593,7 @@ char *re_eprint(int err) void init_re_comp(my_regex_t *re, const char* str) { int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), - &my_charset_latin1); + &my_charset_latin1, NULL); if (err) { char erbuf[100]; @@ -9032,7 +9032,7 @@ int reg_replace(char** buf_p, int* buf_l if (icase) cflags|= REG_ICASE; - if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1))) + if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1, NULL))) { check_regerr(&r,err_code); return 1; === modified file 'regex/main.c' --- a/regex/main.c 2010-10-19 22:36:59 +0000 +++ b/regex/main.c 2010-11-24 09:07:00 +0000 @@ -74,7 +74,8 @@ char *argv[]; exit(status); } - err = my_regcomp(&re, argv[optind++], copts, &my_charset_latin1); + err = my_regcomp(&re, argv[optind++], copts, &my_charset_latin1, + NULL); if (err) { len = my_regerror(err, &re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", @@ -226,7 +227,7 @@ int opts; /* may not match f1 */ strcpy(f0copy, f0); re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL; fixstr(f0copy); - err = my_regcomp(&re, f0copy, opts, &my_charset_latin1); + err = my_regcomp(&re, f0copy, opts, &my_charset_latin1, NULL); if (err != 0 && (!opt('C', f1) || err != efind(f2))) { /* unexpected error or wrong error */ len = my_regerror(err, &re, erbuf, sizeof(erbuf)); === modified file 'regex/my_regex.h' --- a/regex/my_regex.h 2005-09-29 00:08:24 +0000 +++ b/regex/my_regex.h 2010-11-24 09:07:00 +0000 @@ -28,7 +28,8 @@ typedef struct { /* === regcomp.c === */ -extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset); +extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset, + int (*check_enough_mem_in_stack)()); #define REG_BASIC 0000 #define REG_EXTENDED 0001 #define REG_ICASE 0002 === modified file 'regex/regcomp.c' --- a/regex/regcomp.c 2010-07-09 19:37:52 +0000 +++ b/regex/regcomp.c 2010-11-24 09:07:00 +0000 @@ -100,11 +100,12 @@ static int never = 0; /* for use in ass = #define REG_DUMP 0200 */ int /* 0 success, otherwise REG_something */ -my_regcomp(preg, pattern, cflags, charset) +my_regcomp(preg, pattern, cflags, charset, check_enough_mem_in_stack) my_regex_t *preg; const char *pattern; int cflags; CHARSET_INFO *charset; +int (*check_enough_mem_in_stack)(); { struct parse pa; register struct re_guts *g; @@ -174,7 +175,7 @@ CHARSET_INFO *charset; EMIT(OEND, 0); g->firststate = THERE(); if (cflags®_EXTENDED) - p_ere(p, OUT); + p_ere(p, OUT, check_enough_mem_in_stack); else if (cflags®_NOSPEC) p_str(p); else @@ -205,12 +206,13 @@ CHARSET_INFO *charset; /* - p_ere - ERE parser top level, concatenation and alternation - == static void p_ere(register struct parse *p, int stop); + == static void p_ere(register struct parse *p, int stop, (int*)(check_stack_overun)()); */ static void -p_ere(p, stop) +p_ere(p, stop, check_enough_mem_in_stack) register struct parse *p; int stop; /* character this ERE should end at */ +int (*check_enough_mem_in_stack)(); { register char c; register sopno UNINIT_VAR(prevback); @@ -221,8 +223,14 @@ int stop; /* character this ERE should for (;;) { /* do a bunch of concatenated expressions */ conc = HERE(); - while (MORE() && (c = PEEK()) != '|' && c != stop) - p_ere_exp(p); + while (MORE() && (c = PEEK()) != '|' && c != stop) { + if (check_enough_mem_in_stack && + check_enough_mem_in_stack()) { + SETERROR(REG_ESPACE); + return; + } + p_ere_exp(p, check_enough_mem_in_stack); + } if(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */ if (!EAT('|')) @@ -254,8 +262,9 @@ int stop; /* character this ERE should == static void p_ere_exp(register struct parse *p); */ static void -p_ere_exp(p) +p_ere_exp(p,check_enough_mem_in_stack) register struct parse *p; +int (*check_enough_mem_in_stack)(); { register char c; register sopno pos; @@ -277,7 +286,7 @@ register struct parse *p; p->pbegin[subno] = HERE(); EMIT(OLPAREN, subno); if (!SEE(')')) - p_ere(p, ')'); + p_ere(p, ')', check_enough_mem_in_stack); if (subno < NPAREN) { p->pend[subno] = HERE(); assert(p->pend[subno] != 0); === modified file 'regex/regcomp.ih' --- a/regex/regcomp.ih 2004-10-19 22:28:42 +0000 +++ b/regex/regcomp.ih 2010-11-24 09:07:00 +0000 @@ -4,8 +4,8 @@ extern "C" { #endif /* === regcomp.c === */ -static void p_ere(register struct parse *p, int stop); -static void p_ere_exp(register struct parse *p); +static void p_ere(register struct parse *p, int stop, int (*check_enough_mem_in_stack)()); +static void p_ere_exp(register struct parse *p, int (*check_enough_mem_in_stack)()); static void p_str(register struct parse *p); static void p_bre(register struct parse *p, register int end1, register int end2); static int p_simp_re(register struct parse *p, int starordinary); === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2010-09-09 12:48:06 +0000 +++ b/sql/item_cmpfunc.cc 2010-11-24 09:07:00 +0000 @@ -4791,6 +4791,18 @@ void Item_func_like::cleanup() #ifdef USE_REGEX +extern "C" +int +check_enough_stack_size() +{ +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + uchar stack_top; +#endif + return check_stack_overrun(current_thd, STACK_MIN_SIZE, + &stack_top); +} + + /** @brief Compile regular expression. @@ -4834,7 +4846,8 @@ int Item_func_regex::regcomp(bool send_e } if ((error= my_regcomp(&preg, res->c_ptr_safe(), - regex_lib_flags, regex_lib_charset))) + regex_lib_flags, regex_lib_charset, + check_enough_stack_size))) { if (send_error) { --===============2119161836== 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\ # w1hfdjmntgzv5tuh # target_branch: file:///Users/shulga/projects/mysql/5.1-bugteam-\ # bug58026/ # testament_sha1: 7102f18a218e9ea6d2ef01de7caf107ffd3d9c68 # timestamp: 2010-11-24 15:07:14 +0600 # base_revision_id: davi.arnaut@stripped\ # l0f3bxmcwibcplxq # # Begin bundle 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 +LuSKcKEgfU8Y4g= --===============2119161836==--