[MDEV-30565] Direct leak in ha_innobase::open with indexed virtual columns Created: 2023-02-03  Updated: 2023-02-04

Status: Open
Project: MariaDB Server
Component/s: Server, Storage Engine - InnoDB
Affects Version/s: 10.3, 10.4
Fix Version/s: 10.4

Type: Bug Priority: Minor
Reporter: Elena Stepanova Assignee: Sergei Golubchik
Resolution: Unresolved Votes: 0
Labels: not-10.5+, regression


 Description   

--source include/have_innodb.inc
 
CREATE TABLE t (id INT, f BLOB UNIQUE) ENGINE=InnoDB;
INSERT INTO t VALUES (1,'foo');
UPDATE t SET id = 2;
--source include/restart_mysqld.inc
--sleep 1
UPDATE t SET id = 3;
--source include/restart_mysqld.inc
 
# Cleanup
DROP TABLE t;

Imitation for 10.3

--source include/have_innodb.inc
 
CREATE TABLE t (id INT, f BLOB, fv BLOB AS (LEFT(f, 20)) INVISIBLE, KEY(fv(20))) ENGINE=InnoDB;
INSERT INTO t VALUES (1,'foo');
UPDATE t SET id = 2;
 
--source include/restart_mysqld.inc
--sleep 1
UPDATE t SET id = 3;
--source include/restart_mysqld.inc
 
# Cleanup
DROP TABLE t;

10.4 b05218e0

==36327==ERROR: LeakSanitizer: detected memory leaks
 
Direct leak of 120 byte(s) in 1 object(s) allocated from:
    #0 0x7f7cfd7998f7 in operator new(unsigned long, std::nothrow_t const&) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:105
    #1 0x55efeecb226a in ha_innobase::open(char const*, int, unsigned int) /src/storage/innobase/handler/ha_innodb.cc:6313
    #2 0x55efee32b8c3 in handler::ha_open(TABLE*, char const*, int, unsigned int, st_mem_root*, List<String>*) /src/sql/handler.cc:2811
    #3 0x55efedead924 in open_table_from_share(THD*, TABLE_SHARE*, st_mysql_const_lex_string const*, unsigned int, unsigned int, unsigned int, TABLE*, bool, List<String>*) /src/sql/table.cc:4176
    #4 0x55efeda0c1f9 in open_table(THD*, TABLE_LIST*, Open_table_context*) /src/sql/sql_base.cc:2109
    #5 0x55efeda94dde in open_purge_table(THD*, char const*, unsigned long, char const*, unsigned long) /src/sql/sql_class.cc:4929
    #6 0x55efeecf2e2f in innodb_acquire_mdl /src/storage/innobase/handler/ha_innodb.cc:20573
    #7 0x55efeecf342a in innodb_find_table_for_vc /src/storage/innobase/handler/ha_innodb.cc:20649
    #8 0x55efeecf391d in innobase_init_vc_templ(dict_table_t*) /src/storage/innobase/handler/ha_innodb.cc:20683
    #9 0x55efef073a69 in row_purge_parse_undo_rec /src/storage/innobase/row/row0purge.cc:1250
    #10 0x55efef074da7 in row_purge /src/storage/innobase/row/row0purge.cc:1395
    #11 0x55efef0753c7 in row_purge_step(que_thr_t*) /src/storage/innobase/row/row0purge.cc:1476
    #12 0x55efeef47bba in que_thr_step /src/storage/innobase/que/que0que.cc:966
    #13 0x55efeef47ff1 in que_run_threads_low /src/storage/innobase/que/que0que.cc:1028
    #14 0x55efeef48417 in que_run_threads(que_thr_t*) /src/storage/innobase/que/que0que.cc:1068
    #15 0x55efef15fa5e in trx_purge(unsigned long, bool, srv_slot_t*) /src/storage/innobase/trx/trx0purge.cc:1297
    #16 0x55efef0fe7d0 in srv_do_purge /src/storage/innobase/srv/srv0srv.cc:2580
    #17 0x55efef0ff140 in srv_purge_coordinator_thread /src/storage/innobase/srv/srv0srv.cc:2721
    #18 0x7f7cfd1c4ea6 in start_thread nptl/pthread_create.c:477
 
Indirect leak of 144 byte(s) in 1 object(s) allocated from:
    #0 0x7f7cfd797e8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55efeecb03d5 in innobase_build_v_templ(TABLE const*, dict_table_t const*, dict_vcol_templ_t*, dict_add_v_col_t const*, bool) /src/storage/innobase/handler/ha_innodb.cc:5979
    #2 0x55efeecb230d in ha_innobase::open(char const*, int, unsigned int) /src/storage/innobase/handler/ha_innodb.cc:6314
    #3 0x55efee32b8c3 in handler::ha_open(TABLE*, char const*, int, unsigned int, st_mem_root*, List<String>*) /src/sql/handler.cc:2811
    #4 0x55efedead924 in open_table_from_share(THD*, TABLE_SHARE*, st_mysql_const_lex_string const*, unsigned int, unsigned int, unsigned int, TABLE*, bool, List<String>*) /src/sql/table.cc:4176
    #5 0x55efeda0c1f9 in open_table(THD*, TABLE_LIST*, Open_table_context*) /src/sql/sql_base.cc:2109
    #6 0x55efeda94dde in open_purge_table(THD*, char const*, unsigned long, char const*, unsigned long) /src/sql/sql_class.cc:4929
    #7 0x55efeecf2e2f in innodb_acquire_mdl /src/storage/innobase/handler/ha_innodb.cc:20573
    #8 0x55efeecf342a in innodb_find_table_for_vc /src/storage/innobase/handler/ha_innodb.cc:20649
    #9 0x55efeecf391d in innobase_init_vc_templ(dict_table_t*) /src/storage/innobase/handler/ha_innodb.cc:20683
    #10 0x55efef073a69 in row_purge_parse_undo_rec /src/storage/innobase/row/row0purge.cc:1250
    #11 0x55efef074da7 in row_purge /src/storage/innobase/row/row0purge.cc:1395
    #12 0x55efef0753c7 in row_purge_step(que_thr_t*) /src/storage/innobase/row/row0purge.cc:1476
    #13 0x55efeef47bba in que_thr_step /src/storage/innobase/que/que0que.cc:966
    #14 0x55efeef47ff1 in que_run_threads_low /src/storage/innobase/que/que0que.cc:1028
    #15 0x55efeef48417 in que_run_threads(que_thr_t*) /src/storage/innobase/que/que0que.cc:1068
    #16 0x55efef15fa5e in trx_purge(unsigned long, bool, srv_slot_t*) /src/storage/innobase/trx/trx0purge.cc:1297
    #17 0x55efef0fe7d0 in srv_do_purge /src/storage/innobase/srv/srv0srv.cc:2580
    #18 0x55efef0ff140 in srv_purge_coordinator_thread /src/storage/innobase/srv/srv0srv.cc:2721
    #19 0x7f7cfd1c4ea6 in start_thread nptl/pthread_create.c:477
 
Indirect leak of 144 byte(s) in 1 object(s) allocated from:
    #0 0x7f7cfd797e8f in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55efeecb0861 in innobase_build_v_templ(TABLE const*, dict_table_t const*, dict_vcol_templ_t*, dict_add_v_col_t const*, bool) /src/storage/innobase/handler/ha_innodb.cc:6005
    #2 0x55efeecb230d in ha_innobase::open(char const*, int, unsigned int) /src/storage/innobase/handler/ha_innodb.cc:6314
    #3 0x55efee32b8c3 in handler::ha_open(TABLE*, char const*, int, unsigned int, st_mem_root*, List<String>*) /src/sql/handler.cc:2811
    #4 0x55efedead924 in open_table_from_share(THD*, TABLE_SHARE*, st_mysql_const_lex_string const*, unsigned int, unsigned int, unsigned int, TABLE*, bool, List<String>*) /src/sql/table.cc:4176
    #5 0x55efeda0c1f9 in open_table(THD*, TABLE_LIST*, Open_table_context*) /src/sql/sql_base.cc:2109
    #6 0x55efeda94dde in open_purge_table(THD*, char const*, unsigned long, char const*, unsigned long) /src/sql/sql_class.cc:4929
    #7 0x55efeecf2e2f in innodb_acquire_mdl /src/storage/innobase/handler/ha_innodb.cc:20573
    #8 0x55efeecf342a in innodb_find_table_for_vc /src/storage/innobase/handler/ha_innodb.cc:20649
    #9 0x55efeecf391d in innobase_init_vc_templ(dict_table_t*) /src/storage/innobase/handler/ha_innodb.cc:20683
    #10 0x55efef073a69 in row_purge_parse_undo_rec /src/storage/innobase/row/row0purge.cc:1250
    #11 0x55efef074da7 in row_purge /src/storage/innobase/row/row0purge.cc:1395
    #12 0x55efef0753c7 in row_purge_step(que_thr_t*) /src/storage/innobase/row/row0purge.cc:1476
    #13 0x55efeef47bba in que_thr_step /src/storage/innobase/que/que0que.cc:966
    #14 0x55efeef47ff1 in que_run_threads_low /src/storage/innobase/que/que0que.cc:1028
    #15 0x55efeef48417 in que_run_threads(que_thr_t*) /src/storage/innobase/que/que0que.cc:1068
    #16 0x55efef15fa5e in trx_purge(unsigned long, bool, srv_slot_t*) /src/storage/innobase/trx/trx0purge.cc:1297
    #17 0x55efef0fe7d0 in srv_do_purge /src/storage/innobase/srv/srv0srv.cc:2580
    #18 0x55efef0ff140 in srv_purge_coordinator_thread /src/storage/innobase/srv/srv0srv.cc:2721
    #19 0x7f7cfd1c4ea6 in start_thread nptl/pthread_create.c:477
 
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x7f7cfd798037 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x55efeecaf858 in innobase_build_v_templ(TABLE const*, dict_table_t const*, dict_vcol_templ_t*, dict_add_v_col_t const*, bool) /src/storage/innobase/handler/ha_innodb.cc:5919
    #2 0x55efeecb230d in ha_innobase::open(char const*, int, unsigned int) /src/storage/innobase/handler/ha_innodb.cc:6314
    #3 0x55efee32b8c3 in handler::ha_open(TABLE*, char const*, int, unsigned int, st_mem_root*, List<String>*) /src/sql/handler.cc:2811
    #4 0x55efedead924 in open_table_from_share(THD*, TABLE_SHARE*, st_mysql_const_lex_string const*, unsigned int, unsigned int, unsigned int, TABLE*, bool, List<String>*) /src/sql/table.cc:4176
    #5 0x55efeda0c1f9 in open_table(THD*, TABLE_LIST*, Open_table_context*) /src/sql/sql_base.cc:2109
    #6 0x55efeda94dde in open_purge_table(THD*, char const*, unsigned long, char const*, unsigned long) /src/sql/sql_class.cc:4929
    #7 0x55efeecf2e2f in innodb_acquire_mdl /src/storage/innobase/handler/ha_innodb.cc:20573
    #8 0x55efeecf342a in innodb_find_table_for_vc /src/storage/innobase/handler/ha_innodb.cc:20649
    #9 0x55efeecf391d in innobase_init_vc_templ(dict_table_t*) /src/storage/innobase/handler/ha_innodb.cc:20683
    #10 0x55efef073a69 in row_purge_parse_undo_rec /src/storage/innobase/row/row0purge.cc:1250
    #11 0x55efef074da7 in row_purge /src/storage/innobase/row/row0purge.cc:1395
    #12 0x55efef0753c7 in row_purge_step(que_thr_t*) /src/storage/innobase/row/row0purge.cc:1476
    #13 0x55efeef47bba in que_thr_step /src/storage/innobase/que/que0que.cc:966
    #14 0x55efeef47ff1 in que_run_threads_low /src/storage/innobase/que/que0que.cc:1028
    #15 0x55efeef48417 in que_run_threads(que_thr_t*) /src/storage/innobase/que/que0que.cc:1068
    #16 0x55efef15fa5e in trx_purge(unsigned long, bool, srv_slot_t*) /src/storage/innobase/trx/trx0purge.cc:1297
    #17 0x55efef0fe7d0 in srv_do_purge /src/storage/innobase/srv/srv0srv.cc:2580
    #18 0x55efef0ff140 in srv_purge_coordinator_thread /src/storage/innobase/srv/srv0srv.cc:2721
    #19 0x7f7cfd1c4ea6 in start_thread nptl/pthread_create.c:477
 
Indirect leak of 23 byte(s) in 1 object(s) allocated from:
    #0 0x7f7cfd799a07 in operator new[](unsigned long, std::nothrow_t const&) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:108
    #1 0x55efeecaf9a6 in innobase_build_v_templ(TABLE const*, dict_table_t const*, dict_vcol_templ_t*, dict_add_v_col_t const*, bool) /src/storage/innobase/handler/ha_innodb.cc:5924
    #2 0x55efeecb230d in ha_innobase::open(char const*, int, unsigned int) /src/storage/innobase/handler/ha_innodb.cc:6314
    #3 0x55efee32b8c3 in handler::ha_open(TABLE*, char const*, int, unsigned int, st_mem_root*, List<String>*) /src/sql/handler.cc:2811
    #4 0x55efedead924 in open_table_from_share(THD*, TABLE_SHARE*, st_mysql_const_lex_string const*, unsigned int, unsigned int, unsigned int, TABLE*, bool, List<String>*) /src/sql/table.cc:4176
    #5 0x55efeda0c1f9 in open_table(THD*, TABLE_LIST*, Open_table_context*) /src/sql/sql_base.cc:2109
    #6 0x55efeda94dde in open_purge_table(THD*, char const*, unsigned long, char const*, unsigned long) /src/sql/sql_class.cc:4929
    #7 0x55efeecf2e2f in innodb_acquire_mdl /src/storage/innobase/handler/ha_innodb.cc:20573
    #8 0x55efeecf342a in innodb_find_table_for_vc /src/storage/innobase/handler/ha_innodb.cc:20649
    #9 0x55efeecf391d in innobase_init_vc_templ(dict_table_t*) /src/storage/innobase/handler/ha_innodb.cc:20683
    #10 0x55efef073a69 in row_purge_parse_undo_rec /src/storage/innobase/row/row0purge.cc:1250
    #11 0x55efef074da7 in row_purge /src/storage/innobase/row/row0purge.cc:1395
    #12 0x55efef0753c7 in row_purge_step(que_thr_t*) /src/storage/innobase/row/row0purge.cc:1476
    #13 0x55efeef47bba in que_thr_step /src/storage/innobase/que/que0que.cc:966
    #14 0x55efeef47ff1 in que_run_threads_low /src/storage/innobase/que/que0que.cc:1028
    #15 0x55efeef48417 in que_run_threads(que_thr_t*) /src/storage/innobase/que/que0que.cc:1068
    #16 0x55efef15fa5e in trx_purge(unsigned long, bool, srv_slot_t*) /src/storage/innobase/trx/trx0purge.cc:1297
    #17 0x55efef0fe7d0 in srv_do_purge /src/storage/innobase/srv/srv0srv.cc:2580
    #18 0x55efef0ff140 in srv_purge_coordinator_thread /src/storage/innobase/srv/srv0srv.cc:2721
    #19 0x7f7cfd1c4ea6 in start_thread nptl/pthread_create.c:477
 
SUMMARY: AddressSanitizer: 455 byte(s) leaked in 5 allocation(s).

The failure appeared in 10.3 after this commit:

commit d08f2ab6d61b1b431be3c003c4ecc9495faebffc
Author: Sergei Golubchik
Date:   Tue Nov 1 19:50:20 2022 +0100
 
    MDEV-28855 SEGV around dict_free_vc_templ during DROP INDEX

Not reproducible on 10.5+, and it's probably not worth fixing in 10.3 this close to EOL, so it's 10.4-only, hence minor.



 Comments   
Comment by Marko Mäkelä [ 2023-02-04 ]

We appear to leak ib_table->vc_templ:

        if (ib_table->n_v_cols) {
                mutex_enter(&dict_sys.mutex);
                if (ib_table->vc_templ == NULL) {
                        ib_table->vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t());
                        innobase_build_v_templ(
                                table, ib_table, ib_table->vc_templ, NULL,
                                true);
                }
 
                mutex_exit(&dict_sys.mutex);
        }

Something related to this was changed in 10.3 by serg and applied to 10.4 as part of my merge. This memory leak could be an unforeseen interaction caused by MDEV-371 (introduced in 10.4), which causes hidden indexed virtual columns to be defined on BLOBs.

It might be possible to reproduce this leak on 10.3 by explicitly defining an indexed virtual column similar to what MDEV-371 does.

Comment by Elena Stepanova [ 2023-02-04 ]

Thanks. I have edited the description to add a 10.3-applicable test case, forgot to try that while filing.
Also added the commit which brought the failure: d08f2ab6d

Generated at Thu Feb 08 10:17:12 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.