diff options
author | Michael Widenius <monty@mariadb.org> | 2014-07-31 13:13:33 +0300 |
---|---|---|
committer | Michael Widenius <monty@mariadb.org> | 2014-07-31 13:13:33 +0300 |
commit | 37ba4f37acce26488c7822cc321d6fb9aa6f4f73 (patch) | |
tree | e9ff4a8086bdac0b730933cb51e66a0f3465825e /storage/maria/ha_maria.cc | |
parent | a270e8abc4344654aaac1a6881cbb169165a3cf0 (diff) | |
download | mariadb-git-37ba4f37acce26488c7822cc321d6fb9aa6f4f73.tar.gz |
Fixed memory overflow
Diffstat (limited to 'storage/maria/ha_maria.cc')
-rw-r--r-- | storage/maria/ha_maria.cc | 84 |
1 files changed, 45 insertions, 39 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index d91c91c0376..4f784457740 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2809,7 +2809,8 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) TRN *trn; int error; uint locked_tables; - MARIA_SHARE **used_tables= 0; + DYNAMIC_ARRAY used_tables; + DBUG_ENTER("ha_maria::implicit_commit"); if (!maria_hton || !(trn= THD_TRN)) DBUG_RETURN(0); @@ -2825,32 +2826,37 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) DBUG_PRINT("info", ("locked_tables, skipping")); DBUG_RETURN(0); } - if ((locked_tables= trnman_has_locked_tables(trn))) + + locked_tables= trnman_has_locked_tables(trn); + + if (new_trn && trn && trn->used_tables) { - MARIA_SHARE **used_tables_end; MARIA_USED_TABLES *tables; - /* Save locked tables so that we can move them to another transaction */ + /* + Save locked tables so that we can move them to another transaction + We are using a dynamic array as locked_tables in some cases can be + smaller than the used_tables list (for example when the server does + early unlock of tables. + */ - used_tables= (MARIA_SHARE**) my_malloc((locked_tables+1) * - sizeof(MARIA_SHARE*), - MY_WME); - used_tables_end= used_tables; - if (!used_tables) - { - /* Continue using the old transaction; Should be safe in most cases */ - error= HA_ERR_OUT_OF_MEM; - goto end; - } - + my_init_dynamic_array2(&used_tables, sizeof(MARIA_SHARE*), (void*) 0, + locked_tables, 8); for (tables= (MARIA_USED_TABLES*) trn->used_tables; tables; tables= tables->next) { if (tables->share->base.born_transactional) - *used_tables_end++= tables->share; + { + if (insert_dynamic(&used_tables, (uchar*) &tables->share)) + { + error= HA_ERR_OUT_OF_MEM; + goto end_and_free; + } + } } - *used_tables_end= 0; // End marker } + else + bzero(&used_tables, sizeof(used_tables)); error= 0; if (unlikely(ma_commit(trn))) @@ -2875,7 +2881,7 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) if (unlikely(trn == NULL)) { error= HA_ERR_OUT_OF_MEM; - goto end; + goto end_and_free; } /* Move all locked tables to the new transaction @@ -2884,28 +2890,27 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) when we should call _ma_setup_live_state() and in some cases, like in check table, we use the table without calling start_stmt(). */ - if (used_tables) + + uint i; + for (i= 0 ; i < used_tables.elements ; i++) { - MARIA_SHARE **tables; - for (tables= used_tables; *tables ; tables++) - { - MARIA_SHARE *share= *tables; - LIST *handlers; + MARIA_SHARE *share; + LIST *handlers; - /* Find table instances that was used in this transaction */ - for (handlers= share->open_list; handlers; handlers= handlers->next) - { - MARIA_HA *handler= (MARIA_HA*) handlers->data; - if (handler->external_ref && - ((TABLE*) handler->external_ref)->in_use == thd) - { - _ma_set_trn_for_table(handler, trn); - /* If handler uses versioning */ - if (handler->s->lock_key_trees) - { - if (_ma_setup_live_state(handler)) - error= HA_ERR_OUT_OF_MEM; - } + share= *(dynamic_element(&used_tables, i, MARIA_SHARE**)); + /* Find table instances that was used in this transaction */ + for (handlers= share->open_list; handlers; handlers= handlers->next) + { + MARIA_HA *handler= (MARIA_HA*) handlers->data; + if (handler->external_ref && + ((TABLE*) handler->external_ref)->in_use == thd) + { + _ma_set_trn_for_table(handler, trn); + /* If handler uses versioning */ + if (handler->s->lock_key_trees) + { + if (_ma_setup_live_state(handler)) + error= HA_ERR_OUT_OF_MEM; } } } @@ -2913,8 +2918,9 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) /* This is just a commit, tables stay locked if they were: */ trnman_reset_locked_tables(trn, locked_tables); +end_and_free: + delete_dynamic(&used_tables); end: - my_free(used_tables); DBUG_RETURN(error); } |