Bug #80487 Accessing uninitialized memory lock0lock.cc lock_table_create() ~3748
Submitted: 24 Feb 2016 6:43 Modified: 24 Feb 2016 23:54
Reporter: Sergey Sprogis Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: Compiling Severity:S3 (Non-critical)
Version:5.7.10 OS:Solaris (Sparc, 11.3)
Assigned to: CPU Architecture:Any

[24 Feb 2016 6:43] Sergey Sprogis
Description:
Oracle's tool called Discover detects UMR (Uninitialized Memory Read)
in mysqld server when executing '1st' test case located inside
MySQL 5.7.10. This UMR was produced on Sparc Solaris 11.3 T7 system,
but it's not platform specific, and can occur on any other platform.

Error message and call stack reported by Discover looks like this:
======================================
(UMR): accessing uninitialized data ... (8 bytes) on the stack:
 lock_table_create(dict_table_t*, unsigned long, trx_t*) + 0x1c54 <lock0lock.cc : 3748>
  3748:=> ut_list_append(table->locks, lock, TableLockGetNode());
 lock_table(unsigned long, dict_table_t*, lock_mode, que_thr_t*) + 0x868 <lock0lock.cc : 4095>
  4095:=> lock_table_create(table, mode | flags, trx);
 row_sel_step(que_thr_t*) + 0x1444 <row0sel.cc : 2368>
  2368:=> thr);
 que_thr_step(que_thr_t*) + 0x1144 <que0que.cc : 1034>
  1034:=> thr = row_sel_step(thr);
 que_run_threads_low(que_thr_t*) + 0x33c <que0que.cc : 1118>
  1118:=> next_thr = que_thr_step(thr);
 que_run_threads(que_thr_t*) + 0x1e0 <que0que.cc : 1158>
  1158:=> que_run_threads_low(thr);
 que_eval_sql(pars_info_t*, const char*, unsigned long, trx_t*) + 0xc10 <que0que.cc : 1235>
  1235:=> que_run_threads(thr);
 row_merge_drop_temp_indexes() + 0x528 <row0merge.cc : 3701>
  3701:=> error = que_eval_sql(NULL, sql, FALSE, trx);
======================================

How to repeat:
1. If you have access to Discover tool, and latest Sun Studio C/C++ compilers
   you need to build MySQL-5.7.10 sources in debug mode on Solaris Sparc,
   then launch discover binary with input argument as mysqld binary,
   and when completed to take a look inside mysql.html file which should
   contain call stack shown in description above.

2. If you do not have access to Discover, you need to debug MySQL server
   with '1st' test case, and to see  that TableLockGetNode() call located
   inside storage/innobase/lock/lock0lock.cc/ lines ~3748

    ut_list_append(table->locks, lock, TableLockGetNode());

   is indeed uninitialized before that point. It should have 1 input argument
   because 3-rd parameter 'Functor get_node' inside ut_list_append()
   template function definition has such input argument, as it can be seen
    from storage/innobase/include/ut0lst.h file:

     ut_list_append(
       ....
        Functor                         get_node)
     {
        typename List::node_type&       node = get_node(*elem);

   Below is 34 lines independent executable t.cc test case which accurately
   simulates original issue. For it Discover produces exactly the same UMR
   message as for original mysqld server.

t.cc
===================================
t.cc
===================================
struct lock_t;
template <typename Type> struct ut_list_node {
 Type*  prev;
 Type* next;
};
struct lock_table_t {
 ut_list_node<lock_t> locks;
};
struct lock_t {
 union {
  lock_table_t tab_lock;
  unsigned     type_mode;
 } un_member;
};
struct TableLockGetNode {
 ut_list_node<lock_t>& operator() (lock_t& elem) {
  return(elem.un_member.tab_lock.locks);
 }
};
template <typename Functor> void ut_list_append(lock_t *elem, Functor get_node){
 get_node(*elem);
};
int main () {
 lock_t lc,*lock=&lc,*lock2;
 lock_table_t ltt;
 ut_list_node<lock_t> uln;
 uln.prev=lock;
 uln.next=lock;
 ltt.locks=uln;
 lock2=lock;
 ut_list_append(lock,TableLockGetNode());
 return 0;
}
===================================

Suggested fix:
Define constructor for TableLockGetNode struct with 1 input argument
so that it will match 3-rd parameter of ut_list_append() template function.
[24 Feb 2016 23:54] Sergey Sprogis
After more analysis I came to the conclusion that it's not a MySQL bug,
but rather a false message produced by Discover when it processes empty structure.