Bug #58026 massive recursion and crash in regular expression handling
Submitted: 6 Nov 2010 8:06 Modified: 2 Mar 2011 15:50
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Data Types Severity:S1 (Critical)
Version:5.0.92, 5.1.53, 5.5.8 OS:Any
Assigned to: Dmitry Shulga CPU Architecture:Any
Tags: recursion, RLIKE, stack

[6 Nov 2010 8:06] Shane Bester
Description:
5.1.53:

<cut> few thousands recursive call frames </cut>

#3437 in p_ere_exp at regcomp.c:280
#3438 in p_ere at regcomp.c:225
#3439 in my_regcomp at regcomp.c:177
#3440 in Item_func_regex::regcomp at item_cmpfunc.cc:4836
#3441 in Item_func_regex::fix_fields at item_cmpfunc.cc:4885
#3442 in setup_fields at sql_base.cc:7549
#3443 in JOIN::prepare at sql_select.cc:514
#3444 in mysql_select at sql_select.cc:2523
#3445 in handle_select at sql_select.cc:269
#3446 in execute_sqlcom_select at sql_parse.cc:5144
#3447 in mysql_execute_command at sql_parse.cc:2293
#3448 in mysql_parse at sql_parse.cc:6068
#3449 in dispatch_command at sql_parse.cc:1261
#3450 in do_command at sql_parse.cc:889
#3451 in handle_one_connection at sql_connect.cc:1136
#3452 in start_thread at pthread_create.c:301

How to repeat:
select '1' rlike rpad('1',10000,'(');
[6 Nov 2010 8:09] MySQL Verification Team
we need some reasonable limits implemented here... or check thread_stack now and then.
[6 Nov 2010 8:12] Valeriy Kravchuk
This is what I've got on Mac OS X:

macbook-pro:5.1 openxs$ bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.53-debug Source distribution

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL v2 license

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select '1' rlike rpad('1',10000,'(');
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql> 
bin/mysqld_safe: line 137: 12147 Illegal instruction     nohup /Users/openxs/dbs/5.1/libexec/mysqld --basedir=/Users/openxs/dbs/5.1 --datadir=/Users/openxs/dbs/5.1/var --user=mysql --log-error=/Users/openxs/dbs/5.1/var/macbook-pro.err --pid-file=/Users/openxs/dbs/5.1/var/macbook-pro.pid < /dev/null >> /Users/openxs/dbs/5.1/var/macbook-pro.err 2>&1 >> /Users/openxs/dbs/5.1/var/macbook-pro.err 2>&1 >> /Users/openxs/dbs/5.1/var/macbook-pro.err 2>&1
101106 10:09:07 mysqld_safe mysqld restarted
...
[24 Nov 2010 5:18] MySQL Verification Team
workaround for smaller number of recursions is to increase thread_stack to a higher number.
[24 Nov 2010 9:08] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/124816

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.
[18 Jan 2011 7:18] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/129024

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.
[19 Jan 2011 17:11] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/129227

3514 Dmitry Shulga	2011-01-19
      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.
     @ mysql-test/t/not_embedded_server.test
        Added test for bug#58026
     @ regex/my_regex.h
        added pointer to function as last argument of my_regex_init() for check
        enough memory in stack.
     @ regex/regcomp.c
        p_ere() was modified: added call to function for check enough memory
        in stack. Function for check available stack space specified by
        global variable my_regex_enough_mem_in_stack. This variable set to
        NULL for embedded mysqld and to a pointer to function
        check_enough_stack_size otherwise.
     @ regex/reginit.c
        my_regex_init was modified: pass a pointer to a function for check
        enough memory in stack space. Reset this pointer to NULL in my_regex_end.
     @ sql/mysqld.cc
        Added function check_enough_stack_size() for check enough memory in stack.
        Passed this function as second argument to my_regex_init. For embedded 
        mysqld passed NULL as second argument.
[27 Jan 2011 14:23] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/129781

3514 Dmitry Shulga	2011-01-27
      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.
     @ mysql-test/t/not_embedded_server.test
        Added test for bug#58026
     @ regex/my_regex.h
        added pointer to function as last argument of my_regex_init() for check
        enough memory in stack.
     @ regex/regcomp.c
        p_ere() was modified: added call to function for check enough memory
        in stack. Function for check available stack space specified by
        global variable my_regex_enough_mem_in_stack. This variable set to
        NULL for embedded mysqld and to a pointer to function
        check_enough_stack_size otherwise.
     @ regex/reginit.c
        my_regex_init was modified: pass a pointer to a function for check
        enough memory in stack space. Reset this pointer to NULL in my_regex_end.
     @ sql/mysqld.cc
        Added function check_enough_stack_size() for check enough memory in stack.
        Passed this function as second argument to my_regex_init. For embedded 
        mysqld passed NULL as second argument.
[3 Feb 2011 9:28] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/130304

3575 Dmitry Shulga	2011-02-03
      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.
     @ mysql-test/t/not_embedded_server.test
        Added test for bug#58026.
     @ regex/my_regex.h
        added pointer to function as last argument of my_regex_init() for check
        enough memory in stack.
     @ regex/regcomp.c
        p_ere() was modified: added call to function for check enough memory
        in stack. Function for check available stack space specified by
        global variable my_regex_enough_mem_in_stack. This variable set to
        NULL for embedded mysqld and to a pointer to function
        check_enough_stack_size otherwise.
     @ regex/reginit.c
        my_regex_init was modified: pass a pointer to a function for check
        enough memory in stack space. Reset this pointer to NULL in my_regex_end.
     @ sql/mysqld.cc
        Added function check_enough_stack_size() for check enough memory in stack.
        Passed this function as second argument to my_regex_init. For embedded 
        mysqld passed NULL as second argument.
[3 Feb 2011 10:29] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/130309

3300 Dmitry Shulga	2011-02-03 [merge]
      Merge from mysql-5.1 for bug#58026.
[4 Feb 2011 4:49] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/130351

3575 Dmitry Shulga	2011-02-04
      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.
     @ mysql-test/t/not_embedded_server.test
        Added test for bug#58026.
     @ regex/my_regex.h
        added pointer to function as last argument of my_regex_init() for check
        enough memory in stack.
     @ regex/regcomp.c
        p_ere() was modified: added call to function for check enough memory
        in stack. Function for check available stack space specified by
        global variable my_regex_enough_mem_in_stack. This variable set to
        NULL for embedded mysqld and to a pointer to function
        check_enough_stack_size otherwise.
     @ regex/reginit.c
        my_regex_init was modified: pass a pointer to a function for check
        enough memory in stack space. Reset this pointer to NULL in my_regex_end.
     @ sql/mysqld.cc
        Added function check_enough_stack_size() for check enough memory in stack.
        Passed this function as second argument to my_regex_init. For embedded 
        mysqld passed NULL as second argument.
[4 Feb 2011 5:13] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/130352

3598 Dmitry Shulga	2011-02-04 [merge]
      Megre changes from mysql-5.5 for bug#58026.
[4 Feb 2011 5:16] Bugs System
Pushed into mysql-5.1 5.1.56 (revid:dmitry.shulga@oracle.com-20110204044746-sakc2ctbjb9n7tqv) (version source revid:dmitry.shulga@oracle.com-20110204044746-sakc2ctbjb9n7tqv) (merge vers: 5.1.56) (pib:24)
[4 Feb 2011 5:16] Bugs System
Pushed into mysql-trunk 5.6.2 (revid:dmitry.shulga@oracle.com-20110204051109-7enmofxh2vnpdmox) (version source revid:dmitry.shulga@oracle.com-20110204051109-7enmofxh2vnpdmox) (merge vers: 5.6.2) (pib:24)
[4 Feb 2011 5:16] Bugs System
Pushed into mysql-5.5 5.5.10 (revid:dmitry.shulga@oracle.com-20110204045955-1ssnkooxtwhu6oa1) (version source revid:dmitry.shulga@oracle.com-20110204045955-1ssnkooxtwhu6oa1) (merge vers: 5.5.10) (pib:24)
[4 Feb 2011 5:17] Dmitry Shulga
Pushed to mysql-5.1, mysql-5.5 and mysql-trunk.
[2 Mar 2011 15:50] Paul DuBois
Noted in 5.1.56, 5.5.10, 5.6.2 changelogs.

Parsing nested regular expressions could lead to recursion resulting
in a stack overflow crash. 

CHANGESET - http://lists.mysql.com/commits/130352
[30 Jul 2011 12:16] MySQL Verification Team
why is this bug not fixed in the embedded server also?
[30 Jul 2011 12:28] Davi Arnaut
Because it's embedded into a larger stack, how do you (portably) find where the stack started?