List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:February 4 2011 5:16am
Subject:bzr push into mysql-5.5 branch (Dmitry.Shulga:3299 to 3300) Bug#58026
View as plain text  
 3300 Dmitry Shulga	2011-02-04 [merge]
      Merge from mysql-5.1 for bug#58026.

    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
 3299 Georgi Kodinov	2011-02-02 [merge]
      merge

    modified:
      mysql-test/t/func_time.test
=== modified file 'mysql-test/r/not_embedded_server.result'
--- a/mysql-test/r/not_embedded_server.result	2011-01-07 12:08:05 +0000
+++ b/mysql-test/r/not_embedded_server.result	2011-02-04 04:59:55 +0000
@@ -3,6 +3,10 @@ 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, '(');
+#
 # WL#4284: Transactional DDL locking
 #
 # FLUSH PRIVILEGES should not implicitly unlock locked tables.

=== modified file 'mysql-test/t/not_embedded_server.test'
--- a/mysql-test/t/not_embedded_server.test	2011-01-07 12:08:05 +0000
+++ b/mysql-test/t/not_embedded_server.test	2011-02-04 04:59:55 +0000
@@ -14,6 +14,16 @@ call mtr.add_suppression("Can't open and
 
 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
 
 --echo #

=== 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-04 04:47:46 +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-23 20:16:29 +0000
+++ b/regex/regcomp.c	2011-02-04 04:59:55 +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&REG_EXTENDED) && (cflags&REG_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-04 04:47:46 +0000
@@ -4,10 +4,12 @@
 #include <m_ctype.h>
 #include <m_string.h>
 #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 18:13:28 +0000
+++ b/sql/mysqld.cc	2011-02-04 04:59:55 +0000
@@ -2879,6 +2879,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.
 
@@ -3340,7 +3353,11 @@ static int init_common_variables()
   if (item_create_init())
     return 1;
   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
     the first available character set. This is mostly for


Attachment: [text/bzr-bundle] bzr/dmitry.shulga@oracle.com-20110204045955-1ssnkooxtwhu6oa1.bundle
Thread
bzr push into mysql-5.5 branch (Dmitry.Shulga:3299 to 3300) Bug#58026Dmitry Shulga4 Feb