[MDEV-11641] innobase_get_stmt_safe() does not copy the last byte of thd->query_string Created: 2016-12-22  Updated: 2017-02-15  Resolved: 2017-02-15

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - InnoDB, Tests
Affects Version/s: 10.2.2, 10.2.3
Fix Version/s: 10.2.4

Type: Bug Priority: Major
Reporter: Elena Stepanova Assignee: Marko Mäkelä
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Relates
relates to MDEV-12070 Introduce thd_query_safe() from MySQL... Closed
relates to MDEV-7069 Fix buildbot failures in main server ... Stalled

 Description   

http://buildbot.askmonty.org/buildbot/builders/xenial-amd64-valgrind/builds/183/steps/test/logs/stdio
Also reproducible locally with cmake . -DCMAKE_BUILD_TYPE=Debug -DWITH_VALGRIND=YES

innodb.innodb_information_schema_tables 'innodb' w3 [ fail ]  Found warnings/errors in server log file!
        Test ended at 2016-12-22 09:15:35
line
==26507== Thread 27:
==26507== Conditional jump or move depends on uninitialised value(s)
==26507==    at 0xFB1FA9: hash_get_nth_cell(hash_table_t*, unsigned long) (hash0hash.ic:40)
==26507==    by 0xFB2440: ha_storage_get(ha_storage_t*, void const*, unsigned long) (ha0storage.cc:59)
==26507==    by 0xFB24CF: ha_storage_put_memlim(ha_storage_t*, void const*, unsigned long, unsigned long) (ha0storage.cc:100)
==26507==    by 0xE36F5A: fill_trx_row(i_s_trx_row_t*, trx_t const*, i_s_locks_row_t const*, trx_i_s_cache_t*) (trx0i_s.cc:503)
==26507==    by 0xE38A17: fetch_data_into_cache_low(trx_i_s_cache_t*, bool, ut_list_base<trx_t, ut_list_node<trx_t> trx_t::*>*) (trx0i_s.cc:1312)
==26507==    by 0xE38B29: fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1338)
==26507==    by 0xE38C07: trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1366)
==26507==    by 0xC8D457: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1274)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507== Use of uninitialised value of size 8
==26507==    at 0xFB2441: ha_storage_get(ha_storage_t*, void const*, unsigned long) (ha0storage.cc:59)
==26507==    by 0xFB24CF: ha_storage_put_memlim(ha_storage_t*, void const*, unsigned long, unsigned long) (ha0storage.cc:100)
==26507==    by 0xE36F5A: fill_trx_row(i_s_trx_row_t*, trx_t const*, i_s_locks_row_t const*, trx_i_s_cache_t*) (trx0i_s.cc:503)
==26507==    by 0xE38A17: fetch_data_into_cache_low(trx_i_s_cache_t*, bool, ut_list_base<trx_t, ut_list_node<trx_t> trx_t::*>*) (trx0i_s.cc:1312)
==26507==    by 0xE38B29: fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1338)
==26507==    by 0xE38C07: trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1366)
==26507==    by 0xC8D457: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1274)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507==    by 0x6E055F: handle_select(THD*, LEX*, select_result*, unsigned long) (sql_select.cc:373)
==26507== Conditional jump or move depends on uninitialised value(s)
==26507==    at 0xFB1FA9: hash_get_nth_cell(hash_table_t*, unsigned long) (hash0hash.ic:40)
==26507==    by 0xFB263E: ha_storage_put_memlim(ha_storage_t*, void const*, unsigned long, unsigned long) (ha0storage.cc:132)
==26507==    by 0xE36F5A: fill_trx_row(i_s_trx_row_t*, trx_t const*, i_s_locks_row_t const*, trx_i_s_cache_t*) (trx0i_s.cc:503)
==26507==    by 0xE38A17: fetch_data_into_cache_low(trx_i_s_cache_t*, bool, ut_list_base<trx_t, ut_list_node<trx_t> trx_t::*>*) (trx0i_s.cc:1312)
==26507==    by 0xE38B29: fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1338)
==26507==    by 0xE38C07: trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1366)
==26507==    by 0xC8D457: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1274)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507==    by 0x6E055F: handle_select(THD*, LEX*, select_result*, unsigned long) (sql_select.cc:373)
==26507== Use of uninitialised value of size 8
==26507==    at 0xFB2647: ha_storage_put_memlim(ha_storage_t*, void const*, unsigned long, unsigned long) (ha0storage.cc:132)
==26507==    by 0xE36F5A: fill_trx_row(i_s_trx_row_t*, trx_t const*, i_s_locks_row_t const*, trx_i_s_cache_t*) (trx0i_s.cc:503)
==26507==    by 0xE38A17: fetch_data_into_cache_low(trx_i_s_cache_t*, bool, ut_list_base<trx_t, ut_list_node<trx_t> trx_t::*>*) (trx0i_s.cc:1312)
==26507==    by 0xE38B29: fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1338)
==26507==    by 0xE38C07: trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1366)
==26507==    by 0xC8D457: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1274)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507==    by 0x6E055F: handle_select(THD*, LEX*, select_result*, unsigned long) (sql_select.cc:373)
==26507==    by 0x6AC2D9: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:6399)
==26507== Use of uninitialised value of size 8
==26507==    at 0xFB2657: ha_storage_put_memlim(ha_storage_t*, void const*, unsigned long, unsigned long) (ha0storage.cc:132)
==26507==    by 0xE36F5A: fill_trx_row(i_s_trx_row_t*, trx_t const*, i_s_locks_row_t const*, trx_i_s_cache_t*) (trx0i_s.cc:503)
==26507==    by 0xE38A17: fetch_data_into_cache_low(trx_i_s_cache_t*, bool, ut_list_base<trx_t, ut_list_node<trx_t> trx_t::*>*) (trx0i_s.cc:1312)
==26507==    by 0xE38B29: fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1338)
==26507==    by 0xE38C07: trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t*) (trx0i_s.cc:1366)
==26507==    by 0xC8D457: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1274)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507==    by 0x6E055F: handle_select(THD*, LEX*, select_result*, unsigned long) (sql_select.cc:373)
==26507==    by 0x6AC2D9: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:6399)
==26507== Conditional jump or move depends on uninitialised value(s)
==26507==    at 0x4C30F78: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26507==    by 0xC8C3C0: fill_innodb_trx_from_cache(trx_i_s_cache_t*, THD*, TABLE*) (i_s.cc:644)
==26507==    by 0xC8D57F: trx_i_s_common_fill_table(THD*, TABLE_LIST*, Item*) (i_s.cc:1289)
==26507==    by 0x74BD50: get_schema_tables_result(JOIN*, enum_schema_table_state) (sql_show.cc:8204)
==26507==    by 0x6EAD24: JOIN::exec_inner() (sql_select.cc:3352)
==26507==    by 0x6EA463: JOIN::exec() (sql_select.cc:3199)
==26507==    by 0x6EB5C5: mysql_select(THD*, TABLE_LIST*, unsigned int, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*) (sql_select.cc:3584)
==26507==    by 0x6E055F: handle_select(THD*, LEX*, select_result*, unsigned long) (sql_select.cc:373)
==26507==    by 0x6AC2D9: execute_sqlcom_select(THD*, TABLE_LIST*) (sql_parse.cc:6399)
==26507==    by 0x6A1AE4: mysql_execute_command(THD*) (sql_parse.cc:3423)
==26507==    by 0x6AFC4E: mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool) (sql_parse.cc:7842)
==26507==    by 0x69D551: dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool) (sql_parse.cc:1799)



 Comments   
Comment by Marko Mäkelä [ 2017-02-15 ]

This problem was introduced in a merge of MySQL 5.7.9 to MariaDB Server 10.2.2 which included a buggy mock-up version of the function innobase_get_stmt_safe() that fails to copy the last byte of the thd_query_string().
I filed MDEV-12070 for implementing the function properly.

Comment by Marko Mäkelä [ 2017-02-15 ]

A simple fix:

diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e53253db19c..ef599bc5d04 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2465,8 +2465,8 @@ innobase_get_stmt_safe(
 	stmt =  thd ? thd_query_string(thd) : NULL;
 
 	if (stmt && stmt->str) {
-		length = stmt->length > buflen ? buflen : stmt->length;
-		memcpy(buf, stmt->str, length-1);
+		length = stmt->length >= buflen ? buflen - 1 : stmt->length;
+		memcpy(buf, stmt->str, length);
 		buf[length]='\0';
 	} else {
 		buf[0]='\0';

With this fix, the tests pass:

innodb.row_lock 'innodb'                 w3 [ pass ]   4630
innodb.innodb_information_schema 'innodb' w2 [ pass ]   7422
main.partition_innodb_plugin 'innodb'    w1 [ pass ]  10631
valgrind_report                          w0 [ pass ]       

Generated at Thu Feb 08 07:51:32 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.