Commit d284940f authored by Dmitry Shulga's avatar Dmitry Shulga

Merge from mysql-5.1 for bug#58026.

parents 5ba1fe97 6c777a62
...@@ -3,6 +3,10 @@ SHOW VARIABLES like 'slave_skip_errors'; ...@@ -3,6 +3,10 @@ SHOW VARIABLES like 'slave_skip_errors';
Variable_name Value Variable_name Value
slave_skip_errors OFF slave_skip_errors OFF
# #
# Bug#58026: massive recursion and crash in regular expression handling
#
SELECT '1' RLIKE RPAD('1', 10000, '(');
#
# WL#4284: Transactional DDL locking # WL#4284: Transactional DDL locking
# #
# FLUSH PRIVILEGES should not implicitly unlock locked tables. # FLUSH PRIVILEGES should not implicitly unlock locked tables.
......
...@@ -14,6 +14,16 @@ call mtr.add_suppression("Can't open and lock privilege tables: Table 'host' was ...@@ -14,6 +14,16 @@ call mtr.add_suppression("Can't open and lock privilege tables: Table 'host' was
SHOW VARIABLES like 'slave_skip_errors'; 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 # End of 5.1 tests
--echo # --echo #
......
...@@ -28,6 +28,7 @@ typedef struct { ...@@ -28,6 +28,7 @@ typedef struct {
/* === regcomp.c === */ /* === regcomp.c === */
typedef int (*my_regex_stack_check_t)();
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);
#define REG_BASIC 0000 #define REG_BASIC 0000
#define REG_EXTENDED 0001 #define REG_EXTENDED 0001
...@@ -76,7 +77,8 @@ extern void my_regfree(my_regex_t *); ...@@ -76,7 +77,8 @@ extern void my_regfree(my_regex_t *);
/* === reginit.c === */ /* === 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 */ extern void my_regex_end(void); /* If one wants a clean end */
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -31,6 +31,9 @@ struct parse { ...@@ -31,6 +31,9 @@ struct parse {
CHARSET_INFO *charset; /* for ctype things */ 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" #include "regcomp.ih"
static char nuls[10]; /* place to point scanner in event of error */ static char nuls[10]; /* place to point scanner in event of error */
...@@ -117,7 +120,7 @@ CHARSET_INFO *charset; ...@@ -117,7 +120,7 @@ CHARSET_INFO *charset;
# define GOODFLAGS(f) ((f)&~REG_DUMP) # define GOODFLAGS(f) ((f)&~REG_DUMP)
#endif #endif
my_regex_init(charset); /* Init cclass if neaded */ my_regex_init(charset, NULL); /* Init cclass if neaded */
preg->charset=charset; preg->charset=charset;
cflags = GOODFLAGS(cflags); cflags = GOODFLAGS(cflags);
if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC)) if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
...@@ -222,7 +225,15 @@ int stop; /* character this ERE should end at */ ...@@ -222,7 +225,15 @@ int stop; /* character this ERE should end at */
/* do a bunch of concatenated expressions */ /* do a bunch of concatenated expressions */
conc = HERE(); conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop) 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(REQUIRE(HERE() != conc, REG_EMPTY)) {}/* require nonempty */
if (!EAT('|')) if (!EAT('|'))
......
...@@ -4,10 +4,12 @@ ...@@ -4,10 +4,12 @@
#include <m_ctype.h> #include <m_ctype.h>
#include <m_string.h> #include <m_string.h>
#include "cclass.h" #include "cclass.h"
#include "my_regex.h"
static my_bool regex_inited=0; 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]; char buff[CCLASS_LAST][256];
int count[CCLASS_LAST]; int count[CCLASS_LAST];
...@@ -16,6 +18,7 @@ void my_regex_init(CHARSET_INFO *cs) ...@@ -16,6 +18,7 @@ void my_regex_init(CHARSET_INFO *cs)
if (!regex_inited) if (!regex_inited)
{ {
regex_inited=1; regex_inited=1;
my_regex_enough_mem_in_stack= func;
bzero((uchar*) &count,sizeof(count)); bzero((uchar*) &count,sizeof(count));
for (i=1 ; i<= 255; i++) for (i=1 ; i<= 255; i++)
...@@ -74,6 +77,7 @@ void my_regex_end() ...@@ -74,6 +77,7 @@ void my_regex_end()
int i; int i;
for (i=0; i < CCLASS_LAST ; i++) for (i=0; i < CCLASS_LAST ; i++)
free((char*) cclasses[i].chars); free((char*) cclasses[i].chars);
my_regex_enough_mem_in_stack= NULL;
regex_inited=0; regex_inited=0;
} }
} }
......
...@@ -2879,6 +2879,19 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); ...@@ -2879,6 +2879,19 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]);
#endif #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. Initialize one of the global date/time format variables.
...@@ -3340,7 +3353,11 @@ static int init_common_variables() ...@@ -3340,7 +3353,11 @@ static int init_common_variables()
if (item_create_init()) if (item_create_init())
return 1; return 1;
item_init(); item_init();
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
/* /*
Process a comma-separated character set list and choose Process a comma-separated character set list and choose
the first available character set. This is mostly for the first available character set. This is mostly for
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment