Bug #90412 potential stack corruption with function casting (int-returning to void-returnin
Submitted: 12 Apr 2018 11:16 Modified: 19 Apr 2018 17:47
Reporter: Przemysław Skibiński (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: MyISAM storage engine Severity:S3 (Non-critical)
Version:5.5, 5.6, 5.7 OS:Any
Assigned to: CPU Architecture:Any

[12 Apr 2018 11:16] Przemysław Skibiński
Description:
Calling a int-returning function
static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
that is cast to a void-returning function:
typedef void (*tree_element_free)(void*, TREE_FREE, void *);
can potentially lead to a stack corruption.

gcc-8 show this as a warning: 
[ 26%] Building C object storage/myisam/CMakeFiles/myisam.dir/mi_write.c.o
/github/mysql-server/storage/myisam/mi_write.c: In function ‘mi_init_bulk_insert’:
/github/mysql-server/storage/myisam/mi_write.c:1016:3: warning: cast between incompatible function types from ‘int (*)(uchar *, TREE_FREE,  bulk_insert_param *)’ {aka ‘int (*)(unsigned char *, enum <anonymous>,  struct <anonymous> *)’} to ‘void (*)(void *, TREE_FREE,  const void *)’ {aka ‘void (*)(void *, enum <anonymous>,  const void *)’} [-Wcast-function-type]
   (tree_element_free) keys_free, (void *)params++);
   ^

How to repeat:
mysql-server/storage/myisam/mi_write.c:1012
      init_tree(&info->bulk_insert[i],
                cache_size * key[i].maxlength,
                cache_size * key[i].maxlength, 0,
		(qsort_cmp2)keys_compare, 0,
		(tree_element_free) keys_free, (void *)params++);

Suggested fix:
Convert keys_free() to: 
void keys_free(void*, TREE_FREE, void *);
[12 Apr 2018 13:25] MySQL Verification Team
Hi,

Thank you, very much, for your bug report.

Your analysis is quite correct and I agree with your findings. I only do not agree about how critical is this bug, since this code is in production for decades.

Verified as reported.
[18 Apr 2018 10:44] Tor Didriksen
Posted by developer:
 
I haven't seen the gcc warning, but clang/UBSAN agrees:

./mtr --mem --sanitize main.ctype_utf8

mysys/tree.cc:160:11: runtime error: call to function keys_free(unsigned char*, TREE_FREE, bulk_insert_param*) through pointer to incorrect function type 'void (*)(void *, TREE_FREE, const void *)'
storage/myisam/mi_write.cc:826: note: keys_free(unsigned char*, TREE_FREE, bulk_insert_param*) defined here
    #0 0x9b9f507 in free_tree(TREE*, int) mysys/tree.cc:160:11
    #1 0x9b9f0b2 in delete_tree(TREE*) mysys/tree.cc:175:3
    #2 0xb23f7c9 in mi_end_bulk_insert(MI_INFO*) storage/myisam/mi_write.cc:922:9
    #3 0xb07938b in ha_myisam::end_bulk_insert() storage/myisam/ha_myisam.cc:1466:3
    #4 0x555c95d in handler::ha_end_bulk_insert() sql/handler.cc:4419:3
    #5 0x62e0360 in Query_result_insert::send_eof() sql/sql_insert.cc:2098:47
    #6 0x6210d53 in do_select(JOIN*) sql/sql_executor.cc:1216:45
    #7 0x620d48d in JOIN::exec() sql/sql_executor.cc:294:11
    #8 0x4767661 in Sql_cmd_dml::execute_inner(THD*) sql/sql_select.cc:651:35
    #9 0x4765006 in Sql_cmd_dml::execute(THD*) sql/sql_select.cc:554:7
[19 Apr 2018 17:47] Paul DuBois
Posted by developer:
 
Fixed in 8.0.13.

Code cleanup. No changelog entry needed.