diff --git a/include/ma_common.h b/include/ma_common.h index a05ecf2b..5bfdb7ad 100644 --- a/include/ma_common.h +++ b/include/ma_common.h @@ -79,6 +79,7 @@ struct st_mysql_options_extension { char *proxy_header; size_t proxy_header_len; int (*io_wait)(my_socket handle, my_bool is_read, int timeout); + my_bool skip_read_response; }; typedef struct st_connection_handler diff --git a/include/mysql.h b/include/mysql.h index 34f09858..ccd1149c 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -246,7 +246,8 @@ extern const char *SQLSTATE_UNKNOWN; MARIADB_OPT_MULTI_STATEMENTS, MARIADB_OPT_INTERACTIVE, MARIADB_OPT_PROXY_HEADER, - MARIADB_OPT_IO_WAIT + MARIADB_OPT_IO_WAIT, + MARIADB_OPT_SKIP_READ_RESPONSE }; enum mariadb_value { @@ -872,6 +873,7 @@ struct st_mariadb_methods { void (*set_error)(MYSQL *mysql, unsigned int error_nr, const char *sqlstate, const char *format, ...); void (*invalidate_stmts)(MYSQL *mysql, const char *function_name); struct st_mariadb_api *api; + int (*db_read_execute_response)(MYSQL_STMT *stmt); }; /* synonyms/aliases functions */ diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 4b4e97bb..3fb9d0b2 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -112,6 +112,7 @@ extern my_bool mthd_supported_buffer_type(enum enum_field_types type); extern my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt); extern my_bool mthd_stmt_get_param_metadata(MYSQL_STMT *stmt); extern my_bool mthd_stmt_get_result_metadata(MYSQL_STMT *stmt); +extern int mthd_stmt_read_execute_response(MYSQL_STMT *stmt); extern int mthd_stmt_fetch_row(MYSQL_STMT *stmt, unsigned char **row); extern int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row); extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt); @@ -2489,7 +2490,7 @@ mysql_real_query(MYSQL *mysql, const char *query, unsigned long length) if (ma_simple_command(mysql, COM_QUERY,query,length,1,0)) return(-1); - if (!skip_result) + if (!skip_result && !mysql->options.extension->skip_read_response) return(mysql->methods->db_read_query_result(mysql)); return(0); } @@ -3362,6 +3363,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) CHECK_OPT_EXTENSION_SET(&mysql->options); mysql->options.extension->io_wait = (int(*)(my_socket, my_bool, int))arg1; break; + case MARIADB_OPT_SKIP_READ_RESPONSE: + OPT_SET_EXTENDED_VALUE_INT(&mysql->options, skip_read_response, *(my_bool *)arg1); + break; default: va_end(ap); SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0); @@ -3577,6 +3581,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...) case MARIADB_OPT_IO_WAIT: *((int(**)(my_socket, my_bool, int))arg) = mysql->options.extension ? mysql->options.extension->io_wait : NULL; break; + case MARIADB_OPT_SKIP_READ_RESPONSE: + *((my_bool*)arg)= mysql->options.extension ? mysql->options.extension->skip_read_response : 0; + break; default: va_end(ap); SET_CLIENT_ERROR(mysql, CR_NOT_IMPLEMENTED, SQLSTATE_UNKNOWN, 0); @@ -4509,5 +4516,7 @@ struct st_mariadb_methods MARIADB_DEFAULT_METHODS = { /* invalidate statements */ ma_invalidate_stmts, /* API functions */ - &MARIADB_API + &MARIADB_API, + /* read execute response */ + mthd_stmt_read_execute_response }; diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index a1a87755..3808f9b2 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -322,10 +322,13 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row) result->data= 0; result->rows= 0; - if (stmt->mysql->methods->db_stmt_read_all_rows(stmt)) - return(1); + if (!stmt->mysql->options.extension->skip_read_response) + { + if (stmt->mysql->methods->db_stmt_read_all_rows(stmt)) + return(1); - return(stmt_buffered_fetch(stmt, row)); + return(stmt_buffered_fetch(stmt, row)); + } } /* no more cursor data available */ *row= NULL; @@ -1575,6 +1578,52 @@ my_bool mthd_stmt_read_prepare_response(MYSQL_STMT *stmt) p++; /* for backward compatibility we also update mysql->warning_count */ stmt->mysql->warning_count= stmt->upsert_status.warning_count= uint2korr(p); + +/* metadata not supported yet */ + + if (stmt->param_count && + stmt->mysql->methods->db_stmt_get_param_metadata(stmt)) + { + return 1; + } + + /* allocated bind buffer for parameters */ + if (stmt->field_count && + stmt->mysql->methods->db_stmt_get_result_metadata(stmt)) + { + return 1; + } + if (stmt->param_count) + { + if (stmt->prebind_params) + { + if (stmt->prebind_params != stmt->param_count) + { + SET_CLIENT_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); + return 1; + } + } else { + if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND)))) + { + SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return 1; + } + memset(stmt->params, '\0', stmt->param_count * sizeof(MYSQL_BIND)); + } + } + /* allocated bind buffer for result */ + if (stmt->field_count) + { + MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root; + if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND)))) + { + SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return 1; + } + memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count); + } + stmt->state = MYSQL_STMT_PREPARED; + return(0); } @@ -1663,57 +1712,14 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon if (!is_multi && mysql->net.extension->multi_status == COM_MULTI_ENABLED) ma_multi_command(mysql, COM_MULTI_END); - if (mysql->net.extension->multi_status > COM_MULTI_OFF) + if (mysql->net.extension->multi_status > COM_MULTI_OFF || + mysql->options.extension->skip_read_response) return 0; if (mysql->methods->db_read_prepare_response && mysql->methods->db_read_prepare_response(stmt)) goto fail; - /* metadata not supported yet */ - - if (stmt->param_count && - stmt->mysql->methods->db_stmt_get_param_metadata(stmt)) - { - goto fail; - } - - /* allocated bind buffer for parameters */ - if (stmt->field_count && - stmt->mysql->methods->db_stmt_get_result_metadata(stmt)) - { - goto fail; - } - if (stmt->param_count) - { - if (stmt->prebind_params) - { - if (stmt->prebind_params != stmt->param_count) - { - SET_CLIENT_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, SQLSTATE_UNKNOWN, 0); - goto fail; - } - } else { - if (!(stmt->params= (MYSQL_BIND *)ma_alloc_root(&stmt->mem_root, stmt->param_count * sizeof(MYSQL_BIND)))) - { - SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - goto fail; - } - memset(stmt->params, '\0', stmt->param_count * sizeof(MYSQL_BIND)); - } - } - /* allocated bind buffer for result */ - if (stmt->field_count) - { - MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root; - if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND)))) - { - SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - goto fail; - } - memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count); - } - stmt->state = MYSQL_STMT_PREPARED; return(0); fail: @@ -1834,7 +1840,7 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt) return(0); } -int stmt_read_execute_response(MYSQL_STMT *stmt) +int mthd_stmt_read_execute_response(MYSQL_STMT *stmt) { MYSQL *mysql= stmt->mysql; int ret; @@ -2070,10 +2076,11 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) return(1); } - if (mysql->net.extension->multi_status > COM_MULTI_OFF) + if (mysql->net.extension->multi_status > COM_MULTI_OFF || + mysql->options.extension->skip_read_response) return(0); - return(stmt_read_execute_response(stmt)); + return(mthd_stmt_read_execute_response(stmt)); } static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags) @@ -2475,43 +2482,18 @@ int STDCALL mariadb_stmt_execute_direct(MYSQL_STMT *stmt, if (ma_multi_command(mysql, COM_MULTI_END)) goto fail; - /* read prepare response */ - if (mysql->methods->db_read_prepare_response && - mysql->methods->db_read_prepare_response(stmt)) - goto fail; - - clear_result= 0; - - /* metadata not supported yet */ - - if (stmt->param_count && - stmt->mysql->methods->db_stmt_get_param_metadata(stmt)) + if (!mysql->options.extension->skip_read_response) { + /* read prepare response */ + if (mysql->methods->db_read_prepare_response && + mysql->methods->db_read_prepare_response(stmt)) goto fail; - } - /* allocated bind buffer for parameters */ - if (stmt->field_count && - stmt->mysql->methods->db_stmt_get_result_metadata(stmt)) - { - goto fail; - } + clear_result= 0; - /* allocated bind buffer for result */ - if (stmt->field_count) - { - MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)stmt->extension)->fields_ma_alloc_root; - if (!(stmt->bind= (MYSQL_BIND *)ma_alloc_root(fields_ma_alloc_root, stmt->field_count * sizeof(MYSQL_BIND)))) - { - SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - goto fail; - } - memset(stmt->bind, 0, sizeof(MYSQL_BIND) * stmt->field_count); + /* read execute response packet */ + return mthd_stmt_read_execute_response(stmt); } - stmt->state = MYSQL_STMT_PREPARED; - - /* read execute response packet */ - return stmt_read_execute_response(stmt); fail: /* check if we need to set error message */ if (!mysql_stmt_errno(stmt)) diff --git a/libmariadb/secure/gnutls.c b/libmariadb/secure/gnutls.c index 3cd13471..564102cd 100644 --- a/libmariadb/secure/gnutls.c +++ b/libmariadb/secure/gnutls.c @@ -1019,8 +1019,6 @@ static size_t ma_gnutls_get_protocol_version(const char *tls_version_option, goto end; - if (strstr(tls_version_option, "TLSv1.0")) - strcat(tls_versions, ":+VERS-TLS1.0"); if (strstr(tls_version_option, "TLSv1.1")) strcat(tls_versions, ":+VERS-TLS1.1"); if (strstr(tls_version_option, "TLSv1.2")) @@ -1033,7 +1031,7 @@ end: if (tls_versions[0]) snprintf(priority_string, prio_len - 1, "-VERS-TLS-ALL%s:NORMAL", tls_versions); else - strncpy(priority_string, "NORMAL:+VERS-ALL", prio_len - 1); + strncpy(priority_string, "NORMAL:+VERS-ALL:-VERS-TLSv1.0", prio_len - 1); return strlen(priority_string); } diff --git a/libmariadb/secure/openssl.c b/libmariadb/secure/openssl.c index 26113cca..5bb77272 100644 --- a/libmariadb/secure/openssl.c +++ b/libmariadb/secure/openssl.c @@ -103,8 +103,6 @@ static long ma_tls_version_options(const char *version) if (!version) return 0; - if (strstr(version, "TLSv1.0")) - protocol_options&= ~SSL_OP_NO_TLSv1; if (strstr(version, "TLSv1.1")) protocol_options&= ~SSL_OP_NO_TLSv1_1; if (strstr(version, "TLSv1.2")) @@ -445,7 +443,8 @@ void *ma_tls_init(MYSQL *mysql) SSL_CTX *ctx= NULL; long options= SSL_OP_ALL | SSL_OP_NO_SSLv2 | - SSL_OP_NO_SSLv3; + SSL_OP_NO_SSLv3 | + SSL_OP_NO_TLSv1; pthread_mutex_lock(&LOCK_openssl_config); #if OPENSSL_VERSION_NUMBER >= 0x10100000L diff --git a/unittest/libmariadb/misc.c b/unittest/libmariadb/misc.c index 723c47e7..04428e9d 100644 --- a/unittest/libmariadb/misc.c +++ b/unittest/libmariadb/misc.c @@ -1463,7 +1463,65 @@ static int test_conc458(MYSQL *my __attribute__((unused))) } +static int test_conc533(MYSQL *mysql) +{ + my_bool skip= 1; + int rc; + MYSQL_RES *result; + MYSQL_ROW row; + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char buffer[10]; + + rc= mysql_options(mysql, MARIADB_OPT_SKIP_READ_RESPONSE, &skip); + + rc= mysql_real_query(mysql, SL("SELECT 1")); + check_mysql_rc(rc, mysql); + + rc= mysql->methods->db_read_query_result(mysql); + check_mysql_rc(rc, mysql); + + result= mysql_store_result(mysql); + row= mysql_fetch_row(result); + + FAIL_IF(strcmp(row[0], "1"), "Expected value \"1\""); + mysql_free_result(result); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL("SELECT 1")); + check_stmt_rc(rc, stmt); + + rc= mysql->methods->db_read_prepare_response(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_field_count(stmt) != 1, "Expected field_count= 1"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql->methods->db_read_execute_response(stmt); + check_stmt_rc(rc, stmt); + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer= buffer; + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer_length= 10; + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(strcmp(buffer, "1"), "Expected value \"1\""); + + mysql_stmt_close(stmt); + + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc533", test_conc533, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"test_conc458", test_conc458, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc457", test_conc457, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc384", test_conc384, TEST_CONNECTION_NONE, 0, NULL, NULL},