summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2012-04-06 15:08:09 -0700
committerIgor Babaev <igor@askmonty.org>2012-04-06 15:08:09 -0700
commit4ca9b8eb3af0fbfabd493bf72a0cc0e57f51d935 (patch)
tree151af947a63d7e9c9f906e5eebcf6979723fb4e2
parent2149a42928f961112e65944e4b0d7639416e6f50 (diff)
downloadmariadb-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.result20
-rw-r--r--mysql-test/t/view.test29
-rw-r--r--sql/item.cc15
-rw-r--r--sql/item.h2
-rw-r--r--sql/sql_base.cc25
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);