summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-05-15 16:17:15 +0300
committerAleksey Midenkov <midenok@gmail.com>2020-05-15 16:17:15 +0300
commita4996f951d731322acc63033646d950ddbb0f60c (patch)
treea82b31076a630e302e26892e653597d47a749ad2
parent72789e4b2b0f631635297c6bc785c7364d60ca9f (diff)
downloadmariadb-git-a4996f951d731322acc63033646d950ddbb0f60c.tar.gz
MDEV-22563 Segfault on duplicate free of Item_func_in::array
Same array instance in two Item_func_in instances. First Item_func_in instance is freed on table close. Second one is freed on cleanup_after_query(). get_copy() depends on copy ctor for copying an item and hence does shallow copy for default copy ctor. Use build_clone() for deep copy of Item_func_in.
-rw-r--r--mysql-test/main/alter_table.result35
-rw-r--r--mysql-test/main/alter_table.test35
-rw-r--r--sql/field.cc2
-rw-r--r--sql/item.h5
4 files changed, 76 insertions, 1 deletions
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index 3d21b5c350d..8e8b4362ed8 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -2559,3 +2559,38 @@ drop view v1;
#
# End of 10.3 tests
#
+#
+# MDEV-22563 Segfault on duplicate free of Item_func_in::array
+#
+create or replace table person_principal (
+person_id bigint not null,
+insurant_id varchar(10) not null,
+principal_id bigint not null,
+principal_officer_id bigint not null,
+nursing_degree tinyint null,
+nursing_degree_valid_from date not null default cast(current_timestamp(6) as date),
+carma_user_id bigint not null,
+current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6),
+constraint pk_person_principal primary key (person_id asc),
+constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+Warnings:
+Warning 1280 Name 'pk_person_principal' ignored for PRIMARY key.
+create or replace table person_principal_hist (
+person_id bigint not null,
+insurant_id varchar(10) not null,
+principal_id bigint not null,
+principal_officer_id bigint not null,
+nursing_degree tinyint null,
+nursing_degree_valid_from date not null default cast(now() as date),
+carma_user_id bigint not null,
+orig_date_time datetime(6) not null,
+constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc),
+constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+Warnings:
+Warning 1280 Name 'pk_person_principal_hist' ignored for PRIMARY key.
+insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id)
+values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1);
+alter table person_principal add column if not exists date_mask tinyint null;
+update person_principal set date_mask = 0;
+alter table person_principal modify column date_mask tinyint not null;
+drop tables person_principal_hist, person_principal;
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index dc6983da38b..f090df56e5f 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -2076,3 +2076,38 @@ drop view v1;
--echo #
--echo # End of 10.3 tests
--echo #
+
+--echo #
+--echo # MDEV-22563 Segfault on duplicate free of Item_func_in::array
+--echo #
+create or replace table person_principal (
+ person_id bigint not null,
+ insurant_id varchar(10) not null,
+ principal_id bigint not null,
+ principal_officer_id bigint not null,
+ nursing_degree tinyint null,
+ nursing_degree_valid_from date not null default cast(current_timestamp(6) as date),
+ carma_user_id bigint not null,
+ current_date_time timestamp(6) not null default current_timestamp(6) on update current_timestamp(6),
+ constraint pk_person_principal primary key (person_id asc),
+ constraint ck_person_principal_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+
+create or replace table person_principal_hist (
+ person_id bigint not null,
+ insurant_id varchar(10) not null,
+ principal_id bigint not null,
+ principal_officer_id bigint not null,
+ nursing_degree tinyint null,
+ nursing_degree_valid_from date not null default cast(now() as date),
+ carma_user_id bigint not null,
+ orig_date_time datetime(6) not null,
+ constraint pk_person_principal_hist primary key (person_id asc, orig_date_time asc),
+ constraint ck_person_principal_hist_nursing_degree check (nursing_degree in (1,2,3,4,5)));
+
+insert into person_principal (person_id, insurant_id, principal_id, principal_officer_id, nursing_degree, nursing_degree_valid_from, carma_user_id)
+values (1, 'A123456789', 5, 1, 1, '2018-05-06', 1);
+alter table person_principal add column if not exists date_mask tinyint null;
+update person_principal set date_mask = 0;
+alter table person_principal modify column date_mask tinyint not null;
+drop tables person_principal_hist, person_principal;
+
diff --git a/sql/field.cc b/sql/field.cc
index 5d946ef5d0c..9d118a15748 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -11396,7 +11396,7 @@ Virtual_column_info* Virtual_column_info::clone(THD *thd)
return NULL;
if (expr)
{
- dst->expr= expr->get_copy(thd);
+ dst->expr= expr->build_clone(thd);
if (!dst->expr)
return NULL;
}
diff --git a/sql/item.h b/sql/item.h
index 54eaaaf8743..b83b997323d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1586,6 +1586,7 @@ public:
virtual bool is_order_clause_position() const { return false; }
/* cloning of constant items (0 if it is not const) */
virtual Item *clone_item(THD *thd) { return 0; }
+ /* deep copy item */
virtual Item* build_clone(THD *thd) { return get_copy(thd); }
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
@@ -2031,6 +2032,10 @@ public:
virtual bool check_index_dependence(void *arg) { return 0; }
/*============== End of Item processor list ======================*/
+ /*
+ Does not guarantee deep copy (depends on copy ctor).
+ See build_clone() for deep copy.
+ */
virtual Item *get_copy(THD *thd)=0;
bool cache_const_expr_analyzer(uchar **arg);