diff --git a/include/errmsg.h b/include/errmsg.h index 0e6d24e0..26743ff1 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -116,10 +116,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define CR_BINLOG_SEMI_SYNC_ERROR 5023 #define CR_INVALID_CLIENT_FLAG 5024 #define CR_STMT_NO_RESULT 5025 +#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_STMT_NO_RESULT +#define CR_MARIADB_LAST_ERROR CR_ERR_MISSING_ERROR_INFO #endif @@ -128,6 +129,6 @@ extern const char *mariadb_client_errors[]; /* Error messages */ #define ER(code) IS_MYSQL_ERROR((code)) ? client_errors[(code) - CR_MIN_ERROR] : \ IS_MARIADB_ERROR((code)) ? mariadb_client_errors[(code) - CER_MIN_ERROR] : \ - "Unknown or undefined error code" + "Unknown or undefined error code" #define CER(code) ER((code)) 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__) diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 1985b44f..69e8683c 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() diff --git a/libmariadb/ma_context.c b/libmariadb/ma_context.c index f9431d04..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]); @@ -204,7 +205,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 +441,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 +676,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 diff --git a/libmariadb/ma_errmsg.c b/libmariadb/ma_errmsg.c index 53890f87..a5b528c1 100644 --- a/libmariadb/ma_errmsg.c +++ b/libmariadb/ma_errmsg.c @@ -120,6 +120,7 @@ const char *mariadb_client_errors[] = /* 5023 */ "Semi sync request error: %s", /* 5024 */ "Invalid client flags (%lu) specified. Supported flags: %lu", /* 5025 */ "Statement has no result set", + /* 5026 */ "Server returned an error packet without further information", "" }; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index aaaf5576..dcd409a7 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -80,7 +80,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 @@ -273,6 +273,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}, diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index 374f2300..09d53e57 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);