Details
Description
sanja asked me if MemorySanitizer (MDEV-20377) is usable on clang-17. I had previously mostly used it on clang-15, so I tried a clang-16 build of 10.6 and accidentally found a bug that does not appear to be caught by older versions of the compiler:
MSAN_OPTIONS=abort_on_error=1:MSAN_OPTIONS=poison_in_dtor=0 LD_LIBRARY_PATH=~/libmsan-16 MSAN_SYMBOLIZER_PATH=~/bin/llvm-symbolizer-msan ./mtr main.pool_of_threads
|
10.6 53c6c823dc7cafefffdc93c79661cfb146ff8641 |
main.pool_of_threads [ fail ]
|
Test ended at 2024-02-16 16:01:09
|
|
CURRENT_TEST: main.pool_of_threads
|
mysqltest: In included file "./include/common-tests.inc":
|
included from /mariadb/10.6/mysql-test/main/pool_of_threads.test at line 17:
|
At line 1254: query 'select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"' failed: <Unknown> (2013): Lost connection to server during query
|
…
|
Version: '10.6.18-MariaDB-debug-log' socket: '/dev/shm/10.6msan/mysql-test/var/tmp/mysqld.1.sock' port: 16000 Source distribution
|
==981332==WARNING: MemorySanitizer: use-of-uninitialized-value
|
#0 0x55fd598bfae1 in Item_func::not_null_tables() const /mariadb/10.6/sql/item_func.cc:624:3
|
#1 0x55fd597e82d6 in Item_cond::eval_not_null_tables(void*) /mariadb/10.6/sql/item_cmpfunc.cc:5187:38
|
#2 0x55fd597e7707 in Item_cond::fix_fields(THD*, Item**) /mariadb/10.6/sql/item_cmpfunc.cc:5078:10
|
#3 0x55fd5a24ce1b in make_cond_for_table_from_pred(THD*, Item*, Item*, unsigned long long, unsigned long long, int, bool, bool, bool) /mariadb/10.6/sql/sql_select.cc:23938:16
|
#4 0x55fd5a17e543 in make_cond_for_table(THD*, Item*, unsigned long long, unsigned long long, int, bool, bool) /mariadb/10.6/sql/sql_select.cc:23866:10
|
#5 0x55fd5a17e543 in make_join_select(JOIN*, SQL_SELECT*, Item*) /mariadb/10.6/sql/sql_select.cc:12543:16
|
#6 0x55fd5a1563f0 in JOIN::optimize_stage2() /mariadb/10.6/sql/sql_select.cc:2855:7
|
#7 0x55fd5a15f3e1 in JOIN::optimize_inner() /mariadb/10.6/sql/sql_select.cc:2590:9
|
#8 0x55fd5a153b70 in JOIN::optimize() /mariadb/10.6/sql/sql_select.cc:1888:10
|
#9 0x55fd5a13c232 in mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /mariadb/10.6/sql/sql_select.cc:5127:19
|
#10 0x55fd5a13bc9d in handle_select(THD*, LEX*, select_result*, unsigned long) /mariadb/10.6/sql/sql_select.cc:559:10
|
#11 0x55fd5a078ff3 in execute_sqlcom_select(THD*, TABLE_LIST*) /mariadb/10.6/sql/sql_parse.cc:6376:12
|
#12 0x55fd5a0636ce in mysql_execute_command(THD*, bool) /mariadb/10.6/sql/sql_parse.cc:3980:12
|
#13 0x55fd5a053c60 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /mariadb/10.6/sql/sql_parse.cc:8143:18
|
#14 0x55fd5a04cc0c in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) /mariadb/10.6/sql/sql_parse.cc:1896:7
|
#15 0x55fd5a054531 in do_command(THD*, bool) /mariadb/10.6/sql/sql_parse.cc:1409:17
|
#16 0x55fd5a7f7c26 in threadpool_process_request(THD*) /mariadb/10.6/sql/threadpool_common.cc:435:13
|
#17 0x55fd5a7f7c26 in tp_callback(TP_connection*) /mariadb/10.6/sql/threadpool_common.cc:249:12
|
#18 0x55fd5a7ffd45 in worker_main(void*) /mariadb/10.6/sql/threadpool_generic.cc:1556:5
|
#19 0x7f01e9dd045b in start_thread nptl/pthread_create.c:444:8
|
#20 0x7f01e9e50bbb in clone3 misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
|
|
Memory was marked as uninitialized
|
#0 0x55fd595d3db1 in __msan_allocated_memory (/dev/shm/10.6msan/sql/mariadbd+0xf26db1) (BuildId: a8f73f07e16a2953)
|
#1 0x55fd5b5e2d85 in my_malloc /mariadb/10.6/mysys/my_malloc.c:114:7
|
I checked this with rr, and indeed the memory is straight from TRASH_ALLOC():
10.6 53c6c823dc7cafefffdc93c79661cfb146ff8641 |
#3 0x000055c7785aed86 in my_malloc (key=<optimized out>, size=<optimized out>, size@entry=576, my_flags=<optimized out>) at /mariadb/10.6/mysys/my_malloc.c:114
|
#4 0x000055c7785925e0 in alloc_root (mem_root=0x72b000052d98, length=576) at /mariadb/10.6/mysys/my_alloc.c:189
|
#5 0x000055c7771bbcb1 in Item::operator new (size=552, mem_root=0x215000080b58) at /mariadb/10.6/sql/item.h:861
|
#6 eliminate_item_equal (thd=thd@entry=0x72b00004d018, cond=cond@entry=0x0, upper_levels=0x0, item_equal=<optimized out>) at /mariadb/10.6/sql/sql_select.cc:16889
|
#7 0x000055c777145c0f in substitute_for_best_equal_field (thd=0x72b00004d018, context_tab=context_tab@entry=0x1, cond=0x711000075470, cond_equal=0x711000075548, table_join_idx=0x71e0000213f8,
|
do_substitution=true) at /mariadb/10.6/sql/sql_select.cc:17069
|
#8 0x000055c777120aa1 in JOIN::optimize_stage2 (this=0x71a000030030) at /mariadb/10.6/sql/sql_select.cc:2710
|
The memory is being used here:
10.6 53c6c823dc7cafefffdc93c79661cfb146ff8641 |
#0 0x000055c776594018 in __msan_warning_with_origin_noreturn ()
|
#1 0x000055c77688bae2 in Item_func::not_null_tables (this=<optimized out>) at /mariadb/10.6/sql/item_func.cc:624
|
#2 0x000055c7767b42d7 in Item_cond::eval_not_null_tables (this=<optimized out>, opt_arg=<optimized out>) at /mariadb/10.6/sql/item_cmpfunc.cc:5187
|
#3 0x000055c7767b3708 in Item_cond::fix_fields (this=0x711000075970, thd=0x72b00004d018, ref=<optimized out>) at /mariadb/10.6/sql/item_cmpfunc.cc:5078
|
#4 0x000055c777218e1c in make_cond_for_table_from_pred (thd=0x72b00004d018, root_cond=0x711000075470, cond=0x711000075470, tables=13835058055282163713, used_table=used_table@entry=1,
|
join_tab_idx_arg=join_tab_idx_arg@entry=0, exclude_expensive_cond=false, retain_ref_cond=<optimized out>, is_top_and_level=<optimized out>) at /mariadb/10.6/sql/sql_select.cc:23938
|
#5 0x000055c77714a544 in make_cond_for_table (thd=<optimized out>, cond=<optimized out>, tables=<optimized out>, used_table=<optimized out>, join_tab_idx_arg=<optimized out>, exclude_expensive_cond=false,
|
retain_ref_cond=false) at /mariadb/10.6/sql/sql_select.cc:23866
|
#6 make_join_select (join=<optimized out>, join@entry=0x71a000030030, select=<optimized out>, cond=<optimized out>) at /mariadb/10.6/sql/sql_select.cc:12543
|
#7 0x000055c7771223f1 in JOIN::optimize_stage2 (this=0x71a000030030) at /mariadb/10.6/sql/sql_select.cc:2855
|
The construction of the object happens here:
eliminate_item_equal() |
eq_item= new (thd->mem_root) Item_func_eq(thd, |
field_item->remove_item_direct_ref(),
|
head_item->remove_item_direct_ref());
|
The following patch, which makes use of the C++11 data member default initializer feature (to have the initialization added to every constructor), fixes the bug:
diff --git a/sql/item_func.h b/sql/item_func.h
|
index 170fc943681..f3d3684f5b1 100644
|
--- a/sql/item_func.h
|
+++ b/sql/item_func.h
|
@@ -89,7 +89,7 @@ class Item_func :public Item_func_or_sum
|
static void wrong_param_count_error(const LEX_CSTRING &schema_name,
|
const LEX_CSTRING &func_name);
|
|
- table_map not_null_tables_cache;
|
+ table_map not_null_tables_cache= 0;
|
|
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
|
GE_FUNC,GT_FUNC,FT_FUNC, |
I think that along with that addition, some redundant initialization should be removed.
Attachments
Issue Links
- includes
-
MDEV-33665 main.pool_of_threads fails due to (spurious) uninitialized Item_func::not_null_tables_cache
-
- Closed
-
-
MDEV-33755 Some tests cause MSAN alarms due to uninitialized Item_func::not_null_tables_cache
-
- In Review
-
- relates to
-
MDBF-741 Remove the gcc UBSAN builder to use the clang based UBSAN
-
- In Testing
-
Activity
I reproduced this with 10.5 using clang-17 as well, and the same patch fixes it:
10.5 8a1904d7825f9897cd237fc6a1d8a57a9f2108de |
CURRENT_TEST: main.pool_of_threads
|
mysqltest: In included file "./include/common-tests.inc":
|
included from /mariadb/10.5/mysql-test/main/pool_of_threads.test at line 17:
|
At line 1254: query 'select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"' failed: 2013: Lost connection to MySQL server during query
|
…
|
==1100999==WARNING: MemorySanitizer: use-of-uninitialized-value
|
#0 0x55ae778b31a1 in Item_func::not_null_tables() const /mariadb/10.5/sql/item_func.cc:632:3
|
#1 0x55ae777debd6 in Item_cond::fix_fields(THD*, Item**) /mariadb/10.5/sql/item_cmpfunc.cc:5001:38
|
#2 0x55ae781ff9cc in make_cond_for_table_from_pred(THD*, Item*, Item*, unsigned long long, unsigned long long, int, bool, bool, bool) /mariadb/10.5/sql/sql_select.cc:23197:16
|
#3 0x55ae78130e99 in make_cond_for_table(THD*, Item*, unsigned long long, unsigned long long, int, bool, bool) /mariadb/10.5/sql/sql_select.cc:23127:10
|
#4 0x55ae78130e99 in make_join_select(JOIN*, SQL_SELECT*, Item*) /mariadb/10.5/sql/sql_select.cc:11897:16
|
#5 0x55ae78109925 in JOIN::optimize_stage2() /mariadb/10.5/sql/sql_select.cc:2663:7
|
#6 0x55ae78111f26 in JOIN::optimize_inner() /mariadb/10.5/sql/sql_select.cc:2412:9
|
#7 0x55ae781071d0 in JOIN::optimize() /mariadb/10.5/sql/sql_select.cc:1740:10
|
#8 0x55ae780f1b2f in mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /mariadb/10.5/sql/sql_select.cc:4868:19
|
#9 0x55ae780f147d in handle_select(THD*, LEX*, select_result*, unsigned long) /mariadb/10.5/sql/sql_select.cc:449:10
|
#10 0x55ae78034335 in execute_sqlcom_select(THD*, TABLE_LIST*) /mariadb/10.5/sql/sql_parse.cc:6417:12
|
#11 0x55ae7801e5ae in mysql_execute_command(THD*) /mariadb/10.5/sql/sql_parse.cc:4022:12
|
#12 0x55ae7800ed76 in mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) /mariadb/10.5/sql/sql_parse.cc:8196:18
|
#13 0x55ae78007636 in dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) /mariadb/10.5/sql/sql_parse.cc:1891:7
|
#14 0x55ae7800f9c7 in do_command(THD*) /mariadb/10.5/sql/sql_parse.cc:1375:17
|
#15 0x55ae7876a0d1 in threadpool_process_request(THD*) /mariadb/10.5/sql/threadpool_common.cc:365:18
|
#16 0x55ae7876a0d1 in tp_callback(TP_connection*) /mariadb/10.5/sql/threadpool_common.cc:199:12
|
#17 0x55ae78771a95 in worker_main(void*) /mariadb/10.5/sql/threadpool_generic.cc:1567:5
|
#18 0x7f7e4766845b in start_thread nptl/pthread_create.c:444:8
|
#19 0x7f7e476e8bbb in clone3 misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
|
|
Memory was marked as uninitialized
|
#0 0x55ae775d5871 in __msan_allocated_memory (/dev/shm/10.5msan/sql/mariadbd+0xf31871) (BuildId: bf6024e88d2066fe)
|
#1 0x55ae796575f1 in my_malloc /mariadb/10.5/mysys/my_malloc.c:114:7
|
|
SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.5/sql/item_func.cc:632:3 in Item_func::not_null_tables() const
|
Exiting
|
I just ran the default tests in a 10.6 based branch with clang-18 and got a large number of failures:
Completed: Failed 908/5958 tests, 84.76% were successful.
|
grep 'SUMMARY: MemorySanitizer: use-of-uninitialized-value' var/log/stdout.log|sort|uniq -c
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value (/dev/shm/10.6msan/sql/mariadbd+0xfd809b) (BuildId: 85f92222a52eb834) in bcmp
|
4 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/mysys/crc32/crc32c_amd64.cc:709:5 in crc32c_3way
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/debug_sync.cc:1403:5 in debug_sync_eval_action(THD*, char*, char*)
|
1513 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/item_func.cc:624:3 in Item_func::not_null_tables() const
|
22 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/multi_range_read.cc:1210:31 in DsMrr_impl::dsmrr_init(handler*, st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*)
|
6 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/sql_parse.cc:5711:10 in mysql_execute_command(THD*, bool)
|
12 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/sql_prepare.cc:2310:19 in mysql_test_handler_read(Prepared_statement*, TABLE_LIST*)
|
1 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/buf/buf0buf.cc:80:8 in set_numa_interleave_t::set_numa_interleave_t()
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/handler/ha_innodb.cc:12350:4 in create_table_info_t::create_foreign_keys()
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/handler/ha_innodb.cc:12497:5 in create_table_info_t::create_foreign_keys()
|
262 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/handler/ha_innodb.cc:15513:25 in get_foreign_key_info(THD*, dict_foreign_t*)
|
6 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/myisam/ft_boolean_search.c:293:5 in ftb_parse_query_internal
|
1 SUMMARY: MemorySanitizer: use-of-uninitialized-value obj-wide/ncurses/../../ncurses/tinfo/db_iterator.c:64:25 in add_to_blob
|
The bulk of the failures are caught in Item_func::not_null_tables(), with get_foreign_key_info() coming in for a good second.
I can’t revert to clang-15 to work around this on my system anymore:
/usr/include/c++/v1/__config:48:8: warning: "Libc++ only supports Clang 16 and later" [-W#warnings]
|
# warning "Libc++ only supports Clang 16 and later"
|
I figured out the failure in get_foreign_key_info():
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
|
index bea3709943a..9248a2a8174 100644
|
--- a/storage/innobase/handler/ha_innodb.cc
|
+++ b/storage/innobase/handler/ha_innodb.cc
|
@@ -15409,7 +15409,6 @@ get_foreign_key_info(
|
char tmp_buff[NAME_LEN+1];
|
char name_buff[NAME_LEN+1];
|
const char* ptr;
|
- LEX_CSTRING* referenced_key_name;
|
LEX_CSTRING* name = NULL;
|
|
if (dict_table_t::is_temporary_name(foreign->foreign_table_name)) {
|
@@ -15510,18 +15509,16 @@ get_foreign_key_info(
|
|
if (foreign->referenced_index
|
&& foreign->referenced_index->name != NULL) {
|
- referenced_key_name = thd_make_lex_string(
|
+ f_key_info.referenced_key_name = thd_make_lex_string(
|
thd,
|
- f_key_info.referenced_key_name,
|
+ nullptr,
|
foreign->referenced_index->name,
|
strlen(foreign->referenced_index->name),
|
1);
|
} else {
|
- referenced_key_name = NULL;
|
+ f_key_info.referenced_key_name = nullptr;
|
}
|
|
- f_key_info.referenced_key_name = referenced_key_name;
|
-
|
pf_key_info = (FOREIGN_KEY_INFO*) thd_memdup(thd, &f_key_info,
|
sizeof(FOREIGN_KEY_INFO));
|
|
My guess is that up to clang-15, MemorySanitizer was initializing all data members in the default constructor of st_foreign_key_info, which exists because of List data members. An alternative (and overkill) fix could be to explicitly initialize all data fields, to let the constructor do its job:
diff --git a/sql/table.h b/sql/table.h
|
index 2ef61ee9f7e..29016de9ed0 100644
|
--- a/sql/table.h
|
+++ b/sql/table.h
|
@@ -1856,14 +1856,14 @@ enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_NO_ACTION,
|
|
typedef struct st_foreign_key_info
|
{
|
- LEX_CSTRING *foreign_id;
|
- LEX_CSTRING *foreign_db;
|
- LEX_CSTRING *foreign_table;
|
- LEX_CSTRING *referenced_db;
|
- LEX_CSTRING *referenced_table;
|
- enum_fk_option update_method;
|
- enum_fk_option delete_method;
|
- LEX_CSTRING *referenced_key_name;
|
+ LEX_CSTRING *foreign_id= nullptr;
|
+ LEX_CSTRING *foreign_db= nullptr;
|
+ LEX_CSTRING *foreign_table= nullptr;
|
+ LEX_CSTRING *referenced_db= nullptr;
|
+ LEX_CSTRING *referenced_table= nullptr;
|
+ enum_fk_option update_method= FK_OPTION_UNDEF;
|
+ enum_fk_option delete_method= FK_OPTION_UNDEF;
|
+ LEX_CSTRING *referenced_key_name= nullptr;
|
List<LEX_CSTRING> foreign_fields;
|
List<LEX_CSTRING> referenced_fields;
|
} FOREIGN_KEY_INFO; |
I will try to figure out the Item_func::not_null_tables() next.
As far as I understand, the issue in get_foreign_key_info() exists in the very first version of that code (MySQL commit, MariaDB commit. It appears to be passing an uninitialized f_key_info.referenced_key_name to the function thd_make_lex_string(). However, that parameter is actually unused in the implementation, because our call is passing allocate_lex_string=1:
extern "C" |
LEX_CSTRING *thd_make_lex_string(THD *thd, LEX_CSTRING *lex_str,
|
const char *str, size_t size, |
int allocate_lex_string) |
{
|
return allocate_lex_string ? thd->make_clex_string(str, size) |
: thd->make_lex_string(lex_str, str, size);
|
}
|
It appears that recent implementations of MemorySanitizer have added a caller-site check. I did not find any MSAN_OPTIONS for controlling this, and I did not see a sign for that in the executable code either. When it comes to the Item_func::not_null_tables(), the value looks uninitialized and it had been marked uninitialized here:
10.6 0df4651c13d68f1c228986f940d8ea4a226132f5 |
#0 __memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:301
|
#1 0x000056363f134eeb in __msan::PoisonMemory(void const*, unsigned long, __sanitizer::StackTrace*) ()
|
#2 0x000056363f0de99a in __msan_allocated_memory ()
|
#3 0x0000563641343685 in my_malloc (key=7, size=<optimized out>, size@entry=576, my_flags=<optimized out>) at /mariadb/10.6/mysys/my_malloc.c:114
|
#4 0x000056364132052f in alloc_root (mem_root=0x72b00007cf98, length=576) at /mariadb/10.6/mysys/my_alloc.c:189
|
#5 0x000056363fd3ae5a in Item::operator new (size=552, mem_root=0x2150000a6ad8) at /mariadb/10.6/sql/item.h:861
|
#6 eliminate_item_equal (thd=thd@entry=0x72b000077018, cond=cond@entry=0x0, upper_levels=0x0, item_equal=<optimized out>) at /mariadb/10.6/sql/sql_select.cc:16889
|
#7 0x000056363fcc40fc in substitute_for_best_equal_field (thd=0x72b000077018, context_tab=context_tab@entry=0x1, cond=0x711000089e70, cond_equal=0x711000089f48, table_join_idx=<optimized out>,
|
do_substitution=<optimized out>) at /mariadb/10.6/sql/sql_select.cc:17069
|
#8 0x000056363fc9e80f in JOIN::optimize_stage2 (this=0x71a000044430) at /mariadb/10.6/sql/sql_select.cc:2710
|
The following patch (making use of a C++11 feature to extend constructors) would appear to fix this:
diff --git a/sql/item_func.h b/sql/item_func.h
|
index 170fc943681..f3d3684f5b1 100644
|
--- a/sql/item_func.h
|
+++ b/sql/item_func.h
|
@@ -89,7 +89,7 @@ class Item_func :public Item_func_or_sum
|
static void wrong_param_count_error(const LEX_CSTRING &schema_name,
|
const LEX_CSTRING &func_name);
|
|
- table_map not_null_tables_cache;
|
+ table_map not_null_tables_cache= 0;
|
|
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
|
GE_FUNC,GT_FUNC,FT_FUNC, |
However, there could be a logic bug that a call to Item_func::eval_not_null_tables() is missing somewhere.
With the above two fixes, it looks much better, only some 70 tests failing. Note: this is not a plain 10.6 branch; there are some uncommitted tests and work-in-progress code:
Failing test(s): innodb.innodb innodb.innodb_mysql innodb.innodb-index main.mysql_client_test_nonblock main.mysql_client_test main.subselect_mat_cost versioning.foreign innodb.innodb-index-online innodb.foreign_key sys_vars.innodb_numa_interleave_basic innodb_fts.opt innodb.full_crc32_import main.innodb_mrr_cpk innodb.innodb_page_compressed main.range_mrr_icp handler.innodb innodb_fts.misc main.rowid_filter_innodb main.partition_mrr_aria innodb.innodb-fk-warnings main.subselect2 main.partition_mrr_myisam main.mysql_client_test_comp main.myisam_mrr innodb_gis.alter_spatial_index main.ps_missed_cmds main.debug_sync innodb_gis.point_basic main.explain_json main.mysql-interactive main.mrr_icp_extra main.subselect_mat maria.mrr handler.aria main.select_jcl6 main.subselect_no_exists_to_in handler.disconnect_4480 main.subselect_no_mat handler.heap handler.interface handler.myisam main.subselect_no_opts main.subselect_no_scache main.fulltext handler.ps sys_vars.ft_boolean_syntax_func main.xtradb_mrr main.subselect_no_semijoin main.join_nested_jcl6 main.subselect_sj main.subselect_sj_jcl6 main.join_outer_jcl6 main.myisam_icp main.subselect_sj_mat main.subselect innodb.ibuf_delete main.subselect3_jcl6 main.partition_mrr_innodb main.innodb_icp main.join_cache main.subselect4 maria.icp
grep 'SUMMARY: MemorySanitizer: use-of-uninitialized-value' var/log/stdout.log|sort|uniq -c
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value (/dev/shm/10.6msan/sql/mariadbd+0xfd808b) (BuildId: fd63dc86a6202ea3) in bcmp
|
4 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/mysys/crc32/crc32c_amd64.cc:709:5 in crc32c_3way
|
2 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/debug_sync.cc:1403:5 in debug_sync_eval_action(THD*, char*, char*)
|
66 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/multi_range_read.cc:1210:31 in DsMrr_impl::dsmrr_init(handler*, st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*)
|
8 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/sql_parse.cc:5711:10 in mysql_execute_command(THD*, bool)
|
10 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/sql/sql_prepare.cc:2310:19 in mysql_test_handler_read(Prepared_statement*, TABLE_LIST*)
|
1 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/buf/buf0buf.cc:80:8 in set_numa_interleave_t::set_numa_interleave_t()
|
4 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/handler/ha_innodb.cc:12350:4 in create_table_info_t::create_foreign_keys()
|
32 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/innobase/handler/ha_innodb.cc:12497:5 in create_table_info_t::create_foreign_keys()
|
8 SUMMARY: MemorySanitizer: use-of-uninitialized-value /mariadb/10.6/storage/myisam/ft_boolean_search.c:293:5 in ftb_parse_query_internal
|
Re the failure with not_null_tables_cache... Normally, not_null_tables_cache is set here:
Item_func::fix_fields(THD *thd, Item **ref) |
{
|
...
|
not_null_tables_cache= 0;
|
However in this path it is not set:
eq_item= new (thd->mem_root) Item_func_eq(thd, |
field_item->remove_item_direct_ref(),
|
head_item->remove_item_direct_ref());
|
|
if (!eq_item || eq_item->set_cmp_func(thd)) |
return 0; |
eq_item->quick_fix_field();
|
because quick_fix_fields() does NOT set not_null_tables_cache.
There is only one quick_fix_fields() implementation...
An alternative fix to Marko's original fix:
diff --git a/sql/item_func.cc b/sql/item_func.cc
|
index 0973d0c2c82..54f7eb222bf 100644
|
--- a/sql/item_func.cc
|
+++ b/sql/item_func.cc
|
@@ -397,6 +397,7 @@ Item_func::quick_fix_field()
|
}
|
}
|
base_flags|= item_base_t::FIXED;
|
+ eval_not_null_tables(NULL);
|
} |
Now testing it in BB.
The problem with the original fix is that it's setting the value to some "default" constant which may mask the issues. If we just want ASAN not to fail, why not define TRASH_PTR to call bzero...
I'd also like to learn why this failure wasn't caught until now...
psergei, thank you. The reason why I asked you was exactly that I was worried that initializing the field would merely mask the problem for MemorySanitizer (MSAN, clang -fsanitize=memory) but not fix it. ASAN (AddressSanitizer, -fsanitize=address) has nothing to do with this; it does not aim to catch the use of uninitialized values.
Shall you file a separate ticket for the fix, including some analysis on when the problem was introduced?
Update:
sed -ne 's|SUMMARY: MemorySanitizer: use-of-uninitialized-value ||p'<10.5msan/mysql-test/var/log/stdout.log|sort|uniq -c
|
10.5 51e3f1daf54309d14fe8db438024d88aa110e86a |
4 /mariadb/10.5/mysys/crc32/crc32c_amd64.cc:709:5 in crc32c_3way
|
2 /mariadb/10.5/sql/debug_sync.cc:1248:5 in debug_sync_eval_action(THD*, char*, char*)
|
100 /mariadb/10.5/sql/item_func.cc:632:3 in Item_func::not_null_tables() const
|
2714 /mariadb/10.5/sql/log.cc:3599:8 in MYSQL_BIN_LOG::open_index_file(char const*, char const*, bool)
|
58 /mariadb/10.5/sql/multi_range_read.cc:1208:31 in DsMrr_impl::dsmrr_init(handler*, st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*)
|
8 /mariadb/10.5/sql/sql_parse.cc:5753:10 in mysql_execute_command(THD*)
|
8 /mariadb/10.5/sql/sql_prepare.cc:2268:19 in mysql_test_handler_read(Prepared_statement*, TABLE_LIST*)
|
1 /mariadb/10.5/storage/innobase/buf/buf0buf.cc:87:8 in set_numa_interleave_t::set_numa_interleave_t()
|
2 /mariadb/10.5/storage/innobase/dict/dict0stats.cc:2399:7 in dict_stats_save_index_stat(dict_index_t*, long, char const*, unsigned long, unsigned long*, char const*, trx_t*)
|
4 /mariadb/10.5/storage/innobase/handler/ha_innodb.cc:12247:4 in create_table_info_t::create_foreign_keys()
|
32 /mariadb/10.5/storage/innobase/handler/ha_innodb.cc:12394:5 in create_table_info_t::create_foreign_keys()
|
8 /mariadb/10.5/storage/myisam/ft_boolean_search.c:293:5 in ftb_parse_query_internal
|
1 obj-wide/ncurses/../../ncurses/tinfo/db_iterator.c:64:25 in add_to_blob
|
The fix of MDEV-33665 was not enough; the error is still being flagged in some tests, such as main.subselect_sj2_mat during the following:
explain
|
select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3)) |
Stack trace of the access:
10.5 51e3f1daf54309d14fe8db438024d88aa110e86a |
#0 0x000055b34cccb9e8 in Item_func::not_null_tables (this=<optimized out>) at /mariadb/10.5/sql/item_func.cc:632
|
#1 0x000055b34cbf73c6 in Item_cond::fix_fields (this=0x7120000a78b0, thd=0x72b00003f018, ref=<optimized out>) at /mariadb/10.5/sql/item_cmpfunc.cc:5001
|
#2 0x000055b34d5646d2 in add_cond_and_fix (thd=0x72b00003f018, e2=<optimized out>, e1=<optimized out>) at /mariadb/10.5/sql/sql_select.cc:11318
|
#3 make_join_select (join=join@entry=0x71b00003fe30, select=0x715000095630, cond=0x70d000007050) at /mariadb/10.5/sql/sql_select.cc:12314
|
#4 0x000055b34d538ad5 in JOIN::optimize_stage2 (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:2663
|
#5 0x000055b34d540b14 in JOIN::optimize_inner (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:2412
|
#6 0x000055b34d5365c1 in JOIN::optimize (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:1740
|
#7 0x000055b34d521131 in mysql_select (thd=0x72b00003f018, tables=<optimized out>,
|
fields=@0x71a000055fa8: {<base_list> = {<Sql_alloc> = {dummy_for_valgrind = false}, first = 0x705000066b00, last = 0x705000023e48, elements = 4}, <No data fields>}, conds=<optimized out>, og_num=0,
|
order=<optimized out>, group=<optimized out>, having=<optimized out>, proc_param=<optimized out>, select_options=<optimized out>, result=<optimized out>, unit=<optimized out>, select_lex=<optimized out>)
|
at /mariadb/10.5/sql/sql_select.cc:4868
|
#8 0x000055b34d60b16a in mysql_explain_union (thd=<optimized out>, thd@entry=0x72b00003f018, unit=<optimized out>, unit@entry=0x72b000042fe8, result=<optimized out>, result@entry=0x70600001b030)
|
at /mariadb/10.5/sql/sql_select.cc:28121
|
Stack trace of the allocation where the memory was marked uninitialized:
10.5 51e3f1daf54309d14fe8db438024d88aa110e86a |
#5 0x000055b34d564821 in Item::operator new (size=224, mem_root=0x21100008dc10) at /mariadb/10.5/sql/item.h:748
|
#6 make_join_select (join=join@entry=0x71b00003fe30, select=0x715000095630, cond=0x70d000007050) at /mariadb/10.5/sql/sql_select.cc:12336
|
#7 0x000055b34d538ad5 in JOIN::optimize_stage2 (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:2663
|
#8 0x000055b34d540b14 in JOIN::optimize_inner (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:2412
|
#9 0x000055b34d5365c1 in JOIN::optimize (this=this@entry=0x71b00003fe30) at /mariadb/10.5/sql/sql_select.cc:1740
|
#10 0x000055b34d521131 in mysql_select (thd=0x72b00003f018, tables=<optimized out>,
|
fields=@0x71a000055fa8: {<base_list> = {<Sql_alloc> = {dummy_for_valgrind = false}, first = 0x705000066b00, last = 0x705000023e48, elements = 4}, <No data fields>}, conds=<optimized out>, og_num=0,
|
order=<optimized out>, group=<optimized out>, having=<optimized out>, proc_param=<optimized out>, select_options=<optimized out>, result=<optimized out>, unit=<optimized out>, select_lex=<optimized out>)
|
at /mariadb/10.5/sql/sql_select.cc:4868
|
#11 0x000055b34d60b16a in mysql_explain_union (thd=<optimized out>, thd@entry=0x72b00003f018, unit=<optimized out>, unit@entry=0x72b000042fe8, result=<optimized out>, result@entry=0x70600001b030)
|
at /mariadb/10.5/sql/sql_select.cc:28121
|
psergei, do you want to implement more specialized fixes, or can I just extend the constructor, as in my above patch?
The binlog and replication test failures were apparently specific to cmake -DPLUGIN_PERFSCHEMA=NO and can be fixed by the following:
diff --git a/sql/log.h b/sql/log.h
|
index fbe0f30f22b..dd31081c404 100644
|
--- a/sql/log.h
|
+++ b/sql/log.h
|
@@ -426,6 +426,7 @@ struct wait_for_commit;
|
|
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
|
{
|
+#ifdef HAVE_PSI_INTERFACE
|
/** The instrumentation key to use for @ LOCK_index. */
|
PSI_mutex_key m_key_LOCK_index;
|
/** The instrumentation key to use for @ COND_relay_log_updated */
|
@@ -440,6 +441,16 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
|
PSI_cond_key m_key_COND_queue_busy;
|
/** The instrumentation key to use for LOCK_binlog_end_pos. */
|
PSI_mutex_key m_key_LOCK_binlog_end_pos;
|
+#else
|
+ static constexpr PSI_mutex_key m_key_LOCK_index= 0;
|
+ static constexpr PSI_cond_key m_key_relay_log_update= 0;
|
+ static constexpr PSI_cond_key m_key_bin_log_update= 0;
|
+ static constexpr PSI_file_key m_key_file_log= 0, m_key_file_log_cache= 0;
|
+ static constexpr PSI_file_key m_key_file_log_index= 0;
|
+ static constexpr PSI_file_key m_key_file_log_index_cache= 0;
|
+ static constexpr PSI_cond_key m_key_COND_queue_busy= 0;
|
+ static constexpr PSI_mutex_key m_key_LOCK_binlog_end_pos= 0;
|
+#endif
|
|
struct group_commit_entry
|
{ |
With the above patches, I got the following:
Completed: Failed 74/5298 tests, 98.60% were successful.
Failing test(s): innodb.innodb innodb.innodb_mysql innodb.innodb-index main.mysql_client_test main.mysql_client_test_nonblock main.subselect_mat_cost versioning.foreign innodb.innodb-index-online innodb.foreign_key innodb_fts.opt main.backup_stages sys_vars.innodb_numa_interleave_basic innodb.innodb_page_compressed main.m-
MDEV-32667innodb_gis.alter_spatial_index main.xtradb_mrr main.partition_mrr_aria handler.innodb innodb.innodb-fk-warnings main.partition_mrr_myisam innodb.full_crc32_import main.mysql_client_test_comp innodb_gis.point_basic main.rowid_filter_innodb main.range_mrr_icp main.fulltext main.mrr_icp_extra main.subselect_mat main.subselect_no_exists_to_in main.debug_sync handler.aria main.select_jcl6 main.subselect_no_mat main.subselect_no_opts handler.disconnect_4480 main.explain_json main.subselect2 main.innodb_mrr_cpk main.myisam_mrr handler.heap handler.interface main.subselect_no_scache main.myisam_icp handler.myisam main.join_nested_jcl6 sys_vars.ft_boolean_syntax_func main.subselect_no_semijoin handler.ps main.subselect_sj main.mysql-interactive main.subselect main.subselect_sj_jcl6 main.subselect_sj_mat main.join_outer_jcl6 innodb_fts.misc main.subselect3_jcl6 maria.mrr main.partition_mrr_innodb main.join_cache main.innodb_icp main.subselect4 maria.icp innodb.mdev-19747
4 /mariadb/10.5/mysys/crc32/crc32c_amd64.cc:709:5 in crc32c_3way
|
2 /mariadb/10.5/sql/debug_sync.cc:1248:5 in debug_sync_eval_action(THD*, char*, char*)
|
66 /mariadb/10.5/sql/multi_range_read.cc:1208:31 in DsMrr_impl::dsmrr_init(handler*, st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*)
|
10 /mariadb/10.5/sql/sql_parse.cc:5753:10 in mysql_execute_command(THD*)
|
8 /mariadb/10.5/sql/sql_prepare.cc:2268:19 in mysql_test_handler_read(Prepared_statement*, TABLE_LIST*)
|
1 /mariadb/10.5/storage/innobase/buf/buf0buf.cc:87:8 in set_numa_interleave_t::set_numa_interleave_t()
|
2 /mariadb/10.5/storage/innobase/dict/dict0stats.cc:2399:7 in dict_stats_save_index_stat(dict_index_t*, long, char const*, unsigned long, unsigned long*, char const*, trx_t*)
|
4 /mariadb/10.5/storage/innobase/handler/ha_innodb.cc:12247:4 in create_table_info_t::create_foreign_keys()
|
32 /mariadb/10.5/storage/innobase/handler/ha_innodb.cc:12394:5 in create_table_info_t::create_foreign_keys()
|
8 /mariadb/10.5/storage/myisam/ft_boolean_search.c:293:5 in ftb_parse_query_internal
|
1 obj-wide/ncurses/../../ncurses/tinfo/db_iterator.c:64:25 in add_to_blob
|
The CRC failure is at least for innodb.innodb_page_compressed, related to buf_page_encrypt(). Maybe some additional instrumentation will be needed around WolfSSL.
marko Yes, I would like to reproduce this and so optimizer team can work on the failures ourselves. Any idea which OS to use for this?
psergei, I use clang-18 on Debian and the build instructions that I have updated in MDEV-20377. At a minimum, you need an instrumented libc++. If you want to avoid failures for some client tests, you must work around MDEV-22083 by building all the dependencies of libmariadb as well.
I don’t know if all these failures are reproducible with clang-16, but I think that the chances are good for that. You could try a pre-made container, which is what the MSAN builder on our CI could soon be updated to:
docker pull quay.io/mariadb-foundation/bb-worker:debian11-msan-clang-16
|
The test test_bind_result_ext1 in main.mysql_client_test fails because only the least significant 32 bits of long bData are being initialized:
10.5 fb774eb1ebab7d397c10a516be364d395440d079 |
0x000055dbbce480f2 in convert_froma_string (r_param=r_param@entry=0x71c0000002b8, buffer=0x72400000201f "206\0036.7", len=<optimized out>) at /mariadb/10.5/libmariadb/libmariadb/ma_stmt_codec.c:536
|
536 longstore(r_param->buffer, (int32)val);
|
(rr) bt
|
#0 0x000055dbbce480f2 in convert_froma_string (r_param=r_param@entry=0x71c0000002b8, buffer=0x72400000201f "206\0036.7", len=<optimized out>) at /mariadb/10.5/libmariadb/libmariadb/ma_stmt_codec.c:536
|
#1 0x000055dbbce45c2c in ps_fetch_string (r_param=0x71c0000002b8, field=<optimized out>, row=0x7fff9b9cede0) at /mariadb/10.5/libmariadb/libmariadb/ma_stmt_codec.c:1197
|
#2 0x000055dbbce2a01c in mthd_stmt_fetch_to_bind (stmt=<optimized out>, row=<optimized out>) at /mariadb/10.5/libmariadb/libmariadb/mariadb_stmt.c:446
|
#3 0x000055dbbce327b6 in mysql_stmt_fetch (stmt=stmt@entry=0x718000000000) at /mariadb/10.5/libmariadb/libmariadb/mariadb_stmt.c:1503
|
#4 0x000055dbbcb881d9 in wrap_mysql_stmt_fetch (stmt=0x718000000000) at /mariadb/10.5/tests/nonblock-wrappers.h:351
|
#5 test_bind_result_ext1 () at /mariadb/10.5/tests/mysql_client_test.c:3927
|
#6 0x000055dbbcb52204 in main (argc=0, argv=0x70e000000078) at /mariadb/10.5/tests/mysql_client_fw.c:1459
|
This would appear to be a bug in Connector/C. long is 32 bits only on 32-bit platforms or LLP64 platforms, such as Microsoft Windows.
I see that MYSQL_TYPE_LONG always was 32 bits. Here is the fixed test:
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
|
index fde6148f4e0..b1e40ea5c88 100644
|
--- a/tests/mysql_client_test.c
|
+++ b/tests/mysql_client_test.c
|
@@ -3842,7 +3842,7 @@ static void test_bind_result_ext1()
|
short i_data;
|
uchar b_data;
|
int f_data;
|
- long bData;
|
+ int bData;
|
char d_data[20];
|
double szData;
|
MYSQL_BIND my_bind[8];
|
@@ -3938,7 +3938,7 @@ static void test_bind_result_ext1()
|
fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]);
|
fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]);
|
|
- fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]);
|
+ fprintf(stdout, "\n data (bin) : %d(%lu)", bData, length[6]);
|
fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]);
|
}
|
|
The other error related to foreign keys is a bogus one:
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
|
--- a/storage/innobase/handler/ha_innodb.cc
|
+++ b/storage/innobase/handler/ha_innodb.cc
|
@@ -12108,7 +12108,7 @@ create_table_info_t::create_foreign_keys()
|
dict_index_t* index = NULL;
|
fkerr_t index_error = FK_SUCCESS;
|
dict_index_t* err_index = NULL;
|
- ulint err_col;
|
+ ulint err_col = 0;
|
const bool tmp_table = m_flags2 & DICT_TF2_TEMPORARY;
|
const CHARSET_INFO* cs = thd_charset(m_thd);
|
const char* operation = "Create "; |
If dict_foreign_find_index() yields FK_INDEX_NOT_FOUND, the value of err_col will remain uninitialized, but it would not be used by foreign_push_index_error() either. MemorySanitizer starting with clang-16 does not allow uninitialized data to be passed by value or to be returned. A similar fix is needed for the test main.debug_sync when it is trying to report Missing synchronization point name:
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
|
index eec95bee1f2..160851ae004 100644
|
--- a/sql/debug_sync.cc
|
+++ b/sql/debug_sync.cc
|
@@ -1008,7 +1008,7 @@ static bool debug_sync_eval_action(THD *thd, char *action_str, char *action_end)
|
st_debug_sync_action *action= NULL;
|
const char *errmsg;
|
char *ptr;
|
- char *token;
|
+ char *token= nullptr;
|
uint token_length= 0;
|
DBUG_ENTER("debug_sync_eval_action");
|
DBUG_ASSERT(thd); |
Another one is main.fulltext; for delimiters the w would not be initialized:
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
|
index f69f1869383..3d95fffacaf 100644
|
--- a/storage/myisam/ft_boolean_search.c
|
+++ b/storage/myisam/ft_boolean_search.c
|
@@ -287,6 +287,8 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param,
|
uchar *end= (uchar*) query + len;
|
FT_WORD w;
|
|
+ w.pos= NULL;
|
+ w.len= 0;
|
info.prev= ' ';
|
info.quot= 0;
|
while (ft_get_word(cs, start, end, &w, &info)) |
The test innodb.page_compressed,lz4 fails because I do not have an instrumented lz4 compression library.
The test handler.heap and about 10 other tests are fixed by the following:
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
|
index b6d91896142..3ab50d4aaa8 100644
|
--- a/sql/sql_lex.h
|
+++ b/sql/sql_lex.h
|
@@ -3260,7 +3260,7 @@ struct LEX: public Query_tables_list
|
Table_type table_type; /* Used for SHOW CREATE */
|
List<Key_part_spec> ref_list;
|
List<LEX_USER> users_list;
|
- List<Item> *insert_list,field_list,value_list,update_list;
|
+ List<Item> *insert_list= nullptr,field_list,value_list,update_list;
|
List<List_item> many_values;
|
List<set_var_base> var_list;
|
List<set_var_base> stmt_var_list; //SET_STATEMENT values |
The test main.subselect4 and 31 other tests are fixed by the following:
diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h
|
index 57cfd21727f..d0fdb5a2c87 100644
|
--- a/sql/multi_range_read.h
|
+++ b/sql/multi_range_read.h
|
@@ -581,7 +581,7 @@ class DsMrr_impl
|
int dsmrr_explain_info(uint mrr_mode, char *str, size_t size);
|
private:
|
/* Buffer to store (key, range_id) pairs */
|
- Lifo_buffer *key_buffer;
|
+ Lifo_buffer *key_buffer= nullptr;
|
|
/*
|
The "owner" handler object (the one that is expected to "own" this object |
The function DsMrr_impl::dsmrr_init() would read a garbage key_buffer. This affects at least MyISAM, InnoDB and Aria.
The test main.mysql-interactive appears to fail because I do not have an instrumented ncurses library. The memory was marked uninitialized at allocation and the uninitialized use flagged in add_to_blob() a little later by __interceptor_strlen().
#3 0x000055c0e0cd8162 in __interceptor_malloc ()
|
#4 0x00007f741238d7f9 in _nc_first_db (state=<optimized out>, offset=<optimized out>) at ../../ncurses/tinfo/db_iterator.c:352
|
#5 0x00007f741239b20f in _nc_read_entry2 (name=0x7010000000a0 "dumb", filename=filename@entry=0x7fff875cb5e0 "dumb", tp=tp@entry=0x7160000002b0) at ../../ncurses/tinfo/read_entry.c:902
|
#6 0x00007f74123905b6 in _nc_setup_tinfo (tn=<optimized out>, tp=0x7160000002b0) at ../../ncurses/tinfo/lib_setup.c:626
|
#7 0x00007f7412390996 in _nc_setupterm (tname=<optimized out>, Filedes=1, errret=0x7fff875cc674, reuse=<optimized out>) at ../../ncurses/tinfo/lib_setup.c:916
|
#8 0x000055c0e0d3391d in put_info (str=0x55c0e09c4c74 "Welcome to the MariaDB monitor. Commands end with ; or \\g.", info_type=info_type@entry=INFO_INFO, error=error@entry=0, sqlstate=sqlstate@entry=0x0)
|
at /mariadb/10.5/client/mysql.cc:5092
|
#9 0x000055c0e0d3294c in main (argc=9, argv=0x70d000000070) at /mariadb/10.5/client/mysql.cc:1229
|
This test was recently added for MDEV-14448. I think that we can skip it on MSAN.
On merge to 10.6, there were no additonal failures. Hopefully it will stay like that when merging to further later-version branches.
I believe the fix provided for multi_range_read.h is legitimate, and here is why. So, we had this MSAN warning:
==243288==WARNING: MemorySanitizer: use-of-uninitialized-value
|
#0 0x5577ba464d89 in DsMrr_impl::dsmrr_init(handler*, st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*) /home/oleg/server/sql/multi_range_read.cc:1208:31
|
#1 0x5577bbd61bd2 in ha_myisam::multi_range_read_init(st_range_seq_if*, void*, unsigned int, unsigned int, st_handler_buffer*) /home/oleg/server/storage/myisam/ha_myisam.cc:2639:17
|
#2 0x5577bac5ab4b in QUICK_RANGE_SELECT::reset() /home/oleg/server/sql/opt_range.cc:12703:16
|
#3 0x5577ba084442 in join_init_read_record(st_join_table*) /home/oleg/server/sql/sql_select.cc:22170:64
|
#4 0x5577ba0efae8 in sub_select(JOIN*, st_join_table*, bool) /home/oleg/server/sql/sql_select.cc:21219:12
|
#5 0x5577ba08e802 in do_select(JOIN*, Procedure*) /home/oleg/server/sql/sql_select.cc:20739:14
|
#6 0x5577ba08ba6e in JOIN::exec_inner() /home/oleg/server/sql/sql_select.cc:4625:50
|
#7 0x5577ba0895fa in JOIN::exec() /home/oleg/server/sql/sql_select.cc:4405:3
|
#8 0x5577ba0166ec in mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) /home/oleg/server/sql/sql_select.cc:4882:9
|
#9 0x5577ba015f18 in handle_select(THD*, LEX*, select_result*, unsigned long) /home/oleg/server/sql/sql_select.cc:449:10
|
We had an uninitialized key_buffer passed to the init() method:
multi_range_read.cc |
if ((res= index_strategy->init(secondary_file, seq_funcs, seq_init_param,
|
n_ranges, mode, &keypar, key_buffer,
|
&buf_manager)) ||
|
(res= disk_strategy->init(primary_file, index_strategy, mode,
|
&rowid_buffer, rowid_filter)))
|
init() is a pure virtual method that is overriden in Mrr_simple_index_reader and Mrr_ordered_index_reader classes. However, in the case of Mrr_simple_index_reader the parameter key_buffer is not used, so it is just passed to the method according to the calling convention. And in the case of Mrr_ordered_index_reader the key_buffer is used, and it is always initialized before the init() call (at least in all cases covered by the test suite). I couldn't come up with a case when an uninitialized key_buffer might have been passed to the method.
So initializing key_buffer to nullptr as this is done at
commit 09d991d01c47e22030879e5bf0c7a4893a598199
|
Author: Marko Mäkelä <marko.makela@mariadb.com>
|
Date: Mon Mar 18 16:01:29 2024 +0200
|
is valid to silence the memory sanitizer warnings.
For some reason, I can reproduce this with clang 16.0.6 and clang 17.0.6 but not with clang 15.0.7. (See
MDEV-20377for build instructions.)