diff --git a/CMakeLists.txt b/CMakeLists.txt index 745114a4..c4d7d5fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,20 @@ ADD_OPTION(WITH_CURL "Enables use of curl" ON) ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON) ############### +if (WITH_ASAN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -static-libasan") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize-recover=all") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-common") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-address-use-after-scope") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=null") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=vptr") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan") +endif() + INCLUDE(${CC_SOURCE_DIR}/cmake/misc.cmake) INCLUDE(FindCURL) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index b63f4164..b0025e8e 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -399,6 +399,15 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg, { NET *net= &mysql->net; int result= -1; + + /* CONC-589: If reconnect option was specified, we have to check if the connection + (socket) is still available */ + if (command != COM_QUIT && mysql->options.reconnect && ma_pvio_is_alive(mysql->net.pvio)) + { + mysql->net.pvio= NULL; + mysql->net.error= 1; + } + if (mysql->net.pvio == 0) { /* Do reconnect if possible */ @@ -1044,6 +1053,35 @@ static size_t rset_field_offsets[]= { OFFSET(MYSQL_FIELD, org_name_length) }; +/* calculate lengths for field metadata: + returns zero on success, 1 if null_length was + detected */ +static my_bool ma_get_rset_field_lengths(MYSQL_ROW row, unsigned int field_count, + unsigned long *lengths) +{ + unsigned long *last_length= 0; + char *pos= 0; + MYSQL_ROW end= row + field_count + 1; + my_bool rc= 0; + + while (row != end) + { + if (*row) + { + if (pos) + *last_length= (ulong)(*row - pos - 1); + pos= *row; + } else { + /* NULL_LENGTH (see also CONC-709) */ + rc= 1; + *last_length= 0; + } + last_length= lengths++; + row++; + } + return rc; +} + MYSQL_FIELD * unpack_fields(const MYSQL *mysql, MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields, @@ -1060,21 +1098,19 @@ unpack_fields(const MYSQL *mysql, for (row=data->data; row ; row = row->next,field++) { + unsigned long lengths[9]; + if (field >= result + fields) goto error; + if (ma_get_rset_field_lengths(row->data, field_count, lengths)) + goto error; + for (i=0; i < field_count; i++) { - uint length; - - if (!row->data[i]) - goto error; - - length= (uint)(row->data[i+1] - row->data[i] - 1); - *(char **)(((char *)field) + rset_field_offsets[i*2])= ma_strdup_root(alloc, (char *)row->data[i]); - *(unsigned int *)(((char *)field) + rset_field_offsets[i*2+1])= length; + *(unsigned int *)(((char *)field) + rset_field_offsets[i*2+1])= lengths[i]; } field->extension= NULL; diff --git a/mariadb_config/mariadb_config.c.in b/mariadb_config/mariadb_config.c.in index 36c01179..d25e0a8d 100644 --- a/mariadb_config/mariadb_config.c.in +++ b/mariadb_config/mariadb_config.c.in @@ -175,7 +175,9 @@ static void mariadb_get_install_location() goto end; else { #if defined(__APPLE__) - unsigned int len= PATH_MAX; + // If reading the path was successful, then *bufsize is + // unchanged. + unsigned int len= PATH_MAX - 1; if (_NSGetExecutablePath(p, &len) != 0) *p= 0; else diff --git a/unittest/libmariadb/charset.c b/unittest/libmariadb/charset.c index db22591d..aa48fc91 100644 --- a/unittest/libmariadb/charset.c +++ b/unittest/libmariadb/charset.c @@ -815,7 +815,6 @@ static int test_conc223(MYSQL *mysql) return SKIP; } - /* Test if we're running against an MDEV-27266 server. It can be detected by the presense of the FULL_COLLATION_NAME diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index ff035f01..f23f2598 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -2366,7 +2366,54 @@ static int test_conc748(MYSQL *my __attribute__((unused))) } #endif +static int test_conc589(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + MYSQL_RES *result; + int rc; + my_bool reconnect= 1, verify= 0; + unsigned long last_thread_id= 0; + + mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); + mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &verify); + + if (!my_test_connect(mysql, hostname, username, + password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS)) + { + diag("error: %s", mysql_error(mysql)); + return FAIL; + } + + rc= mysql_query(mysql, "SET SESSION wait_timeout=5"); + check_mysql_rc(rc, mysql); + + last_thread_id= mysql_thread_id(mysql); + if ((rc= mysql_query(mysql, "SELECT 1")) || (result= mysql_store_result(mysql)) == NULL) + check_mysql_rc(rc, mysql); + + mysql_free_result(result); + sleep(10); + + if ((rc= mysql_query(mysql, "SELECT 2")) || (result= mysql_store_result(mysql)) == NULL) + check_mysql_rc(rc, mysql); + mysql_free_result(result); + FAIL_IF(mysql_thread_id(mysql) == last_thread_id, "Expected new connection id"); + last_thread_id= mysql_thread_id(mysql); + + mysql_kill(my, last_thread_id); + + sleep(10); + + if ((rc= mysql_query(mysql, "SELECT 3")) || (result= mysql_store_result(mysql)) == NULL) + check_mysql_rc(rc, mysql); + mysql_free_result(result); + FAIL_IF(mysql_thread_id(mysql) == last_thread_id, "Expected new connection id"); + mysql_close(mysql); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc589", test_conc589, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) {"test_conc748", test_conc748, TEST_CONNECTION_NONE, 0, NULL, NULL}, #endif