stack-use-after-scope in reinit_io_cache() detected by ASan
Description
Environment
Smart Checklist
Activity
Yura Sorokin July 5, 2018 at 9:14 PM
Although 'IO_CACHE tempfile' declared inside an inner block in 'mysql_update()' function is copied by value to 'select->file'
select->file=tempfile
this operation is not safe as some of the members inside IO_CACHE struct were initialized with addresses of other data members.
In particular, in 'setup_io_cache()', called from 'init_functions()', called from 'init_io_cache()', called from 'open_cached_file()'
'current_pos' and 'current_end' are initialized with such addresses.
/* Ensure that my_b_tell() and my_b_bytes_in_cache works */
if (info->type == WRITE_CACHE)
{
info->current_pos= &info->write_pos;
info->current_end= &info->write_end;
}
else
{
info->current_pos= &info->read_pos;
info->current_end= &info->read_end;
}
Yura Sorokin July 3, 2018 at 3:00 PM
The problem is known to Oracle as
Bug #24343330 "READ OF OUT-OF-SCOPE (TEMPFILE) IN MYSQL_UPDATE()"
and was fixed in 8.0.4 (https://github.com/mysql/mysql-server/commit/4d5ff7bfbf8)
and 5.7.21 (https://github.com/mysql/mysql-server/commit/e49e52a5de7) but never
backported to 5.6 and 5.5.
Yura Sorokin July 3, 2018 at 2:57 PM
The problem seems to be with the
IO_CACHE tempfile;
declared inside of the one of the inner blocks in 'mysql_update()' function but used in the
init_read_record(&info, thd, table, select, 0, 1, FALSE);
outside of this block via 'select' parameter
select->file=tempfile; // Read row ptrs from this file
Details
Details
Assignee
Reporter
Time tracking
Fix versions
Affects versions
Priority
Smart Checklist
Open Smart Checklist
Smart Checklist

Address Sanitizer from GCC 7.3 and 8.0 detects the following problem in a number of MTR test cases.
The easiest way to reproduce it is
./mysql-test/mtr --debug-server innodb_bug12661768
==11845==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7f6f48198250 at pc 0x5642cb4ab9c7 bp 0x7f6f48197950 sp 0x7f6f48197940 READ of size 8 at 0x7f6f48198250 thread T17 #0 0x5642cb4ab9c6 in reinit_io_cache /mnt/hgfs/repos/percona-server/mysys/mf_iocache.c:342 #1 0x5642cb39a502 in init_read_record(READ_RECORD*, THD*, TABLE*, SQL_SELECT*, int, bool, bool) /mnt/hgfs/repos/percona-server/sql/records.cc:232 #2 0x5642caea11cd in mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, enum_duplicates, bool, unsigned long long*, unsigned long long*) /mnt/hgfs/repos/percona-server/sql/sql_update.cc:621 #3 0x5642cacd168c in mysql_execute_command(THD*) /mnt/hgfs/repos/percona-server/sql/sql_parse.cc:3098 #4 0x5642cace2114 in mysql_parse(THD*, char*, unsigned int, Parser_state*) /mnt/hgfs/repos/percona-server/sql/sql_parse.cc:6116 #5 0x5642cace7a2e in dispatch_command(enum_server_command, THD*, char*, unsigned int) /mnt/hgfs/repos/percona-server/sql/sql_parse.cc:1112 #6 0x5642cacecfd4 in do_command(THD*) /mnt/hgfs/repos/percona-server/sql/sql_parse.cc:792 #7 0x5642caf64d35 in do_handle_one_connection(THD*) /mnt/hgfs/repos/percona-server/sql/sql_connect.cc:1478 #8 0x5642caf6503a in handle_one_connection /mnt/hgfs/repos/percona-server/sql/sql_connect.cc:1385 #9 0x5642cb525c79 in pfs_spawn_thread /mnt/hgfs/repos/percona-server/storage/perfschema/pfs.cc:1015 #10 0x7f6f580516da in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76da) #11 0x7f6f56b3088e in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x12188e) Address 0x7f6f48198250 is located in stack of thread T17 at offset 1328 in frame #0 0x5642cae9f10b in mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, enum_duplicates, bool, unsigned long long*, unsigned long long*) /mnt/hgfs/repos/percona-server/sql/sql_update.cc:260 This frame has 20 object(s): [32, 33) 'need_sort' [96, 97) 'reverse' [160, 164) 'error' [224, 228) 'dup_key_found' [288, 292) 'table_count' [352, 356) 'cond_value' [416, 420) 'length' [480, 488) 'old_covering_keys' [544, 552) 'table' [608, 616) 'examined_rows' [672, 680) 'prelocking_strategy' [736, 744) 'tmp' [800, 808) 'table_list' [864, 872) 'conds' [928, 952) 'all_fields' [992, 1024) '_db_stack_frame_' [1056, 1088) '_db_stack_frame_' [1120, 1280) 'info' [1312, 1592) 'tempfile' <== Memory access at offset 1328 is inside this variable [1632, 2144) 'buff' HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) Thread T17 created by T0 here: #0 0x7f6f586d3043 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x4b043) #1 0x5642cb529535 in spawn_thread_v1 /mnt/hgfs/repos/percona-server/storage/perfschema/pfs.cc:1038 #2 0x5642cab14c56 in inline_mysql_thread_create /mnt/hgfs/repos/percona-server/include/mysql/psi/mysql_thread.h:1049 #3 0x5642cab14c56 in create_thread_to_handle_connection(THD*) /mnt/hgfs/repos/percona-server/sql/mysqld.cc:5334 #4 0x5642cab16964 in create_new_thread /mnt/hgfs/repos/percona-server/sql/mysqld.cc:5432 #5 0x5642cab16964 in handle_connections_sockets() /mnt/hgfs/repos/percona-server/sql/mysqld.cc:5692 #6 0x5642cab1dc04 in mysqld_main(int, char**) /mnt/hgfs/repos/percona-server/sql/mysqld.cc:4946 #7 0x5642cab02351 in main /mnt/hgfs/repos/percona-server/sql/main.cc:25 #8 0x7f6f56a30b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96) SUMMARY: AddressSanitizer: stack-use-after-scope /mnt/hgfs/repos/percona-server/mysys/mf_iocache.c:342 in reinit_io_cache Shadow bytes around the buggy address: 0x0fee6902aff0: 00 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2 f2 f2 f2 0x0fee6902b000: 00 f2 f2 f2 f2 f2 f2 f2 00 f2 f2 f2 f2 f2 f2 f2 0x0fee6902b010: 00 f2 f2 f2 f2 f2 f2 f2 00 00 00 f2 f2 f2 f2 f2 0x0fee6902b020: 00 00 00 00 f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 0x0fee6902b030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0fee6902b040: 00 00 00 00 f2 f2 f2 f2 f8 f8[f8]f8 f8 f8 f8 f8 0x0fee6902b050: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x0fee6902b060: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 0x0fee6902b070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0fee6902b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0fee6902b090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==11845==ABORTING