From b5fe7ab8412d63b784ab318f11506954639f1d3c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 13 Feb 2022 19:09:03 +0100 Subject: [PATCH 1/5] MDEV-27826 Mariabackup is linked against libsql_builtins.so dynamically build sql_builtins always statically --- sql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 43555a0095d..e42f1a164df 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -273,7 +273,7 @@ IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS) SET_TARGET_PROPERTIES(mysqld_import_lib PROPERTIES IMPORTED_LOCATION ${MYSQLD_LIB}) ENDIF() -ADD_LIBRARY( sql_builtins ${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc) +ADD_LIBRARY(sql_builtins STATIC ${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc) TARGET_LINK_LIBRARIES(sql_builtins ${MYSQLD_STATIC_PLUGIN_LIBS}) MYSQL_ADD_EXECUTABLE(mysqld ${MYSQLD_SOURCE} DESTINATION ${INSTALL_SBINDIR} COMPONENT Server) From 0b849a441afaa5f4ce1ad1af877363d7b5c4a1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Feb 2022 07:18:00 +0200 Subject: [PATCH 2/5] WSREP: Fix GCC 12.0.1 -Wuninitialized GCC 12 complains if a reference to an uninitialized object is being passed to a constructor. The mysql_mutex_t, mysql_cond_t would be initialized in the constructor body, which is executed after the initializer list. There is no problem passing a pointer instead of a reference. The wrapper classes do not dereference the pointers in the constructor or destructor, so there does not appear to be any correctness issue. --- sql/sql_class.cc | 4 ++-- sql/wsrep_condition_variable.h | 10 +++++----- sql/wsrep_mutex.h | 10 +++++----- sql/wsrep_server_state.cc | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 21546ddaebf..7ed58555be1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -669,8 +669,8 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) /* wsrep-lib */ m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID), - m_wsrep_mutex(LOCK_thd_data), - m_wsrep_cond(COND_wsrep_thd), + m_wsrep_mutex(&LOCK_thd_data), + m_wsrep_cond(&COND_wsrep_thd), m_wsrep_client_service(this, m_wsrep_client_state), m_wsrep_client_state(this, m_wsrep_mutex, diff --git a/sql/wsrep_condition_variable.h b/sql/wsrep_condition_variable.h index 6ad53a3086c..c97b47378f7 100644 --- a/sql/wsrep_condition_variable.h +++ b/sql/wsrep_condition_variable.h @@ -26,7 +26,7 @@ class Wsrep_condition_variable : public wsrep::condition_variable { public: - Wsrep_condition_variable(mysql_cond_t& cond) + Wsrep_condition_variable(mysql_cond_t* cond) : m_cond(cond) { } ~Wsrep_condition_variable() @@ -34,21 +34,21 @@ public: void notify_one() { - mysql_cond_signal(&m_cond); + mysql_cond_signal(m_cond); } void notify_all() { - mysql_cond_broadcast(&m_cond); + mysql_cond_broadcast(m_cond); } void wait(wsrep::unique_lock& lock) { mysql_mutex_t* mutex= static_cast(lock.mutex()->native()); - mysql_cond_wait(&m_cond, mutex); + mysql_cond_wait(m_cond, mutex); } private: - mysql_cond_t& m_cond; + mysql_cond_t* m_cond; }; #endif /* WSREP_CONDITION_VARIABLE_H */ diff --git a/sql/wsrep_mutex.h b/sql/wsrep_mutex.h index 3454b44e0ec..f396c1be331 100644 --- a/sql/wsrep_mutex.h +++ b/sql/wsrep_mutex.h @@ -25,26 +25,26 @@ class Wsrep_mutex : public wsrep::mutex { public: - Wsrep_mutex(mysql_mutex_t& mutex) + Wsrep_mutex(mysql_mutex_t* mutex) : m_mutex(mutex) { } void lock() { - mysql_mutex_lock(&m_mutex); + mysql_mutex_lock(m_mutex); } void unlock() { - mysql_mutex_unlock(&m_mutex); + mysql_mutex_unlock(m_mutex); } void* native() { - return &m_mutex; + return m_mutex; } private: - mysql_mutex_t& m_mutex; + mysql_mutex_t* m_mutex; }; #endif /* WSREP_MUTEX_H */ diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc index ebc4efaabe5..973850871b1 100644 --- a/sql/wsrep_server_state.cc +++ b/sql/wsrep_server_state.cc @@ -43,8 +43,8 @@ Wsrep_server_state::Wsrep_server_state(const std::string& name, initial_position, max_protocol_version, wsrep::server_state::rm_sync) - , m_mutex(LOCK_wsrep_server_state) - , m_cond(COND_wsrep_server_state) + , m_mutex(&LOCK_wsrep_server_state) + , m_cond(&COND_wsrep_server_state) , m_service(*this) { } From d3e06dbbe30483c6e02193b6f6f0901e28f08e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Feb 2022 11:34:52 +0200 Subject: [PATCH 3/5] MDEV-27924 page_zip_copy_recs() corrupts ROW_FORMAT=COMPRESSED block descriptor In commit aaef2e1d8c843d1e40b1ce0c5199c3abb3c5da28 (MDEV-27058) we failed to introduce a special copy constructor that would preserve the "page_zip_des_t::fix" field that only exists there in order to avoid alignment loss on 64-bit systems. page_zip_copy_recs(): Invoke the special copy constructor. The block descriptor corruption causes assertion failures when running ./mtr --suite=innodb_zip while InnoDB has been built with UNIV_ZIP_COPY. Normally, calls to page_zip_copy_recs() occur very rarely on page splits. --- storage/innobase/include/page0types.h | 12 +++++++++++- storage/innobase/page/page0zip.cc | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h index 885d2290f7c..83fc45cdfc4 100644 --- a/storage/innobase/include/page0types.h +++ b/storage/innobase/include/page0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, 2021, MariaDB Corporation. +Copyright (c) 2019, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -119,6 +119,16 @@ struct page_zip_des_t - reinterpret_cast(this)); } + page_zip_des_t() = default; + page_zip_des_t(const page_zip_des_t&) = default; + + /* Initialize everything except the member "fix". */ + page_zip_des_t(const page_zip_des_t& old, bool) { + memcpy((void*) this, (void*) &old, + reinterpret_cast(&fix) + - reinterpret_cast(this)); + } + private: friend buf_pool_t; friend buf_page_t; diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index ec90d73e765..423cafe4629 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2021, MariaDB Corporation. +Copyright (c) 2014, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -4562,7 +4562,7 @@ page_zip_copy_recs( to the compressed data page. */ { page_zip_t* data = page_zip->data; - new (page_zip) page_zip_des_t(*src_zip); + new (page_zip) page_zip_des_t(*src_zip, false); page_zip->data = data; } ut_ad(page_zip_get_trailer_len(page_zip, dict_index_is_clust(index)) From 46764652dfa7b779a058f2802fc1d4233aece79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Feb 2022 13:31:14 +0200 Subject: [PATCH 4/5] MDEV-27798 SIGSEGV in dict_index_t::reconstruct_fields() When recovery is rolling back an incomplete instant DROP COLUMN operation, it may access non-existing fields. Let us avoid invoking std::find_if() outside the valid bounds of the array. This bug was reproduced with the Random Query Generator, using a combination of instant DROP, ADD...FIRST, CHANGE (renaming a column). Unfortunately, we were unable to create an mtr test case for reproducing this, despite spending considerable effort on it. --- storage/innobase/dict/dict0mem.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 6b1f837634b..0bdb086a5b6 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2021, MariaDB Corporation. +Copyright (c) 2013, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1217,6 +1217,8 @@ inline bool dict_index_t::reconstruct_fields() { DBUG_ASSERT(is_primary()); + const auto old_n_fields = n_fields; + n_fields += table->instant->n_dropped; n_def += table->instant->n_dropped; @@ -1241,11 +1243,11 @@ inline bool dict_index_t::reconstruct_fields() } else { DBUG_ASSERT(!c.is_not_null()); const auto old = std::find_if( - fields + n_first, fields + n_fields, + fields + n_first, fields + old_n_fields, [c](const dict_field_t& o) { return o.col->ind == c.ind(); }); - if (old >= fields + n_fields + if (old >= fields + old_n_fields || old->prefix_len || old->col != &table->cols[c.ind()]) { return true; From b91a123d8c9c321d54256d4ba055857c9505632b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 23 Feb 2022 15:48:08 +0200 Subject: [PATCH 5/5] Extend have_sanitizer with ASAN+UBSAN and MSAN Disable some tests that are too slow or big for MSAN. --- mysql-test/include/not_asan.inc | 2 +- mysql-test/include/not_msan.inc | 6 ++++++ mysql-test/include/not_ubsan.inc | 2 +- mysql-test/include/rpl_stop_server.inc | 4 +++- mysql-test/main/sum_distinct-big.test | 1 + .../suite/binlog/t/flashback-largebinlog.test | 2 +- mysql-test/suite/maria/max_length.test | 1 + sql/sys_vars.cc | 18 ++++++++++++------ 8 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 mysql-test/include/not_msan.inc diff --git a/mysql-test/include/not_asan.inc b/mysql-test/include/not_asan.inc index 9fc86a8525a..38fcac15ce7 100644 --- a/mysql-test/include/not_asan.inc +++ b/mysql-test/include/not_asan.inc @@ -2,7 +2,7 @@ # be overcome. In normal cases one should fix the bug server/test case or in # the worst case add a (temporary?) suppression in asan.supp or lsan.supp -if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value="ASAN"`) +if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "ASAN%"`) { --skip Can't be run with ASan } diff --git a/mysql-test/include/not_msan.inc b/mysql-test/include/not_msan.inc new file mode 100644 index 00000000000..ca1e2c1d7bd --- /dev/null +++ b/mysql-test/include/not_msan.inc @@ -0,0 +1,6 @@ +# This file should only be used with tests that are too big or slow for MSAN. + +if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "MSAN%"`) +{ +--skip Can't be run WITH_MSAN +} diff --git a/mysql-test/include/not_ubsan.inc b/mysql-test/include/not_ubsan.inc index 809f505507e..237adcb4896 100644 --- a/mysql-test/include/not_ubsan.inc +++ b/mysql-test/include/not_ubsan.inc @@ -2,7 +2,7 @@ # be overcome. In normal cases one should fix the bug server/test case or in # the worst case add a (temporary?) suppression in asan.supp or lsan.supp -if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value="UBSAN"`) +if (`select count(*) from information_schema.system_variables where variable_name='have_sanitizer' and global_value LIKE "%UBSAN"`) { --skip Can't be run with UBSAN } diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc index 049c3d5bbd2..470e86a139d 100644 --- a/mysql-test/include/rpl_stop_server.inc +++ b/mysql-test/include/rpl_stop_server.inc @@ -48,7 +48,9 @@ if ($rpl_debug) # Send shutdown to the connected server and give # it 60 seconds (of mysqltest's default) to die before zapping it -shutdown_server; +let $rpl_shutdown_timeout= `select 60*(1+9*count(*)) from information_schema.system_variables where variable_name='have_sanitizer' and global_value like "MSAN%"`; + +shutdown_server $rpl_shutdown_timeout; --source include/wait_until_disconnected.inc diff --git a/mysql-test/main/sum_distinct-big.test b/mysql-test/main/sum_distinct-big.test index 41aa5a44c19..f808f79dfb1 100644 --- a/mysql-test/main/sum_distinct-big.test +++ b/mysql-test/main/sum_distinct-big.test @@ -5,6 +5,7 @@ --source include/big_test.inc # Test will take more than one hour with valgrind --source include/not_valgrind.inc +--source include/not_msan.inc --source include/have_innodb.inc --source include/have_sequence.inc diff --git a/mysql-test/suite/binlog/t/flashback-largebinlog.test b/mysql-test/suite/binlog/t/flashback-largebinlog.test index fb2703dfac5..80b0da521cc 100644 --- a/mysql-test/suite/binlog/t/flashback-largebinlog.test +++ b/mysql-test/suite/binlog/t/flashback-largebinlog.test @@ -10,11 +10,11 @@ --let $mysqlbinlog_output= tmp/mysqlbinlog_big_1.out --source include/have_binlog_format_row.inc - --source include/have_log_bin.inc # This is a big test. --source include/big_test.inc +--source include/not_msan.inc # Test needs more than 4G of memory --source include/have_64bit.inc diff --git a/mysql-test/suite/maria/max_length.test b/mysql-test/suite/maria/max_length.test index a5bfb0b8fd6..02df51b33d7 100644 --- a/mysql-test/suite/maria/max_length.test +++ b/mysql-test/suite/maria/max_length.test @@ -6,6 +6,7 @@ --source include/big_test.inc # This test is too slow for valgrind --source include/not_valgrind.inc +--source include/not_msan.inc drop table if exists t1,t2; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fde7041ac85..12d0631019e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5078,13 +5078,19 @@ static Sys_var_have Sys_have_symlink( "--skip-symbolic-links option.", READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE); -#if defined(__SANITIZE_ADDRESS__) || defined(WITH_UBSAN) +#if defined __SANITIZE_ADDRESS__ || defined WITH_UBSAN || __has_feature(memory_sanitizer) -#ifdef __SANITIZE_ADDRESS__ -#define SANITIZER_MODE "ASAN" -#else -#define SANITIZER_MODE "UBSAN" -#endif /* __SANITIZE_ADDRESS__ */ +# ifdef __SANITIZE_ADDRESS__ +# ifdef WITH_UBSAN +# define SANITIZER_MODE "ASAN+UBSAN" +# else +# define SANITIZER_MODE "ASAN" +# endif +# elif defined WITH_UBSAN +# define SANITIZER_MODE "UBSAN" +# else +# define SANITIZER_MODE "MSAN" +# endif static char *have_sanitizer; static Sys_var_charptr Sys_have_santitizer(