diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-07-26 12:04:21 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-07-26 13:05:22 +0400 |
commit | 5c5a116b47020e7ed79a59d4d2ced69a686ff090 (patch) | |
tree | 80ee4f67d2ab610f0ac52531fe25e0636c53a3ea | |
parent | 3c141e319ab29afdfe843553da385fe5d981906e (diff) | |
download | mariadb-git-5c5a116b47020e7ed79a59d4d2ced69a686ff090.tar.gz |
MDEV-16614 signal 7 after calling stored procedure, that uses regexp
The problem happened in the derived condition pushdown code:
- When Item_func_regex::build_clone() was called, it created a copy of
the original Item_func_regex, and this copy got registered in free_list.
Class specific additional dynamic members (such as "re") made
a shallow copy, rather than a deep copy, in the cloned Item_func_regex.
As a result, the Regexp_processor_pcre::m_pcre of the cloned Item_func_regex
and of the original Item_func_regex pointed to the same compiled regular
expression.
- On cleanup_items(), both original and cloned copies of Item_func_regex
called re.cleanup(), which called pcre_free(m_pcre). So the same compiled
regular expression was freed two times, which was noticed by ASAN.
The same problem was repeatable for Item_func_regexp_instr.
A similar problem happened for Item_func_sp, for the sp_result_field member.
Both original and cloned copies of Item_func_sp pointed the same Field instance
and both deleted it on cleanup().
A possible solution would be to fix build_clone() to create deep
(instead of shallow) copies for the dynamic members of the affected classes
(Item_func_regex, Item_func_regexp_instr, Item_func sp).
However, this would be too complex.
As agreed with Galina and Igor, this patch disallows using using these
affected classes in derived condition pushdown by overriding get_clone()
to return NULL.
-rw-r--r-- | mysql-test/r/derived_cond_pushdown.result | 47 | ||||
-rw-r--r-- | mysql-test/t/derived_cond_pushdown.test | 55 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 14 | ||||
-rw-r--r-- | sql/item_func.h | 10 |
4 files changed, 105 insertions, 21 deletions
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result index 3adfe0b9b01..22b81ef48a5 100644 --- a/mysql-test/r/derived_cond_pushdown.result +++ b/mysql-test/r/derived_cond_pushdown.result @@ -9827,3 +9827,50 @@ WHERE (SELECT BIT_COUNT(t2.i1) FROM (t2 JOIN t3)) IS NULL; ERROR 21000: Subquery returns more than 1 row DROP TABLE t1, t2, t3; +# +# MDEV-16614 signal 7 after calling stored procedure, that uses regexp +# +CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5)) +BEGIN +SELECT a FROM +(SELECT "aa" a) t +JOIN (SELECT "aa" b) t1 on t.a=t1.b +WHERE t.a regexp m1 and t1.b regexp m2 +GROUP BY a; +END$$ +CALL p1('a','a'); +a +aa +DROP PROCEDURE p1; +CREATE PROCEDURE p1(m1 varchar(5)) +BEGIN +SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1; +END$$ +CALL p1('a'); +a +aa +DROP PROCEDURE p1; +SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +a +aa +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN +RETURN 1; +END;$$ +CREATE OR REPLACE PROCEDURE p1(m1 varchar(5)) +BEGIN +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1); +END$$ +CALL p1('a'); +a +aa +DROP PROCEDURE p1; +DROP FUNCTION f1; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN +RETURN 1; +END;$$ +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +a +aa +DROP FUNCTION f1; diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test index 872acb55589..d9d767f53ed 100644 --- a/mysql-test/t/derived_cond_pushdown.test +++ b/mysql-test/t/derived_cond_pushdown.test @@ -1865,3 +1865,58 @@ WHERE (SELECT BIT_COUNT(t2.i1) FROM (t2 JOIN t3)) IS NULL; DROP TABLE t1, t2, t3; + +--echo # +--echo # MDEV-16614 signal 7 after calling stored procedure, that uses regexp +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5)) +BEGIN +SELECT a FROM + (SELECT "aa" a) t + JOIN (SELECT "aa" b) t1 on t.a=t1.b +WHERE t.a regexp m1 and t1.b regexp m2 +GROUP BY a; +END$$ +DELIMITER ;$$ +CALL p1('a','a'); +DROP PROCEDURE p1; + + +DELIMITER $$; +CREATE PROCEDURE p1(m1 varchar(5)) +BEGIN + SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1; +END$$ +DELIMITER ;$$ +CALL p1('a'); +DROP PROCEDURE p1; + + +SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); + + +DELIMITER $$; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN + RETURN 1; +END;$$ +CREATE OR REPLACE PROCEDURE p1(m1 varchar(5)) +BEGIN + SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1); +END$$ +DELIMITER ;$$ +CALL p1('a'); +DROP PROCEDURE p1; +DROP FUNCTION f1; + + +DELIMITER $$; +CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT +BEGIN + RETURN 1; +END;$$ +DELIMITER ;$$ +SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1)); +DROP FUNCTION f1; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a59432058eb..41a51ee8d12 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2117,16 +2117,7 @@ public: bool fix_length_and_dec(); const char *func_name() const { return "regexp"; } enum precedence precedence() const { return CMP_PRECEDENCE; } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_func_regex>(thd, mem_root, this); } - Item *build_clone(THD *thd, MEM_ROOT *mem_root) - { - Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd, mem_root); - if (clone) - clone->re.reset(); - return clone; - } - + Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } void print(String *str, enum_query_type query_type) { print_op(str, query_type); @@ -2154,8 +2145,7 @@ public: bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); const char *func_name() const { return "regexp_instr"; } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_func_regexp_instr>(thd, mem_root, this); } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } }; diff --git a/sql/item_func.h b/sql/item_func.h index 0969cf2e3f0..4652f2c2d31 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -2439,15 +2439,7 @@ public: { return TRUE; } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_func_sp>(thd, mem_root, this); } - Item *build_clone(THD *thd, MEM_ROOT *mem_root) - { - Item_func_sp *clone= (Item_func_sp *) Item_func::build_clone(thd, mem_root); - if (clone) - clone->sp_result_field= NULL; - return clone; - } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } bool eval_not_null_tables(void *opt_arg) { not_null_tables_cache= 0; |