summaryrefslogtreecommitdiff
path: root/sql/ha_partition.cc
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2018-10-18 22:48:28 +0400
committerSergey Vojtovich <svoj@mariadb.org>2018-10-19 19:09:48 +0400
commit4ac85d6fd7c43fd0c45c98c0b55810591bd7594b (patch)
tree1bd4b56f47426df7f63e9882cd9cf2de87d96c2c /sql/ha_partition.cc
parent8e716138cef2d9be603cdf71701d82bcb72dfd69 (diff)
downloadmariadb-git-4ac85d6fd7c43fd0c45c98c0b55810591bd7594b.tar.gz
MDEV-14815 - Server crash or AddressSanitizer errors or valgrind warnings
in thr_lock / has_old_lock upon FLUSH TABLES Explicit partition access of partitioned MEMORY table under LOCK TABLES may cause subsequent statements to crash the server, deadlock, trigger valgrind warnings or ASAN errors. Freed memory was being used due to incorrect cleanup. At least MyISAM and InnoDB don't seem to be affected, since their THR_LOCK structures don't survive FLUSH TABLES. MEMORY keeps table shared data (including THR_LOCK) even if there're no open instances. There's partition_info::lock_partitions bitmap, which holds bits of partitions allowed to be accessed after pruning. This bitmap is updated for each individual statement. This bitmap was abused in ha_partition::store_lock() such that when we need to unlock a table, locked by LOCK TABLES, only locks for partitions that were accessed by previous statement were released. Eventually FLUSH TABLES frees THR_LOCK_DATA objects, which are still linked into THR_LOCK lists. When such THR_LOCK gets reused we end up with freed memory access. Fixed by using ha_partition::m_locked_partitions bitmap similarly to ha_partition::external_lock().
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r--sql/ha_partition.cc9
1 files changed, 7 insertions, 2 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0488ebfb60f..02de92aa17f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -3907,9 +3907,14 @@ THR_LOCK_DATA **ha_partition::store_lock(THD *thd,
}
else
{
- for (i= bitmap_get_first_set(&(m_part_info->lock_partitions));
+ MY_BITMAP *used_partitions= lock_type == TL_UNLOCK ||
+ lock_type == TL_IGNORE ?
+ &m_locked_partitions :
+ &m_part_info->lock_partitions;
+
+ for (i= bitmap_get_first_set(used_partitions);
i < m_tot_parts;
- i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
+ i= bitmap_get_next_set(used_partitions, i))
{
DBUG_PRINT("info", ("store lock %d iteration", i));
to= m_file[i]->store_lock(thd, to, lock_type);