Details
-
Bug
-
Status: Closed (View Workflow)
-
Minor
-
Resolution: Won't Fix
-
None
-
None
-
None
Description
I found this from a Valgrind warning:
==3619== Invalid read of size 4
|
==3619== at 0x9FF73F: xt_get_res_record_ref(unsigned char*, XTIdxResult*) (index_xt.h:454)
|
==3619== by 0x9F4E90: xt_scan_branch_single(XTTable*, XTIndex*, XTIdxBranch*, XTIdxKeyValue*, XTIdxResult*) (index_xt.cc:501)
|
==3619== by 0x9FEE6B: xt_idx_insert(XTOpenTable*, XTIndex*, unsigned, unsigned, unsigned char*, unsigned char*, int) (index_xt.cc:1877)
|
==3619== by 0xA1924B: xt_tab_new_record(XTOpenTable*, unsigned char*) (table_xt.cc:4392)
|
==3619== by 0x9EECD9: ha_pbxt::write_row(unsigned char*) (ha_pbxt.cc:2645)
|
==3619== by 0x7C4CC1: handler::ha_write_row(unsigned char*) (handler.cc:4642)
|
==3619== by 0x7E3087: copy_data_between_tables(st_table*, st_table*, List<Create_field>&, bool, unsigned, st_order*, unsigned long long*, unsigned long long*, enum_enable_or_disable, bool) (sql_table.cc:7779)
|
==3619== by 0x7F05E2: mysql_alter_table(THD*, char*, char*, st_ha_create_information*, TABLE_LIST*, Alter_info*, unsigned, st_order*, bool) (sql_table.cc:7221)
|
==3619== by 0x68BE71: mysql_execute_command(THD*) (sql_parse.cc:2959)
|
==3619== by 0x692F7F: mysql_parse(THD*, char const*, unsigned, char const**) (sql_parse.cc:6034)
|
==3619== by 0x693D91: dispatch_command(enum_server_command, THD*, char*, unsigned) (sql_parse.cc:1247)
|
==3619== by 0x69528F: do_command(THD*) (sql_parse.cc:886)
|
==3619== by 0x68066C: handle_one_connection (sql_connect.cc:1132)
|
==3619== by 0x50463F6: start_thread (pthread_create.c:297)
|
==3619== by 0x6026B4C: clone (in /usr/lib/debug/libc-2.7.so)
|
==3619== Address 0xcf98030 is 0 bytes after a block of size 33,701,888 alloc'd
|
==3619== at 0x4C22FAB: malloc (vg_replace_malloc.c:207)
|
==3619== by 0x9FF9A2: xt_malloc(XTThread*, unsigned long) (memory_xt.cc:101)
|
==3619== by 0xA439F2: xt_ind_init(XTThread*, unsigned long) (cache_xt.cc:632)
|
==3619== by 0x9EBDBC: pbxt_call_init(XTThread*) (ha_pbxt.cc:974)
|
==3619== by 0x9EC109: pbxt_init(void*) (ha_pbxt.cc:1194)
|
==3619== by 0x7C8E01: ha_initialize_handlerton(st_plugin_int*) (handler.cc:429)
|
==3619== by 0x88ADD6: plugin_initialize(st_plugin_int*) (sql_plugin.cc:1033)
|
==3619== by 0x88E979: plugin_init(int*, char**, int) (sql_plugin.cc:1258)
|
==3619== by 0x67A21C: init_server_components() (mysqld.cc:4069)
|
==3619== by 0x67ACF5: main (mysqld.cc:4541)
|
This is from test case pbxt.multi_update (which takes ~1h to run under
Valgrind :-/).
I think this is a real bug, although possibly minor. Not knowing the code in
detail, I need help in determining the proper fix.
xt_scan_branch_single() basically does a binary search on a block of
memory. There is a while () loop, which exits with i pointing at the position
being searched for.
Note that (at least from a quick look at the code), if the value being
searched for is bigger than all values in the buffer, then the loop will exit
with i pointing past the last element.
After the loop, the code does this:
bitem = base + i * full_item_size;
|
xt_get_res_record_ref(bitem + ind->mi_key_size, result);
|
From the Valgrind trace, it seems to me the problem is that in this case i
points past the last element as described above, so the
xt_get_res_record_ref() reads 8 bytes past the end of the buffer.
This should probably be fixed (in theory this could cause the process to
segfault if memory allocation is really unfortunate and these 8 bytes happen
to be unmapped). Maybe just something like
if (result.sr_found)
|
xt_get_res_record_ref(bitem + ind->mi_key_size, result);
|
in case the values read are only used in the "found" case?
Hope you can sort out the rest from this explanation.