• Brandon Nesterenko's avatar
    MDEV-29894: Calling a function from a different database in a slave side trigger crashes · c2d44ecb
    Brandon Nesterenko authored
    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 d9898c9a 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>
    c2d44ecb
rpl_row_trigger_multi_db.test 2 KB