Commit 788be2ae authored by Ramil Kalimullin's avatar Ramil Kalimullin

Fix for bug #39021: SELECT REGEXP BINARY NULL never returns

Problem: SELECT ... REGEXP BINARY NULL may lead to server crash/hang.

Fix: properly handle NULL regular expressions.


mysql-test/r/func_regexp.result:
  Fix for bug #39021: SELECT REGEXP BINARY NULL never returns
    - test result.
mysql-test/t/func_regexp.test:
  Fix for bug #39021: SELECT REGEXP BINARY NULL never returns
    - test case.
sql/item_cmpfunc.cc:
  Fix for bug #39021: SELECT REGEXP BINARY NULL never returns
    - checking regular expressions' null_value
  we tested it without a val_xxx() call before, which is wrong.
  Now Item_func_regex::regcomp() returns -1 in the case
  and allows to handle NULL expessions properly.
sql/item_cmpfunc.h:
  Fix for bug #39021: SELECT REGEXP BINARY NULL never returns
    - checking regular expressions' null_value
  we tested it without a val_xxx() call before, which is wrong.
  Now Item_func_regex::regcomp() returns -1 in the case
  and allows to handle NULL expessions properly.
parent bcbff0b9
...@@ -114,4 +114,16 @@ End of 4.1 tests ...@@ -114,4 +114,16 @@ End of 4.1 tests
SELECT 1 REGEXP NULL; SELECT 1 REGEXP NULL;
1 REGEXP NULL 1 REGEXP NULL
NULL NULL
SELECT '' REGEXP BINARY NULL;
'' REGEXP BINARY NULL
NULL
SELECT NULL REGEXP BINARY NULL;
NULL REGEXP BINARY NULL
NULL
SELECT 'A' REGEXP BINARY NULL;
'A' REGEXP BINARY NULL
NULL
SELECT "ABC" REGEXP BINARY NULL;
"ABC" REGEXP BINARY NULL
NULL
End of 5.0 tests End of 5.0 tests
...@@ -64,4 +64,14 @@ drop table t1; ...@@ -64,4 +64,14 @@ drop table t1;
SELECT 1 REGEXP NULL; SELECT 1 REGEXP NULL;
#
# Bug #39021: SELECT REGEXP BINARY NULL never returns
#
SELECT '' REGEXP BINARY NULL;
SELECT NULL REGEXP BINARY NULL;
SELECT 'A' REGEXP BINARY NULL;
SELECT "ABC" REGEXP BINARY NULL;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -4341,8 +4341,20 @@ void Item_func_like::cleanup() ...@@ -4341,8 +4341,20 @@ void Item_func_like::cleanup()
#ifdef USE_REGEX #ifdef USE_REGEX
bool /**
Item_func_regex::regcomp(bool send_error) @brief Compile regular expression.
@param[in] send_error send error message if any.
@details Make necessary character set conversion then
compile regular expression passed in the args[1].
@retval 0 success.
@retval 1 error occurred.
@retval -1 given null regular expression.
*/
int Item_func_regex::regcomp(bool send_error)
{ {
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),&my_charset_bin); String tmp(buff,sizeof(buff),&my_charset_bin);
...@@ -4350,12 +4362,12 @@ Item_func_regex::regcomp(bool send_error) ...@@ -4350,12 +4362,12 @@ Item_func_regex::regcomp(bool send_error)
int error; int error;
if (args[1]->null_value) if (args[1]->null_value)
return TRUE; return -1;
if (regex_compiled) if (regex_compiled)
{ {
if (!stringcmp(res, &prev_regexp)) if (!stringcmp(res, &prev_regexp))
return FALSE; return 0;
prev_regexp.copy(*res); prev_regexp.copy(*res);
my_regfree(&preg); my_regfree(&preg);
regex_compiled= 0; regex_compiled= 0;
...@@ -4367,7 +4379,7 @@ Item_func_regex::regcomp(bool send_error) ...@@ -4367,7 +4379,7 @@ Item_func_regex::regcomp(bool send_error)
uint dummy_errors; uint dummy_errors;
if (conv.copy(res->ptr(), res->length(), res->charset(), if (conv.copy(res->ptr(), res->length(), res->charset(),
regex_lib_charset, &dummy_errors)) regex_lib_charset, &dummy_errors))
return TRUE; return 1;
res= &conv; res= &conv;
} }
...@@ -4379,10 +4391,10 @@ Item_func_regex::regcomp(bool send_error) ...@@ -4379,10 +4391,10 @@ Item_func_regex::regcomp(bool send_error)
(void) my_regerror(error, &preg, buff, sizeof(buff)); (void) my_regerror(error, &preg, buff, sizeof(buff));
my_error(ER_REGEXP_ERROR, MYF(0), buff); my_error(ER_REGEXP_ERROR, MYF(0), buff);
} }
return TRUE; return 1;
} }
regex_compiled= 1; regex_compiled= 1;
return FALSE; return 0;
} }
...@@ -4420,13 +4432,14 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) ...@@ -4420,13 +4432,14 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
const_item_cache=args[0]->const_item() && args[1]->const_item(); const_item_cache=args[0]->const_item() && args[1]->const_item();
if (!regex_compiled && args[1]->const_item()) if (!regex_compiled && args[1]->const_item())
{ {
if (args[1]->null_value) int comp_res= regcomp(TRUE);
if (comp_res == -1)
{ // Will always return NULL { // Will always return NULL
maybe_null=1; maybe_null=1;
fixed= 1; fixed= 1;
return FALSE; return FALSE;
} }
if (regcomp(TRUE)) else if (comp_res)
return TRUE; return TRUE;
regex_is_const= 1; regex_is_const= 1;
maybe_null= args[0]->maybe_null; maybe_null= args[0]->maybe_null;
......
...@@ -1323,7 +1323,7 @@ class Item_func_regex :public Item_bool_func ...@@ -1323,7 +1323,7 @@ class Item_func_regex :public Item_bool_func
CHARSET_INFO *regex_lib_charset; CHARSET_INFO *regex_lib_charset;
int regex_lib_flags; int regex_lib_flags;
String conv; String conv;
bool regcomp(bool send_error); int regcomp(bool send_error);
public: public:
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b), Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
regex_compiled(0),regex_is_const(0) {} regex_compiled(0),regex_is_const(0) {}
......
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