From c1559f261f2e7a95b035e2be8510e4ef47c6cd23 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 20 Jan 2025 19:53:25 +0400 Subject: [PATCH] MDEV-35688 UBSAN: SUMMARY: UndefinedBehaviorSanitizer: nullptr-with-offset in my_casedn_utf8mb3 The functions MY_CHARSET_HANDLER::caseup() and MY_CHARSET_HANDLER::casedn() in their virtual imlementations do "const char *end= src + srclen" in the very beginning. Therefore src cannot be NULL to avoid "UBSAN: SUMMARY: UndefinedBehaviorSanitizer: nullptr-with-offset". Adding DBUG_ASSERT(src != NULL) into all virtual implementations, to catch this problem in regular Debug builds (without UBSAN). Fixing Master_info_index::get_master_info() to check connection_name->str. If it is NULL then passing empty_clex_str into IdentBufferCasedn instead of *connection_name. --- mysql-test/suite/sys_vars/r/replicate_do_db_basic.result | 6 ++++++ mysql-test/suite/sys_vars/t/replicate_do_db_basic.test | 6 ++++++ sql/rpl_mi.cc | 4 +++- strings/ctype-mb.c | 2 ++ strings/ctype-simple.c | 2 ++ strings/ctype-ucs2.c | 6 ++++++ strings/ctype-ujis.c | 2 ++ strings/ctype-utf8.c | 4 ++++ 8 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result index 54adf835962..441291401bc 100644 --- a/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result +++ b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result @@ -43,3 +43,9 @@ SELECT @@GLOBAL.replicate_do_db; # Cleanup. SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; +# +# MDEV-35688 UBSAN: SUMMARY: UndefinedBehaviorSanitizer: nullptr-with-offset in my_casedn_utf8mb3 +# +show variables like 'replicate_do_db'; +Variable_name Value +replicate_do_db diff --git a/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test index b7004d1938b..5f2074b9c67 100644 --- a/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test +++ b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test @@ -43,3 +43,9 @@ SELECT @@GLOBAL.replicate_do_db; --echo # Cleanup. SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; + +--echo # +--echo # MDEV-35688 UBSAN: SUMMARY: UndefinedBehaviorSanitizer: nullptr-with-offset in my_casedn_utf8mb3 +--echo # + +show variables like 'replicate_do_db'; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index a61df1ea11c..7d8b70d5f8e 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1374,7 +1374,9 @@ Master_info_index::get_master_info(const LEX_CSTRING *connection_name, connection_name->str)); /* Make name lower case for comparison */ - IdentBufferCasedn buff(*connection_name); + IdentBufferCasedn buff(connection_name->str ? + *connection_name : + empty_clex_str); mi= (Master_info*) my_hash_search(&master_info_hash, (const uchar*) buff.ptr(), buff.length()); if (!mi && warning != Sql_condition::WARN_LEVEL_NOTE) diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 88dd36312ea..404d1c7cd47 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -125,6 +125,7 @@ size_t my_casedn_mb(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(dstlen >= srclen * cs->cset->casedn_multiply(cs)); DBUG_ASSERT(src != dst || cs->cset->casedn_multiply(cs) == 1); return my_casefold_mb(cs, src, srclen, dst, dstlen, cs->to_lower, 0); @@ -135,6 +136,7 @@ size_t my_caseup_mb(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(dstlen >= srclen * cs->cset->caseup_multiply(cs)); DBUG_ASSERT(src != dst || cs->cset->caseup_multiply(cs) == 1); return my_casefold_mb(cs, src, srclen, dst, dstlen, cs->to_upper, 1); diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 1fb8e9c91bb..193d453bd36 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -253,6 +253,7 @@ size_t my_caseup_8bit(CHARSET_INFO * cs, const char *src, size_t srclen, { const char *end= src + srclen; register const uchar *map= cs->to_upper; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); for ( ; src != end ; src++) *dst++= (char) map[(uchar) *src]; @@ -265,6 +266,7 @@ size_t my_casedn_8bit(CHARSET_INFO * cs, const char *src, size_t srclen, { const char *end= src + srclen; register const uchar *map=cs->to_lower; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); for ( ; src != end ; src++) *dst++= (char) map[(uchar) *src]; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 8d275c18bd7..9675731018e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1310,6 +1310,7 @@ my_caseup_utf16(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && @@ -1368,6 +1369,7 @@ my_casedn_utf16(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && @@ -2180,6 +2182,7 @@ my_caseup_utf32(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && @@ -2237,6 +2240,7 @@ my_casedn_utf32(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); while ((res= my_utf32_uni(cs, &wc, (uchar*) src, (uchar*) srcend)) > 0) @@ -3048,6 +3052,7 @@ static size_t my_caseup_ucs2(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(srclen <= dstlen); while ((src < srcend) && @@ -3100,6 +3105,7 @@ static size_t my_casedn_ucs2(CHARSET_INFO *cs, const char *src, size_t srclen, char *dstend= dst + dstlen; MY_CASEFOLD_INFO *uni_plane= cs->casefold; DBUG_ASSERT(srclen <= dstlen); + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ while ((src < srcend) && (res= my_ucs2_uni(cs, &wc, (uchar*) src, (uchar*) srcend)) > 0) diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index a5624a8c341..28bd11c1531 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -67219,6 +67219,7 @@ size_t my_casedn_ujis(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(dstlen >= srclen * cs->cset->casedn_multiply(cs)); DBUG_ASSERT(src != dst || cs->cset->casedn_multiply(cs) == 1); return my_casefold_ujis(cs, src, srclen, dst, dstlen, cs->to_lower, 0); @@ -67232,6 +67233,7 @@ size_t my_caseup_ujis(CHARSET_INFO * cs, const char *src, size_t srclen, char *dst, size_t dstlen) { + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(dstlen >= srclen * cs->cset->caseup_multiply(cs)); DBUG_ASSERT(src != dst || cs->cset->caseup_multiply(cs) == 1); return my_casefold_ujis(cs, src, srclen, dst, dstlen, cs->to_upper, 1); diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b7bdd0e98b0..673ed0839f6 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -676,6 +676,7 @@ static size_t my_caseup_utf8mb3(CHARSET_INFO *cs, const char *srcend= src + srclen; char *dstend= dst + dstlen, *dst0= dst; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(src != dst || cs->cset->caseup_multiply(cs) == 1); while ((src < srcend) && @@ -754,6 +755,7 @@ static size_t my_casedn_utf8mb3(CHARSET_INFO *cs, const char *srcend= src + srclen; char *dstend= dst + dstlen, *dst0= dst; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(src != dst || cs->cset->casedn_multiply(cs) == 1); while ((src < srcend) && @@ -3124,6 +3126,7 @@ my_caseup_utf8mb4(CHARSET_INFO *cs, const char *src, size_t srclen, const char *srcend= src + srclen; char *dstend= dst + dstlen, *dst0= dst; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(src != dst || cs->cset->caseup_multiply(cs) == 1); while ((src < srcend) && @@ -3218,6 +3221,7 @@ my_casedn_utf8mb4(CHARSET_INFO *cs, const char *srcend= src + srclen; char *dstend= dst + dstlen, *dst0= dst; MY_CASEFOLD_INFO *uni_plane= cs->casefold; + DBUG_ASSERT(src != NULL); /* Avoid UBSAN nullptr-with-offset */ DBUG_ASSERT(src != dst || cs->cset->casedn_multiply(cs) == 1); while ((src < srcend) &&