-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MDEV-29894: Calling a function from a different database in a slave s…
…ide trigger crashes When opening and locking tables, if triggers will be invoked in a separate database, thd->set_db() is invoked, thus freeeing the memory and headers which thd->db had previously pointed to. In row based replication, the event execution logic initializes thd->db to point to the database which the event targets, which is owned by the corresponding table share (introduced in d9898c9 for MDEV-7409). The problem then, is that during the table opening and locking process for a row event, memory which belongs to the table share would be freed, which is not valid. This patch replaces the thd->reset_db() calls to thd->set_db(), which copies-by-value, rather than by reference. Then when the memory is freed, our copy of memory is freed, rather than memory which belongs to a table share. Notes: 1. The call to change thd->db now happens on a higher-level, in Rows_log_event::do_apply_event() rather than ::do_exec_row(), in the call stack. This is because do_exec_row() is called within a loop, and each invocation would redundantly set and unset the db to the same value. 2. thd->set_db() is only used if triggers are to be invoked, as there is no vulnerability in the non-trigger case, and copying memory would be an unnecessary inefficiency. Reviewed By: ============ Andrei Elkin <andrei.elkin@mariadb.com>
- Loading branch information
Showing
4 changed files
with
204 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
include/master-slave.inc | ||
[connection master] | ||
connection slave; | ||
set global slave_run_triggers_for_rbr=1; | ||
connection master; | ||
CREATE TABLE t1 (a int); | ||
connection slave; | ||
connection slave; | ||
CREATE DATABASE db2; | ||
CREATE FUNCTION db2.get_value(a INT) RETURNS int(2) RETURN 0; | ||
# | ||
# Test Insert_rows_log_event | ||
connection slave; | ||
CREATE TRIGGER tr_ins BEFORE INSERT ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
connection master; | ||
INSERT INTO t1 VALUES (1); | ||
connection slave; | ||
connection slave; | ||
DROP TRIGGER tr_ins; | ||
# | ||
# Test Update_rows_log_event | ||
connection master; | ||
INSERT INTO t1 VALUES (5); | ||
connection slave; | ||
connection slave; | ||
CREATE TRIGGER tr_upd BEFORE UPDATE ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
connection master; | ||
UPDATE t1 SET a=a+1 WHERE a=5; | ||
connection slave; | ||
connection slave; | ||
DROP TRIGGER tr_upd; | ||
# | ||
# Test Delete_rows_log_event | ||
connection master; | ||
INSERT INTO t1 VALUES (7); | ||
connection slave; | ||
connection slave; | ||
CREATE TRIGGER tr_del BEFORE DELETE ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
connection master; | ||
DELETE FROM t1 WHERE a=7; | ||
connection slave; | ||
connection slave; | ||
DROP TRIGGER tr_del; | ||
# | ||
# Cleanup | ||
connection slave; | ||
SET GLOBAL slave_run_triggers_for_rbr=NO; | ||
DROP DATABASE db2; | ||
connection master; | ||
DROP TABLE t1; | ||
include/rpl_end.inc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# | ||
# This test ensures that a table share's database name is not freed when | ||
# using row based replication with triggers that open different databases | ||
# | ||
# | ||
# References: | ||
# MDEV-29894: Calling a function from a different database in a slave side | ||
# trigger crashes | ||
# | ||
--source include/master-slave.inc | ||
--source include/have_binlog_format_row.inc | ||
|
||
--connection slave | ||
--let $old_slave_run_triggers= `SELECT @@global.slave_run_triggers_for_rbr` | ||
set global slave_run_triggers_for_rbr=1; | ||
|
||
--connection master | ||
CREATE TABLE t1 (a int); | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
CREATE DATABASE db2; | ||
CREATE FUNCTION db2.get_value(a INT) RETURNS int(2) RETURN 0; | ||
|
||
--echo # | ||
--echo # Test Insert_rows_log_event | ||
|
||
--connection slave | ||
DELIMITER //; | ||
CREATE TRIGGER tr_ins BEFORE INSERT ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
DELIMITER ;// | ||
|
||
--connection master | ||
INSERT INTO t1 VALUES (1); | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
DROP TRIGGER tr_ins; | ||
|
||
|
||
--echo # | ||
--echo # Test Update_rows_log_event | ||
--connection master | ||
--let $row_val=5 | ||
--eval INSERT INTO t1 VALUES ($row_val) | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
DELIMITER //; | ||
CREATE TRIGGER tr_upd BEFORE UPDATE ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
DELIMITER ;// | ||
|
||
--connection master | ||
--eval UPDATE t1 SET a=a+1 WHERE a=$row_val | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
DROP TRIGGER tr_upd; | ||
|
||
|
||
--echo # | ||
--echo # Test Delete_rows_log_event | ||
--connection master | ||
--let $row_val=7 | ||
--eval INSERT INTO t1 VALUES ($row_val) | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
DELIMITER //; | ||
CREATE TRIGGER tr_del BEFORE DELETE ON t1 FOR EACH ROW BEGIN | ||
DECLARE a INT; | ||
SET a = db2.get_value(1); | ||
END// | ||
DELIMITER ;// | ||
|
||
--connection master | ||
--eval DELETE FROM t1 WHERE a=$row_val | ||
--sync_slave_with_master | ||
|
||
--connection slave | ||
DROP TRIGGER tr_del; | ||
|
||
|
||
--echo # | ||
--echo # Cleanup | ||
--connection slave | ||
--eval SET GLOBAL slave_run_triggers_for_rbr=$old_slave_run_triggers | ||
DROP DATABASE db2; | ||
--connection master | ||
DROP TABLE t1; | ||
|
||
--source include/rpl_end.inc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters