diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bcdf49b..fffad5b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,20 @@ ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON) ADD_OPTION(DEFAULT_SSL_VERIFY_SERVER_CERT "Default value for MYSQL_OPT_SSL_VERIFY_SERVER_CERT" 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/include/mariadb_com.h b/include/mariadb_com.h index dc429527..8e89c24c 100644 --- a/include/mariadb_com.h +++ b/include/mariadb_com.h @@ -52,6 +52,8 @@ #define MYSQL_AUTODETECT_CHARSET_NAME "auto" #define BINCMP_FLAG 131072 +enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT,ROW_RESULT,DECIMAL_RESULT}; + enum mysql_enum_shutdown_level { SHUTDOWN_DEFAULT = 0, diff --git a/include/mariadb_rpl.h b/include/mariadb_rpl.h index 0d0adf41..f12fdfa1 100644 --- a/include/mariadb_rpl.h +++ b/include/mariadb_rpl.h @@ -73,8 +73,6 @@ extern "C" { #define SEMI_SYNC_INDICATOR 0xEF #define SEMI_SYNC_ACK_REQ 0x01 -enum Item_result {STRING_RESULT,REAL_RESULT,INT_RESULT,ROW_RESULT,DECIMAL_RESULT}; - /* Options */ enum mariadb_rpl_option { MARIADB_RPL_FILENAME, /* Filename and length */ diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 26f00f87..4db33898 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -398,6 +398,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 */ @@ -1054,6 +1063,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, @@ -1070,21 +1108,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/travis.sh b/travis.sh index 0d633849..f90e2599 100755 --- a/travis.sh +++ b/travis.sh @@ -32,6 +32,22 @@ if [ -n "$server_branch" ] ; then # build latest server with latest C/C as libmariadb # skip to build some storage engines to speed up the build + if [ -n "$TRAVIS_PULL_REQUEST" ] && [ "$TRAVIS_PULL_REQUEST" != "false" ] ; then + git submodule update --init --remote libmariadb + cd libmariadb + git fetch origin ${TRAVIS_PULL_REQUEST} + git checkout -qf FETCH_HEAD + else + git submodule set-branch -b ${TRAVIS_BRANCH} libmariadb + git submodule sync + git submodule update --init --remote libmariadb + cd libmariadb + git checkout ${TRAVIS_COMMIT} + fi + + cd $SERVER_DIR + git add libmariadb + mkdir bld cd bld cmake .. -DPLUGIN_MROONGA=NO -DPLUGIN_ROCKSDB=NO -DPLUGIN_SPIDER=NO -DPLUGIN_TOKUDB=NO @@ -43,10 +59,6 @@ if [ -n "$server_branch" ] ; then echo "checkout commit" fi - cp $CC_DIR/* $SERVER_DIR/libmariadb -r - cd $SERVER_DIR - git add libmariadb - cd $SERVER_DIR/bld make -j9 @@ -69,12 +81,11 @@ else echo "build from windows" export MARIADB_CC_TEST=1 export MYSQL_TEST_DB=testc - export MYSQL_TEST_TLS=%TEST_REQUIRE_TLS% - export MYSQL_TEST_USER=%TEST_DB_USER% - export MYSQL_TEST_HOST=%TEST_DB_HOST% - export MYSQL_TEST_PASSWD=%TEST_DB_PASSWORD% - export MYSQL_TEST_PORT=%TEST_DB_PORT% - export MYSQL_TEST_TLS=%TEST_REQUIRE_TLS% + export MYSQL_TEST_TLS=$TEST_REQUIRE_TLS + export MYSQL_TEST_USER=$TEST_DB_USER + export MYSQL_TEST_HOST=$TEST_DB_HOST + export MYSQL_TEST_PASSWD=$TEST_DB_PASSWORD + export MYSQL_TEST_PORT=$TEST_DB_PORT cmake --build . --config RelWithDebInfo else echo "build from linux" diff --git a/unittest/libmariadb/CMakeLists.txt b/unittest/libmariadb/CMakeLists.txt index 1fc8affa..d668c360 100644 --- a/unittest/libmariadb/CMakeLists.txt +++ b/unittest/libmariadb/CMakeLists.txt @@ -34,8 +34,12 @@ INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include ${CC_SOURCE_DIR}/unittest/libmariadb) ADD_DEFINITIONS(-DLIBMARIADB) - SET(API_TESTS "bulk1" "performance" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "thread" "features-10_2") + +IF($ENV{TRAVIS}) + ADD_DEFINITIONS("-DHAVE_TRAVIS=1") +ENDIF() + IF(WITH_DYNCOL) SET(API_TESTS ${API_TESTS} "dyncol") ENDIF() diff --git a/unittest/libmariadb/charset.c b/unittest/libmariadb/charset.c index ec98ddd6..3f191abc 100644 --- a/unittest/libmariadb/charset.c +++ b/unittest/libmariadb/charset.c @@ -547,6 +547,11 @@ static int test_bug30472(MYSQL *mysql) diag("Test requires MySQL Server version 5.1 or above"); return SKIP; } + if (mariadb_connection(mysql) && mysql_get_server_version(mysql) >= 110400) + { + diag("C/C 3.3 doesn't support all collations from 11.4 and above"); + return SKIP; + } /* Retrieve character set information. */ mysql_set_character_set(mysql, "latin1"); @@ -804,6 +809,12 @@ static int test_conc223(MYSQL *mysql) SKIP_MYSQL(mysql); + if (mariadb_connection(mysql) && mysql_get_server_version(mysql) >= 110400) + { + diag("C/C 3.3 doesn't support all collations from 11.4 and above"); + 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 dfced930..b72563d0 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -27,14 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "my_test.h" - -static int kill_conn(MYSQL *mysql, unsigned long thread_id) -{ - char query[128]; - sprintf(query, "KILL %ld", thread_id); - return mysql_query(mysql, query); -} - static int test_conc66(MYSQL *my) { MYSQL *mysql= mysql_init(NULL); @@ -2425,6 +2417,8 @@ static int test_conc748(MYSQL *my __attribute__((unused))) int i; const char *ciphers[3]= {"TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256"}; + SKIP_MAXSCALE; + for (i=0; i < 3; i++) { const char *tls_version; @@ -2455,12 +2449,13 @@ static int test_conc589(MYSQL *my) MYSQL *mysql= mysql_init(NULL); MYSQL_RES *result; int rc; - my_bool reconnect= 1; - my_bool no= 0; + my_bool reconnect= 1, verify= 0; unsigned long last_thread_id= 0; - mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &no); + SKIP_MAXSCALE; + 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, 0)) @@ -2469,32 +2464,30 @@ static int test_conc589(MYSQL *my) return FAIL; } - FAIL_IF(mysql_thread_id(mysql) == last_thread_id, "Expected new connection id"); + 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); - rc= kill_conn(my, last_thread_id); - check_mysql_rc(rc, my); - if ((rc= mysql_query(mysql, "SELECT 1")) || (result= mysql_store_result(mysql)) == NULL) + 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); - rc= kill_conn(my, last_thread_id); - check_mysql_rc(rc, my); - if ((rc= mysql_query(mysql, "SELECT 1")) || (result= mysql_store_result(mysql)) == NULL) + + 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"); - last_thread_id= mysql_thread_id(mysql); - rc= kill_conn(my, last_thread_id); - check_mysql_rc(rc, my); - if ((rc= mysql_query(mysql, "SELECT 1")) || (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_close(mysql); return OK; } diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 5a947dc2..2f262563 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -1544,7 +1544,10 @@ static int test_conc163(MYSQL *mysql) FAIL_IF(mysql_info(mysql) != NULL, "mysql_info: expected NULL"); - rc= mysql_query(mysql, "CREATE OR REPLACE TABLE t1 AS SELECT 1"); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 AS SELECT 1"); check_mysql_rc(rc, mysql); FAIL_IF(mysql_info(mysql) == NULL, "mysql_info: expected != NULL"); @@ -1557,7 +1560,9 @@ static int test_conc163(MYSQL *mysql) check_stmt_rc(rc, stmt); FAIL_IF(mysql_info(mysql) != NULL, "mysql_info: expected NULL"); - rc= mariadb_stmt_execute_direct(stmt, SL("CREATE OR REPLACE TABLE t1 AS SELECT 1")); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mariadb_stmt_execute_direct(stmt, SL("CREATE TABLE t1 AS SELECT 1")); check_stmt_rc(rc, stmt); FAIL_IF(mysql_info(mysql) == NULL, "mysql_info: expected != NULL"); diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index 9bbba0d4..b71231b8 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -577,6 +577,15 @@ static int reset_connection(MYSQL *mysql) { return OK; } +static char *check_envvar(const char *envvar) +{ + char *p = getenv(envvar); + + if (p && p[0]) + return p; + return NULL; +} + /* * function get_envvars(( * @@ -595,51 +604,44 @@ void get_envvars() { if (getenv("TRAVIS_JOB_ID")) travis_test= 1; - if (!hostname && (envvar= getenv("MYSQL_TEST_HOST"))) - hostname= envvar; + if (!hostname) + hostname= check_envvar("MYSQL_TEST_HOST"); + if (!username && !(username= check_envvar("MYSQL_TEST_USER"))) + username= (char *)"root"; - if (!username) - { - if ((envvar= getenv("MYSQL_TEST_USER"))) - username= envvar; - else - username= (char *)"root"; - } - if (!password && (envvar= getenv("MYSQL_TEST_PASSWD"))) - password= envvar; - if (!schema && (envvar= getenv("MYSQL_TEST_DB"))) - schema= envvar; - if (!schema) + if (!password) + password= check_envvar("MYSQL_TEST_PASSWD"); + + if (!schema && !(schema= check_envvar("MYSQL_TEST_DB"))) schema= "test"; + if (!port) { - if ((envvar= getenv("MYSQL_TEST_PORT"))) + if ((envvar= check_envvar("MYSQL_TEST_PORT")) || + (envvar= check_envvar("MASTER_MYPORT"))) port= atoi(envvar); - else if ((envvar= getenv("MASTER_MYPORT"))) - port= atoi(envvar); - diag("port: %d", port); } if (!ssl_port) { - if ((envvar= getenv("MYSQL_TEST_SSL_PORT"))) + if ((envvar= check_envvar("MYSQL_TEST_SSL_PORT"))) ssl_port= atoi(envvar); else ssl_port = port; diag("ssl_port: %d", ssl_port); } - if (!force_tls && (envvar= getenv("MYSQL_TEST_TLS"))) + if (!force_tls && (envvar= check_envvar("MYSQL_TEST_TLS"))) force_tls= atoi(envvar); + if (!socketname) { - if ((envvar= getenv("MYSQL_TEST_SOCKET"))) - socketname= envvar; - else if ((envvar= getenv("MASTER_MYSOCK"))) + if ((envvar= check_envvar("MYSQL_TEST_SOCKET")) || + (envvar= check_envvar("MASTER_MYSOCK"))) socketname= envvar; diag("socketname: %s", socketname); } - if ((envvar= getenv("MYSQL_TEST_PLUGINDIR"))) + if ((envvar= check_envvar("MYSQL_TEST_PLUGINDIR"))) plugindir= envvar; if (IS_XPAND())