diff options
author | Igor Babaev <igor@askmonty.org> | 2012-04-06 15:08:09 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-04-06 15:08:09 -0700 |
commit | 4ca9b8eb3af0fbfabd493bf72a0cc0e57f51d935 (patch) | |
tree | 151af947a63d7e9c9f906e5eebcf6979723fb4e2 | |
parent | 2149a42928f961112e65944e4b0d7639416e6f50 (diff) | |
download | mariadb-git-4ca9b8eb3af0fbfabd493bf72a0cc0e57f51d935.tar.gz |
Fixed bug #915222.
This bug happened because the function find_field_in_view formed
autogenerated names of view columns without a possibility to roll
them back. In some situation it could cause memory misuses reported
by valgrind or even crashes.
-rw-r--r-- | mysql-test/r/view.result | 20 | ||||
-rw-r--r-- | mysql-test/t/view.test | 29 | ||||
-rw-r--r-- | sql/item.cc | 15 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 25 |
5 files changed, 82 insertions, 9 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 15ef0c088b1..b4e6f194058 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4433,6 +4433,26 @@ NULL NULL 1 0 NULL NULL 1 0 DROP VIEW v2; DROP TABLE t1, t2, t3; +# +# BUG#915222: Valgrind complains or crashes with INSERT SELECT +# within a trigger that uses a view +# +CREATE TABLE t1 (a char(1)); +CREATE TABLE t2 (d int, e char(1)); +INSERT INTO t2 VALUES (13,'z'); +CREATE TRIGGER tr AFTER UPDATE ON t2 +FOR EACH ROW +REPLACE INTO t3 +SELECT f, a AS alias FROM t3, v; +CREATE TABLE t3 (f int, g char(8)); +CREATE VIEW v AS SELECT a, e FROM t2, t1; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +DROP TRIGGER tr; +DROP VIEW v; +DROP TABLE t1,t2,t3; # ----------------------------------------------------------------- # -- End of 5.3 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 2a9bfd89f3b..4820e0ac173 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4365,6 +4365,35 @@ SELECT * FROM t1 RIGHT JOIN v2 ON ( v2.a = t1.a ) WHERE v2.b IN ( SELECT b FROM DROP VIEW v2; DROP TABLE t1, t2, t3; +--echo # +--echo # BUG#915222: Valgrind complains or crashes with INSERT SELECT +--echo # within a trigger that uses a view +--echo # + +CREATE TABLE t1 (a char(1)); + +CREATE TABLE t2 (d int, e char(1)); + +INSERT INTO t2 VALUES (13,'z'); + +CREATE TRIGGER tr AFTER UPDATE ON t2 + FOR EACH ROW + REPLACE INTO t3 + SELECT f, a AS alias FROM t3, v; + +CREATE TABLE t3 (f int, g char(8)); + +CREATE VIEW v AS SELECT a, e FROM t2, t1; + +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; + +DROP TRIGGER tr; +DROP VIEW v; +DROP TABLE t1,t2,t3; + --echo # ----------------------------------------------------------------- --echo # -- End of 5.3 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/item.cc b/sql/item.cc index 8169e1d35b4..50cee7e3862 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -951,6 +951,21 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) } +void Item::set_name_for_rollback(THD *thd, const char *str, uint length, + CHARSET_INFO *cs) +{ + char *old_name, *new_name; + old_name= name; + set_name(str, length, cs); + new_name= name; + if (old_name != new_name) + { + name= old_name; + thd->change_item_tree((Item **) &name, (Item *) new_name); + } +} + + /** @details This function is called when: diff --git a/sql/item.h b/sql/item.h index aeae1b1faf2..69aa28dfadd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -620,6 +620,8 @@ public: #endif } /*lint -e1509 */ void set_name(const char *str, uint length, CHARSET_INFO *cs); + void set_name_for_rollback(THD *thd, const char *str, uint length, + CHARSET_INFO *cs); void rename(char *new_name); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 03d8a925fc2..0f496eca9bb 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5988,15 +5988,22 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, */ if (*ref && !(*ref)->is_autogenerated_name) { - if (register_tree_change && - thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute()) - arena= thd->activate_stmt_arena_if_needed(&backup); - item->set_name((*ref)->name, (*ref)->name_length, - system_charset_info); - item->real_item()->set_name((*ref)->name, (*ref)->name_length, - system_charset_info); - if (arena) - thd->restore_active_arena(arena, &backup); + if (register_tree_change) + { + item->set_name_for_rollback(thd, (*ref)->name, + (*ref)->name_length, + system_charset_info); + item->real_item()->set_name_for_rollback(thd, (*ref)->name, + (*ref)->name_length, + system_charset_info); + } + else + { + item->set_name((*ref)->name, (*ref)->name_length, + system_charset_info); + item->real_item()->set_name((*ref)->name, (*ref)->name_length, + system_charset_info); + } } if (register_tree_change) thd->change_item_tree(ref, item); |