Bug #80459 Accessing uninitialized memory inside mysys/mf_qsort.c my_qsort() line ~124
Submitted: 21 Feb 2016 23:34 Modified: 16 Nov 2018 14:59
Reporter: Sergey Sprogis Email Updates:
Status: Won't fix 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
Tags: mysqld, UMR

[21 Feb 2016 23:34] 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 in "stack" ... (8 bytes) on the stack:
 my_qsort() + 0xac8 <mf_qsort.c : 124>
  124:=>  POP(low, high);
 my_dir() + 0xbb4 <my_lib.c : 160>
  160:=>   sizeof(FILEINFO), (qsort_cmp) comp_names);
 find_files(THD*, ... <sql_show.cc : 632>
  632:=>    if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
 make_db_list(THD*, ... <sql_show.cc : 3559>
  3559:=>  mysql_data_home, NullS, 1, tmp_mem_root) != FIND_FILES_OK);
 fill_schema_schemata(THD*, TABLE_LIST*, Item*) + 0x620 <sql_show.cc : 4724>
  4724:=> if (make_db_list(thd, &db_names, &lookup_field_vals,
 do_fill_table(THD*, TABLE_LIST*, QEP_TAB*) + 0x4a4 <sql_show.cc : 8029>
  8029:=> bool res= table_list->schema_table->fill_table(
 get_schema_tables_result(JOIN*, enum_schema_table_state) + 0x1f04 <sql_show.cc : 8132>
  8132:=>  if (do_fill_table(thd, table_list, tab))
 JOIN::prepare_result() + 0xae0 <sql_select.cc : 909>
  909:=>  get_schema_tables_result(this, PROCESSED_BY_JOIN_EXEC))
======================================

How to repeat:
1. If you have access to Discover tool, and latest Sun Stidio 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 'low' argument located
   inside my_qsort.c ,line 124:

   POP(low, high);

   is indeed uninitialized before that point.
   
   Below is 36 lines independent executable t.c test case which accurately
   simulates original issue. For it Discover produces exactly the same UMR
   message as for original mysqld server.

t.c
===================================
typedef struct fileinfo {
  char *name;
} FILEINFO;
typedef struct st_my_dir  {
 struct fileinfo *dir_entry;
 unsigned  number_off_files;
} MY_DIR;
typedef struct st_stack {
 char *low;
 char *high;
} stack_node;
void my_qsort(void *base_ptr, unsigned count, unsigned size){
 char *low, *high;
 stack_node stack[64], *stack_ptr;
 low =(char*)base_ptr;
 high=low+size*(count-1);
 stack_ptr=stack+1;
 do {
  char *low_ptr,*high_ptr;
  for (low_ptr=low+size; low_ptr<=high; low_ptr+=size){
   low=(--stack_ptr)->low;
   high=stack_ptr->high;
  }
 } while (stack_ptr > stack);
}
int main() {
 MY_DIR  buffer,*result;
 FILEINFO finfo[2];
 char *p1=".", *p2="..";
 result=&buffer;
 result->dir_entry=finfo;
 result->dir_entry[0].name=p1; result->dir_entry[1].name=p2;
 result->number_off_files=2;
 my_qsort((void *)result->dir_entry,result->number_off_files,sizeof(FILEINFO));
 return 0;
}
===================================

Suggested fix:
Somehow initialize 'low' argument before passing its value into POP(low, high);
[21 Feb 2016 23:38] Sergey Sprogis
Added MySQL version
[22 Feb 2016 12:57] Umesh Shastry
Hello Sergey,

Thank you for the report!

Thanks,
Umesh
[16 Nov 2018 14:59] Dyre Tjeldvoll
Posted by developer:
 
The file with the problematic code has been removed.