Skip to content

Commit 5c5a116

Browse files
committed
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.
1 parent 3c141e3 commit 5c5a116

File tree

4 files changed

+105
-21
lines changed

4 files changed

+105
-21
lines changed

mysql-test/r/derived_cond_pushdown.result

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9827,3 +9827,50 @@ WHERE (SELECT BIT_COUNT(t2.i1)
98279827
FROM (t2 JOIN t3)) IS NULL;
98289828
ERROR 21000: Subquery returns more than 1 row
98299829
DROP TABLE t1, t2, t3;
9830+
#
9831+
# MDEV-16614 signal 7 after calling stored procedure, that uses regexp
9832+
#
9833+
CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5))
9834+
BEGIN
9835+
SELECT a FROM
9836+
(SELECT "aa" a) t
9837+
JOIN (SELECT "aa" b) t1 on t.a=t1.b
9838+
WHERE t.a regexp m1 and t1.b regexp m2
9839+
GROUP BY a;
9840+
END$$
9841+
CALL p1('a','a');
9842+
a
9843+
aa
9844+
DROP PROCEDURE p1;
9845+
CREATE PROCEDURE p1(m1 varchar(5))
9846+
BEGIN
9847+
SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1;
9848+
END$$
9849+
CALL p1('a');
9850+
a
9851+
aa
9852+
DROP PROCEDURE p1;
9853+
SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1));
9854+
a
9855+
aa
9856+
CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT
9857+
BEGIN
9858+
RETURN 1;
9859+
END;$$
9860+
CREATE OR REPLACE PROCEDURE p1(m1 varchar(5))
9861+
BEGIN
9862+
SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1);
9863+
END$$
9864+
CALL p1('a');
9865+
a
9866+
aa
9867+
DROP PROCEDURE p1;
9868+
DROP FUNCTION f1;
9869+
CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT
9870+
BEGIN
9871+
RETURN 1;
9872+
END;$$
9873+
SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1));
9874+
a
9875+
aa
9876+
DROP FUNCTION f1;

mysql-test/t/derived_cond_pushdown.test

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,3 +1865,58 @@ WHERE (SELECT BIT_COUNT(t2.i1)
18651865
FROM (t2 JOIN t3)) IS NULL;
18661866

18671867
DROP TABLE t1, t2, t3;
1868+
1869+
--echo #
1870+
--echo # MDEV-16614 signal 7 after calling stored procedure, that uses regexp
1871+
--echo #
1872+
1873+
DELIMITER $$;
1874+
CREATE PROCEDURE p1(m1 varchar(5), m2 varchar(5))
1875+
BEGIN
1876+
SELECT a FROM
1877+
(SELECT "aa" a) t
1878+
JOIN (SELECT "aa" b) t1 on t.a=t1.b
1879+
WHERE t.a regexp m1 and t1.b regexp m2
1880+
GROUP BY a;
1881+
END$$
1882+
DELIMITER ;$$
1883+
CALL p1('a','a');
1884+
DROP PROCEDURE p1;
1885+
1886+
1887+
DELIMITER $$;
1888+
CREATE PROCEDURE p1(m1 varchar(5))
1889+
BEGIN
1890+
SELECT a FROM (SELECT "aa" a) t WHERE t.a regexp m1;
1891+
END$$
1892+
DELIMITER ;$$
1893+
CALL p1('a');
1894+
DROP PROCEDURE p1;
1895+
1896+
1897+
SELECT a FROM (SELECT "aa" a) t WHERE REGEXP_INSTR(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1));
1898+
1899+
1900+
DELIMITER $$;
1901+
CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT
1902+
BEGIN
1903+
RETURN 1;
1904+
END;$$
1905+
CREATE OR REPLACE PROCEDURE p1(m1 varchar(5))
1906+
BEGIN
1907+
SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, m1);
1908+
END$$
1909+
DELIMITER ;$$
1910+
CALL p1('a');
1911+
DROP PROCEDURE p1;
1912+
DROP FUNCTION f1;
1913+
1914+
1915+
DELIMITER $$;
1916+
CREATE OR REPLACE FUNCTION f1(a VARCHAR(10), b VARCHAR(10)) RETURNS INT
1917+
BEGIN
1918+
RETURN 1;
1919+
END;$$
1920+
DELIMITER ;$$
1921+
SELECT a FROM (SELECT "aa" a) t WHERE f1(t.a, (SELECT MAX('aa') FROM DUAL LIMIT 1));
1922+
DROP FUNCTION f1;

sql/item_cmpfunc.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,16 +2117,7 @@ class Item_func_regex :public Item_bool_func
21172117
bool fix_length_and_dec();
21182118
const char *func_name() const { return "regexp"; }
21192119
enum precedence precedence() const { return CMP_PRECEDENCE; }
2120-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
2121-
{ return get_item_copy<Item_func_regex>(thd, mem_root, this); }
2122-
Item *build_clone(THD *thd, MEM_ROOT *mem_root)
2123-
{
2124-
Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd, mem_root);
2125-
if (clone)
2126-
clone->re.reset();
2127-
return clone;
2128-
}
2129-
2120+
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
21302121
void print(String *str, enum_query_type query_type)
21312122
{
21322123
print_op(str, query_type);
@@ -2154,8 +2145,7 @@ class Item_func_regexp_instr :public Item_int_func
21542145
bool fix_fields(THD *thd, Item **ref);
21552146
bool fix_length_and_dec();
21562147
const char *func_name() const { return "regexp_instr"; }
2157-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
2158-
{ return get_item_copy<Item_func_regexp_instr>(thd, mem_root, this); }
2148+
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
21592149
};
21602150

21612151

sql/item_func.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,15 +2439,7 @@ class Item_func_sp :public Item_func
24392439
{
24402440
return TRUE;
24412441
}
2442-
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
2443-
{ return get_item_copy<Item_func_sp>(thd, mem_root, this); }
2444-
Item *build_clone(THD *thd, MEM_ROOT *mem_root)
2445-
{
2446-
Item_func_sp *clone= (Item_func_sp *) Item_func::build_clone(thd, mem_root);
2447-
if (clone)
2448-
clone->sp_result_field= NULL;
2449-
return clone;
2450-
}
2442+
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
24512443
bool eval_not_null_tables(void *opt_arg)
24522444
{
24532445
not_null_tables_cache= 0;

0 commit comments

Comments
 (0)