summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2018-07-26 12:04:21 +0400
committerAlexander Barkov <bar@mariadb.com>2018-07-26 13:05:22 +0400
commit5c5a116b47020e7ed79a59d4d2ced69a686ff090 (patch)
tree80ee4f67d2ab610f0ac52531fe25e0636c53a3ea
parent3c141e319ab29afdfe843553da385fe5d981906e (diff)
downloadmariadb-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.result47
-rw-r--r--mysql-test/t/derived_cond_pushdown.test55
-rw-r--r--sql/item_cmpfunc.h14
-rw-r--r--sql/item_func.h10
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;