diff options
author | Neeraj Bisht <neeraj.x.bisht@oracle.com> | 2013-01-14 16:51:52 +0530 |
---|---|---|
committer | Neeraj Bisht <neeraj.x.bisht@oracle.com> | 2013-01-14 16:51:52 +0530 |
commit | 84d798a1d533fb20cdb90dc0bcfae0891873f1bf (patch) | |
tree | 59d42a3d31a24a34b677d3383a42f33feb39b9f5 | |
parent | fd5380b4964df7e0202bd9b9ac77f6874018e185 (diff) | |
parent | 99645e5be59145bcab2fe36aefde4224e6e69961 (diff) | |
download | mariadb-git-84d798a1d533fb20cdb90dc0bcfae0891873f1bf.tar.gz |
BUG#14303860 - EXECUTING A SELECT QUERY WITH TOO
MANY WILDCARDS CAUSES A SEGFAULT
Back port from 5.6 and trunk
-rw-r--r-- | include/m_ctype.h | 2 | ||||
-rw-r--r-- | regex/my_regex.h | 2 | ||||
-rw-r--r-- | regex/regcomp.c | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 22 | ||||
-rw-r--r-- | strings/ctype-bin.c | 27 | ||||
-rw-r--r-- | strings/ctype-mb.c | 51 | ||||
-rw-r--r-- | strings/ctype-simple.c | 26 | ||||
-rw-r--r-- | strings/ctype-uca.c | 26 | ||||
-rw-r--r-- | strings/ctype-utf8.c | 33 | ||||
-rw-r--r-- | strings/ctype.c | 2 |
10 files changed, 144 insertions, 49 deletions
diff --git a/include/m_ctype.h b/include/m_ctype.h index ac4b5d14799..e30a2f444dd 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -149,6 +149,8 @@ enum my_lex_states struct charset_info_st; +extern int (*my_string_stack_guard)(int); + /* See strings/CHARSET_INFO.txt for information about this structure */ typedef struct my_collation_handler_st { diff --git a/regex/my_regex.h b/regex/my_regex.h index 30896e29b91..1f96b8c461e 100644 --- a/regex/my_regex.h +++ b/regex/my_regex.h @@ -28,7 +28,7 @@ typedef struct { /* === regcomp.c === */ -typedef int (*my_regex_stack_check_t)(); +typedef int (*my_regex_stack_check_t)(int); extern int my_regcomp(my_regex_t *, const char *, int, CHARSET_INFO *charset); #define REG_BASIC 0000 #define REG_EXTENDED 0001 diff --git a/regex/regcomp.c b/regex/regcomp.c index 6e2d2511fc1..abc18174f56 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -227,7 +227,7 @@ int stop; /* character this ERE should end at */ while (MORE() && (c = PEEK()) != '|' && c != stop) { if (my_regex_enough_mem_in_stack && - my_regex_enough_mem_in_stack()) + my_regex_enough_mem_in_stack(0)) { SETERROR(REG_ESPACE); return; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 74972463db6..fb3832d438a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2881,14 +2881,25 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); #ifndef EMBEDDED_LIBRARY -static -int -check_enough_stack_size() +/** + This function is used to check for stack overrun for pathological + cases of regular expressions and 'like' expressions. + The call to current_thd is quite expensive, so we try to avoid it + for the normal cases. + The size of each stack frame for the wildcmp() routines is ~128 bytes, + so checking *every* recursive call is not necessary. + */ +extern "C" int +check_enough_stack_size(int recurse_level) { uchar stack_top; + if (recurse_level % 16 != 0) + return 0; - return check_stack_overrun(current_thd, STACK_MIN_SIZE, - &stack_top); + THD *my_thd= current_thd; + if (my_thd != NULL) + return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top); + return 0; } #endif @@ -3367,6 +3378,7 @@ static int init_common_variables() item_init(); #ifndef EMBEDDED_LIBRARY my_regex_init(&my_charset_latin1, check_enough_stack_size); + my_string_stack_guard= check_enough_stack_size; #else my_regex_init(&my_charset_latin1, NULL); #endif diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index ed674da6438..5ddec89ce1c 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -318,13 +318,16 @@ void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)), #define INC_PTR(cs,A,B) (A)++ -int my_wildcmp_bin(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) +static +int my_wildcmp_bin_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) { int result= -1; /* Not found, using wildcards */ - + + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (*wildstr != w_many && *wildstr != w_one) @@ -383,8 +386,8 @@ int my_wildcmp_bin(CHARSET_INFO *cs, if (str++ == str_end) return(-1); { - int tmp=my_wildcmp_bin(cs,str,str_end,wildstr,wildend,escape,w_one, - w_many); + int tmp=my_wildcmp_bin_impl(cs,str,str_end,wildstr,wildend,escape,w_one, + w_many, recurse_level + 1); if (tmp <= 0) return(tmp); } @@ -395,6 +398,16 @@ int my_wildcmp_bin(CHARSET_INFO *cs, return(str != str_end ? 1 : 0); } +int my_wildcmp_bin(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_bin_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + static size_t my_strnxfrm_bin(CHARSET_INFO *cs __attribute__((unused)), uchar *dest, size_t dstlen, diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index e0da94064d0..102680d7c45 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -251,13 +251,16 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t) #define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)] -int my_wildcmp_mb(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) +static +int my_wildcmp_mb_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) { int result= -1; /* Not found, using wildcards */ + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (*wildstr != w_many && *wildstr != w_one) @@ -346,8 +349,8 @@ int my_wildcmp_mb(CHARSET_INFO *cs, INC_PTR(cs,str, str_end); } { - int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one, - w_many); + int tmp=my_wildcmp_mb_impl(cs,str,str_end,wildstr,wildend,escape,w_one, + w_many, recurse_level + 1); if (tmp <= 0) return (tmp); } @@ -358,6 +361,16 @@ int my_wildcmp_mb(CHARSET_INFO *cs, return (str != str_end ? 1 : 0); } +int my_wildcmp_mb(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_mb_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + size_t my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)), const char *pos, const char *end) @@ -988,14 +1001,15 @@ pad_min_max: } -int -my_wildcmp_mb_bin(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) +static int my_wildcmp_mb_bin_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) { int result= -1; /* Not found, using wildcards */ + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (*wildstr != w_many && *wildstr != w_one) @@ -1082,7 +1096,9 @@ my_wildcmp_mb_bin(CHARSET_INFO *cs, INC_PTR(cs,str, str_end); } { - int tmp=my_wildcmp_mb_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many); + int tmp=my_wildcmp_mb_bin_impl(cs,str,str_end, + wildstr,wildend,escape, + w_one,w_many, recurse_level+1); if (tmp <= 0) return (tmp); } @@ -1093,6 +1109,17 @@ my_wildcmp_mb_bin(CHARSET_INFO *cs, return (str != str_end ? 1 : 0); } +int +my_wildcmp_mb_bin(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_mb_bin_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + /* Data was produced from EastAsianWidth.txt diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index d5f1c5363e5..09ea5c08ccb 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -841,13 +841,16 @@ cnv: #define INC_PTR(cs,A,B) (A)++ -int my_wildcmp_8bit(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) +static +int my_wildcmp_8bit_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) { int result= -1; /* Not found, using wildcards */ + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (*wildstr != w_many && *wildstr != w_one) @@ -907,8 +910,9 @@ int my_wildcmp_8bit(CHARSET_INFO *cs, str++; if (str++ == str_end) return(-1); { - int tmp=my_wildcmp_8bit(cs,str,str_end,wildstr,wildend,escape,w_one, - w_many); + int tmp=my_wildcmp_8bit_impl(cs,str,str_end, + wildstr,wildend,escape,w_one, + w_many, recurse_level+1); if (tmp <= 0) return(tmp); } @@ -919,6 +923,16 @@ int my_wildcmp_8bit(CHARSET_INFO *cs, return(str != str_end ? 1 : 0); } +int my_wildcmp_8bit(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_8bit_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + /* ** Calculate min_str and max_str that ranges a LIKE string. diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index a52f9e304e9..1dabdcae442 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -7394,10 +7394,10 @@ static int my_uca_charcmp(CHARSET_INFO *cs, my_wc_t wc1, my_wc_t wc2) */ static -int my_wildcmp_uca(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many) +int my_wildcmp_uca_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, int recurse_level) { int result= -1; /* Not found, using wildcards */ my_wc_t s_wc, w_wc; @@ -7405,7 +7405,9 @@ int my_wildcmp_uca(CHARSET_INFO *cs, int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *, const uchar *); mb_wc= cs->cset->mb_wc; - + + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (1) @@ -7512,8 +7514,8 @@ int my_wildcmp_uca(CHARSET_INFO *cs, if (str == str_end) return -1; - result= my_wildcmp_uca(cs, str, str_end, wildstr, wildend, - escape, w_one, w_many); + result= my_wildcmp_uca_impl(cs, str, str_end, wildstr, wildend, + escape, w_one, w_many, recurse_level+1); if (result <= 0) return result; @@ -7525,6 +7527,16 @@ int my_wildcmp_uca(CHARSET_INFO *cs, return (str != str_end ? 1 : 0); } +int my_wildcmp_uca(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_uca_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, 1); +} + /* Collation language is implemented according to diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 234898e9796..343884827e1 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1921,12 +1921,12 @@ my_tosort_unicode(MY_UNICASE_INFO **uni_plane, my_wc_t *wc) ** 1 if matched with wildcard */ -int -my_wildcmp_unicode(CHARSET_INFO *cs, - const char *str,const char *str_end, - const char *wildstr,const char *wildend, - int escape, int w_one, int w_many, - MY_UNICASE_INFO **weights) +static +int my_wildcmp_unicode_impl(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, + MY_UNICASE_INFO **weights, int recurse_level) { int result= -1; /* Not found, using wildcards */ my_wc_t s_wc, w_wc; @@ -1934,7 +1934,9 @@ my_wildcmp_unicode(CHARSET_INFO *cs, int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *, const uchar *); mb_wc= cs->cset->mb_wc; - + + if (my_string_stack_guard && my_string_stack_guard(recurse_level)) + return 1; while (wildstr != wildend) { while (1) @@ -2056,9 +2058,9 @@ my_wildcmp_unicode(CHARSET_INFO *cs, return -1; str+= scan; - result= my_wildcmp_unicode(cs, str, str_end, wildstr, wildend, - escape, w_one, w_many, - weights); + result= my_wildcmp_unicode_impl(cs, str, str_end, wildstr, wildend, + escape, w_one, w_many, + weights, recurse_level+1); if (result <= 0) return result; } @@ -2068,6 +2070,17 @@ my_wildcmp_unicode(CHARSET_INFO *cs, } +int +my_wildcmp_unicode(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, + MY_UNICASE_INFO **weights) +{ + return my_wildcmp_unicode_impl(cs, str, str_end, + wildstr, wildend, + escape, w_one, w_many, weights, 1); +} /* Store sorting weights using 2 bytes per character. diff --git a/strings/ctype.c b/strings/ctype.c index 91d28d16019..d3ec0f5dc34 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -40,6 +40,8 @@ */ +int (*my_string_stack_guard)(int)= NULL; + static char *mstr(char *str,const char *src,size_t l1,size_t l2) { l1= l1<l2 ? l1 : l2; |