From: Dmitry Shulga Date: January 18 2011 7:17am Subject: bzr commit into mysql-5.1-bugteam branch (Dmitry.Shulga:3514) Bug#58026 List-Archive: http://lists.mysql.com/commits/129024 X-Bug: 58026 Message-Id: <201101180717.p0I7HnFH007856@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1139274228062440968==" --===============1139274228062440968== 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 2011-01-18 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. @ 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 is not necessary 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 is not necessary 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 2011-01-18 07:17:19 +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 2011-01-18 07:17:19 +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 2011-01-18 07:17:19 +0000 @@ -28,7 +28,9 @@ typedef struct { /* === regcomp.c === */ -extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset); +typedef int (*my_regex_stack_check_t)(); +extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset, + my_regex_stack_check_t 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 2011-01-18 07:17:19 +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; +my_regex_stack_check_t 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,14 @@ 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, + my_regex_stack_check_t check_enough_mem_in_stack); */ 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 */ +my_regex_stack_check_t check_enough_mem_in_stack; { register char c; register sopno UNINIT_VAR(prevback); @@ -221,8 +224,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 +263,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; +my_regex_stack_check_t check_enough_mem_in_stack; { register char c; register sopno pos; @@ -277,7 +287,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 2011-01-18 07:17:19 +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, my_regex_stack_check_t check_enough_mem_in_stack); +static void p_ere_exp(register struct parse *p, my_regex_stack_check_t 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 2011-01-18 07:17:19 +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) { --===============1139274228062440968== 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\ # upb85w50xcvdm0p0 # target_branch: file:///Users/shulga/projects/mysql/5.1-bugteam-\ # bug58026/ # testament_sha1: 139b0e4a349bfa3cb7a9260f7cd98826efa7800b # timestamp: 2011-01-18 13:17:27 +0600 # base_revision_id: davi.arnaut@stripped\ # l0f3bxmcwibcplxq # # Begin bundle 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 --===============1139274228062440968==--