From 003ea7e9de5b1db30c48363a964ae1fdee54a481 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 5 Feb 2025 11:56:35 +0100 Subject: [PATCH 1/7] CONC-753: Compile error on .cfi_escape in builds with no unwind/cfi Also CONC-754. Depending on compiler options (eg. -fno-dwarf2-cfi-asm), the compiler may not output .cfi_startproc / .cfi_endproc in generated assember, and this causes a build error on the .cfi_escape directive put in my_context_spawn() on systems with DWARF support. Fix by using the proper preprocessor macro __GCC_HAVE_DWARF2_CFI_ASM to test for .cfi_escape support, rather than crafted check for various compiler brands and versions. Though this macro is only available in clang since version 13.0.0, so unconditionally include the .cfi_escape in earlier clang versions. Thanks to Rainer Orth for the suggested fix. Signed-off-by: Kristian Nielsen --- libmariadb/ma_context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c index f9431d04..4063bebd 100644 --- a/libmariadb/ma_context.c +++ b/libmariadb/ma_context.c @@ -204,7 +204,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) ( "movq %%rsp, (%[save])\n\t" "movq %[stack], %%rsp\n\t" -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __clang__) && !defined(__INTEL_COMPILER) +#if defined(__GCC_HAVE_DWARF2_CFI_ASM) || (defined(__clang__) && __clang_major__ < 13) /* This emits a DWARF DW_CFA_undefined directive to make the return address undefined. This indicates that this is the top of the stack frame, and @@ -440,7 +440,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) ( "movl %%esp, (%[save])\n\t" "movl %[stack], %%esp\n\t" -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __clang__) && !defined(__INTEL_COMPILER) +#if defined(__GCC_HAVE_DWARF2_CFI_ASM) || (defined(__clang__) && __clang_major__ < 13) /* This emits a DWARF DW_CFA_undefined directive to make the return address undefined. This indicates that this is the top of the stack frame, and @@ -675,7 +675,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) ( "mov x10, sp\n\t" "mov sp, %[stack]\n\t" -#if !defined(__INTEL_COMPILER) +#if defined(__GCC_HAVE_DWARF2_CFI_ASM) || (defined(__clang__) && __clang_major__ < 13) /* This emits a DWARF DW_CFA_undefined directive to make the return address (UNW_AARCH64_X30) undefined. This indicates that this is the top of the From 879fcab625709e81b19d5115e0b0c8de2d94f5c4 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 5 Feb 2025 13:26:43 +0100 Subject: [PATCH 2/7] Remove obsolete reference to my_context.c which was renamed to ma_context.c Signed-off-by: Kristian Nielsen --- libmariadb/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 67c803c2..9c632099 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -168,12 +168,6 @@ SET(MYSQL_LIB_SYMBOLS mysql_use_result mysql_warning_count) -# some gcc versions fail to compile asm parts of my_context.c, -# if build type is "Release" (see CONC-133), so we need to add -g flag -IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_BUILD_TYPE MATCHES "Release") - SET_SOURCE_FILES_PROPERTIES(my_context.c PROPERTIES COMPILE_FLAGS -g) -ENDIF() - IF(ZLIB_FOUND AND WITH_EXTERNAL_ZLIB) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) ELSE() From fc49fa706d6918de32a44ad4657a56c864a07dde Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 5 Feb 2025 16:07:25 +0100 Subject: [PATCH 3/7] CONC-618: Please annotate swapcontext for ASAN When compiling for AddressSanitizer, prefer the system ucontext or boost::context co-routine libraries over our custom assembler routines. The custom routines are not easily annotated with the required AddressSanitizer __sanitizer_{start,finish}_switch_fiber() functions, while the system routines should already be so annotated. Signed-off-by: Kristian Nielsen --- include/ma_context.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/ma_context.h b/include/ma_context.h index 4c3f0d8d..966fd0cd 100644 --- a/include/ma_context.h +++ b/include/ma_context.h @@ -26,8 +26,33 @@ (This particular implementation uses Posix ucontext swapcontext().) */ + +/* + When running with address sanitizer, the stack switching can cause confusion + unless the __sanitizer_{start,finish}_switch_fiber() functions are used + (CONC-618). + + In this case prefer the use of boost::context or ucontext, which should have + this instrumentation, over our custom assembler variants. +*/ +#ifdef __has_feature + /* Clang */ +# if __has_feature(address_sanitizer) +# define ASAN_PREFER_NON_ASM 1 +# endif +#else + /* GCC */ +# ifdef __SANITIZE_ADDRESS__ +# define ASAN_PREFER_NON_ASM 1 +# endif +#endif + #ifdef _WIN32 #define MY_CONTEXT_USE_WIN32_FIBERS 1 +#elif defined(ASAN_PREFER_NON_ASM) && defined(HAVE_BOOST_CONTEXT_H) +#define MY_CONTEXT_USE_BOOST_CONTEXT +#elif defined(ASAN_PREFER_NON_ASM) && defined(HAVE_UCONTEXT_H) +#define MY_CONTEXT_USE_UCONTEXT #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__x86_64__) && !defined(__ILP32__) #define MY_CONTEXT_USE_X86_64_GCC_ASM #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) From 77754f4d877af40c589670033c3f4c4713f3eb34 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 5 Feb 2025 16:57:31 +0100 Subject: [PATCH 4/7] CONC-725: Fix compiler warning about uninitialized union member Signed-off-by: Kristian Nielsen --- libmariadb/ma_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c index 4063bebd..224783b2 100644 --- a/libmariadb/ma_context.c +++ b/libmariadb/ma_context.c @@ -105,6 +105,7 @@ my_context_spawn(struct my_context *c, void (*f)(void *), void *d) c->user_func= f; c->user_data= d; c->active= 1; + u.a[1]= 0; /* Otherwise can give uninitialized warnings on 32-bit. */ u.p= c; makecontext(&c->spawned_context, (uc_func_t)my_context_spawn_internal, 2, u.a[0], u.a[1]); From 2381127b1178c56a4ece68f07b5ceba3cb73de56 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Thu, 6 Feb 2025 00:24:28 +0100 Subject: [PATCH 5/7] CONC-473: mysql_real_connect_start() stack overrun with mdns hostname Increase the default stack size for co-routines to 256 kByte. It was 60 kByte, which was too small for glibc getaddrinfo() when using mdns. Signed-off-by: Kristian Nielsen --- libmariadb/mariadb_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index a028c321..f1053dd3 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -81,7 +81,7 @@ #define strncasecmp _strnicmp #endif -#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15) +#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (256*1024) #define MA_RPL_VERSION_HACK "5.5.5-" #define CHARSET_NAME_LEN 64 From 28ae227e801fd9ad5f5589658dad872060854a9b Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 11 Feb 2025 10:50:40 +0100 Subject: [PATCH 6/7] CONC-755: Fix MSAN failure Fixed uninitialized variable warning by initializing MYSQL_BIND structure. --- unittest/libmariadb/ps_bugs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index 3a3c35d3..3109b141 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -5027,11 +5027,14 @@ static int test_conc_fraction(MYSQL *mysql) diag("second_part: %ld", tm.second_part); - expected= i > 6 ? 123456 : frac * (unsigned int)powl(10, (6 - i)); + expected= frac * 100000; + while (expected >= 1000000) + expected /= 10; if (tm.second_part != expected) { diag("Error: tm.second_part=%ld expected=%ld", tm.second_part, expected); + mysql_stmt_close(stmt); return FAIL; } } @@ -5618,6 +5621,7 @@ static int test_conc623(MYSQL *mysql) rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_PARAM, conc623_param_callback); check_stmt_rc(rc, stmt); + memset(&bind, 0, sizeof(MYSQL_BIND)); bind.buffer_type= MYSQL_TYPE_LONG; rc= mysql_stmt_bind_param(stmt, &bind); check_stmt_rc(rc, stmt); From 4877093937c7d1a7e1a7ba3e20a9263414fd1428 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Tue, 11 Feb 2025 11:28:56 +0100 Subject: [PATCH 7/7] Workaround for MDEV-35935 If the server returns an error packet without error number (and message) we set errno=CR_ERR_MISSING_ERROR_INFO (5026) --- include/errmsg.h | 3 +- libmariadb/ma_errmsg.c | 2 ++ libmariadb/mariadb_lib.c | 5 +++ unittest/libmariadb/errors.c | 69 ++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/include/errmsg.h b/include/errmsg.h index f22db164..7d63580f 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -115,10 +115,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_BINLOG_INVALID_FILE 5022 #define CR_BINLOG_SEMI_SYNC_ERROR 5023 #define CR_INVALID_CLIENT_FLAG 5024 +#define CR_ERR_MISSING_ERROR_INFO 5026 /* Always last, if you add new error codes please update the value for CR_MARIADB_LAST_ERROR */ -#define CR_MARIADB_LAST_ERROR CR_INVALID_CLIENT_FLAG +#define CR_MARIADB_LAST_ERROR CR_ERR_MISSING_ERROR_INFO #endif diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index 90218573..14e2e3b5 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -119,6 +119,8 @@ const char *mariadb_client_errors[] = /* 5022 */ "File '%s' is not a binary log file", /* 5023 */ "Semi sync request error: %s", /* 5024 */ "Invalid client flags (%lu) specified. Supported flags: %lu", + /* 5025 */ "", + /* 5026 */ "Server returned an error packet without further information", "" }; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index f1053dd3..02d0f872 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -274,6 +274,11 @@ restart: ma_strmake(net->last_error,(char*) pos, min(len,sizeof(net->last_error)-1)); } + /* MDEV-35935: if server sends error packet without error, we have to + set error manually */ + if (!net->last_errno) { + my_set_error(mysql, CR_ERR_MISSING_ERROR_INFO, SQLSTATE_UNKNOWN, 0); + } } else { diff --git a/unittest/libmariadb/errors.c b/unittest/libmariadb/errors.c index b0914782..2f895c9d 100644 --- a/unittest/libmariadb/errors.c +++ b/unittest/libmariadb/errors.c @@ -272,8 +272,77 @@ static int test_parse_error_and_bad_length(MYSQL *mysql) return OK; } +#define TEST_ARRAY_SIZE 1024 + +static int test_mdev35935(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + const char *stmt_str= "INSERT INTO bulk1 (a,b) VALUES (?,?)"; + unsigned int array_size= TEST_ARRAY_SIZE; + int rc; + unsigned int i; + char **buffer; + unsigned long *lengths; + unsigned int *vals; + MYSQL_BIND bind[2]; + const char *data= "test"; + + SKIP_MYSQL(mysql); + + rc= mysql_select_db(mysql, schema); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE bulk1 (a int , b VARCHAR(255))"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + + rc= mysql_query(mysql, "ALTER TABLE bulk1 ADD c int"); + check_mysql_rc(rc, mysql); + + /* allocate memory */ + buffer= calloc(TEST_ARRAY_SIZE, sizeof(char *)); + lengths= calloc(TEST_ARRAY_SIZE, sizeof *lengths); + vals= calloc(TEST_ARRAY_SIZE, sizeof *vals); + + for (i=0; i < TEST_ARRAY_SIZE; i++) + { + buffer[i]= (void *)data; + lengths[i]= -1; + vals[i]= i; + } + + memset(bind, 0, sizeof(MYSQL_BIND) * 2); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= vals; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (void *)buffer; + bind[1].length= (unsigned long *)lengths; + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); + + if ((rc= mysql_stmt_execute(stmt))) + { + FAIL_IF((!mysql_stmt_errno(stmt) || !mysql_errno(mysql)), "Error number > 0 expected"); + } + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); + check_mysql_rc(rc, mysql); + return OK; +} + + struct my_tests_st my_tests[] = { + {"test_mdev35935", test_mdev35935, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_client_warnings", test_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_ps_client_warnings", test_ps_client_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_server_warnings", test_server_warnings, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},