|
If SP CALLhas been prepared and executed, and then the SP is changed(DROPped and CREATEd) by someone, the second execution of that CALL statement will reliably crash the server. The C API code to repeat
MYSQL *ma;
|
MYSQL_STMT *stmt;
|
MYSQL_BIND bind[3], paramBind[3];
|
MARIADB_CHARSET_INFO *cs;
|
my_bool is_null= 0, error= 0;
|
unsigned int i= 0, j= 0, res[3]={30,20,50}, param[3]= {30,20,50};
|
|
ma = mysql_init(NULL);
|
mysql_optionsv(ma, MYSQL_SET_CHARSET_NAME, "latin1");
|
|
if (!mysql_real_connect(ma, "localhost", "root", "root", "test", 3306, NULL, CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS))
|
{
|
printf("Could not connect: %s\n", mysql_error(ma));
|
exit(1);
|
}
|
else
|
{
|
printf("Server info %s\nClient info: %s\n",
|
mysql_get_server_info(ma), mysql_get_client_info());
|
}
|
|
stmt= mysql_stmt_init(ma);
|
|
mysql_query(ma, "DROP PROCEDURE IF EXISTS t_outparams");
|
mysql_query(ma, "CREATE PROCEDURE t_outparams("
|
" IN p_in INT, "
|
" OUT p_out INT, "
|
" INOUT p_inout INT) "
|
"BEGIN "
|
" SET p_in = p_in*10, p_out = (p_in+p_inout)*10, p_inout = p_inout*10; "
|
"END");
|
mysql_stmt_prepare(stmt, "CALL t_outparams(?,?,?)", -1);
|
|
memset(&bind, 0, sizeof(bind));
|
memset(&bind, 0, sizeof(paramBind));
|
|
bind[0].buffer_type= MYSQL_TYPE_LONG;
|
bind[0].buffer= (void *)res;
|
bind[0].buffer_length= sizeof(int);
|
bind[0].is_null= NULL;
|
bind[0].error= NULL;
|
|
bind[1].buffer_type= MYSQL_TYPE_LONG;
|
bind[1].buffer= (void *)(res + 1);
|
bind[1].buffer_length= sizeof(int);
|
bind[1].is_null= NULL;
|
bind[1].error= NULL;
|
|
bind[2].buffer_type= MYSQL_TYPE_LONG;
|
bind[2].buffer= (void *)(res + 2);
|
bind[2].buffer_length= sizeof(int);
|
bind[2].is_null= NULL;
|
bind[2].error= NULL;
|
|
mysql_stmt_bind_param(stmt, bind);
|
mysql_stmt_execute(stmt);
|
mysql_stmt_store_result(stmt);
|
mysql_stmt_bind_result(stmt, bind);
|
|
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
|
{
|
printf("-- Values= %d %d %d\n", res[0], res[1], res[2]);
|
}
|
printf("---------------------------------------------------\n");
|
mysql_stmt_next_result(stmt);
|
if (mysql_stmt_field_count(stmt) == 0)
|
{
|
printf("SP returned: %lld", mysql_stmt_affected_rows(stmt));
|
}
|
|
mysql_query(ma, "DROP PROCEDURE t_outparams");
|
|
mysql_query(ma, "CREATE PROCEDURE t_outparams("
|
" OUT p_out VARCHAR(19), "
|
" IN p_in INT, "
|
" INOUT p_inout INT) "
|
"BEGIN "
|
" SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
|
" SELECT p_inout, p_in, substring(p_out, 9);"
|
"END");
|
|
mysql_stmt_bind_param(stmt, bind);
|
mysql_stmt_execute(stmt);
|
mysql_stmt_store_result(stmt);
|
mysql_stmt_bind_result(stmt, bind);
|
|
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
|
{
|
printf("-- Values= %d %d %d\n", res[0], res[1], res[2]);
|
}
|
printf("---------------------------------------------------\n");
|
mysql_stmt_next_result(stmt);
|
mysql_stmt_close(stmt);
|
|
mysql_query(ma, "DROP PROCEDURE t_outparams");
|
mysql_close(ma);
|
I don't have latest versions for all branches, but this crashes all supported server release series
Server info 10.11.5-MariaDB
|
Client info: 3.3.8
|
-- Values= 3500 500 50
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 10.5.20-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 10.6.11-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 10.4.31-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 10.10.2-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 10.9.4-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Could not connect: Can't connect to server on 'localhost' (10061)
|
Server info 11.0.2-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Server info 11.1.2-MariaDB
|
Client info: 3.3.8
|
-- Values= 20000 0 0
|
---------------------------------------------------
|
SP returned: 0
|
-- Values= 200 300 0
|
---------------------------------------------------
|
Call mysql_stmt_next_result unexpectedly returned !0 because of Lost connection to server during query (errno: 2013)
|
===================================================
|
Unlikely this matters, but I am testing on Windows. The backtrace from the log:
Server version: 10.11.5-MariaDB source revision: 7875294b6b74b53dd3aaa723e6cc103d2bb47b2c
|
key_buffer_size=134217728
|
read_buffer_size=131072
|
max_used_connections=1
|
max_threads=65537
|
thread_count=1
|
It is possible that mysqld could use up to
|
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 142742958 K bytes of memory
|
Hope that's ok; if not, decrease some variables in the equation.
|
|
Thread pointer: 0x1a98daccf98
|
Attempting backtrace. You can use the following information to find out
|
where mysqld died. If you see no messages after this, something went
|
terribly wrong...
|
server.dll!my_convert()[ctype.c:1267]
|
server.dll!String::copy()[sql_string.cc:476]
|
server.dll!Protocol::net_store_data_cs()[protocol.cc:104]
|
server.dll!Protocol_text::store_field_metadata()[protocol.cc:854]
|
server.dll!Protocol::send_result_set_metadata()[protocol.cc:1213]
|
server.dll!Protocol_binary::send_out_parameters()[protocol.cc:1965]
|
server.dll!Prepared_statement::execute()[sql_prepare.cc:5335]
|
server.dll!Prepared_statement::execute_loop()[sql_prepare.cc:4646]
|
server.dll!mysql_stmt_execute_common()[sql_prepare.cc:3578]
|
server.dll!mysqld_stmt_execute()[sql_prepare.cc:3352]
|
server.dll!dispatch_command()[sql_parse.cc:1826]
|
server.dll!do_command()[sql_parse.cc:1407]
|
server.dll!tp_callback()[threadpool_common.cc:245]
|
KERNEL32.DLL!TermsrvSetKeySecurity()
|
ntdll.dll!RtlEqualUnicodeString()
|
ntdll.dll!TpReleaseCleanupGroupMembers()
|
KERNEL32.DLL!BaseThreadInitThunk()
|
ntdll.dll!RtlUserThreadStart()
|
|
Trying to get some variables.
|
Some pointers may be invalid and cause the dump to abort.
|
Query (0x1a98db75090): CALL t_outparams(?,?,?)
|
Connection ID (thread ID): 12
|
Status: NOT_KILLED
|
|
Optimizer switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=off
|
I did not dig much, but looks like the order of in/out parameters is what matters here - in original test the first change of procedure did not change that, but added a resultset, and it did not crash the server.
Not sure if it's critical - unlikely something that people do on production systems, but it's still a crash.
|