summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-12-17 16:33:23 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-12-17 17:10:42 +0200
commit10e01b56f734d306897d2a59d091e6c421943e6b (patch)
tree56afffde928244462548b1898d5d784e0262bc7c
parent32eeed21297f0e5a2836daca058e38dbe3a82bc4 (diff)
downloadmariadb-git-10e01b56f734d306897d2a59d091e6c421943e6b.tar.gz
Fix USE_AFTER_FREE (CWE-416)
A static analysis tool suggested that in the function row_merge_read_clustered_index(), ut_free(nonnull) could be invoked twice for nonnull!=NULL. While a manual review of the code disproved this, it should not hurt to clean up the code so that the static analysis tool will not complain. index_tuple_info_t::insert(), row_mtuple_cmp(): Remove the parameter mtr_committed, which duplicated !mtr->is_active(). row_merge_read_clustered_index(): Initialize row_heap = NULL. Remove a duplicated call mem_heap_empty(row_heap) that was inadvertently added in commit cb1e76e4de120d20064a96be4fcc245c3d22bd78. Replace a "goto func_exit" with "break", to get consistent error handling for both failures to create or write a temporary file. end_of_index: Assign row_heap=NULL and nonnull=NULL to prevent double freeing. func_exit: Check for row_heap!=NULL before invoking mem_heap_free(). Closes #959
-rw-r--r--storage/innobase/row/row0merge.cc64
1 files changed, 25 insertions, 39 deletions
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index f623cfb6df4..c1ee3d29ce1 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -115,14 +115,12 @@ public:
@param[in,out] row_heap memory heap
@param[in] pcur cluster index scanning cursor
@param[in,out] scan_mtr mini-transaction for pcur
- @param[out] mtr_committed whether scan_mtr got committed
@return DB_SUCCESS if successful, else error number */
- dberr_t insert(
+ inline dberr_t insert(
trx_id_t trx_id,
mem_heap_t* row_heap,
btr_pcur_t* pcur,
- mtr_t* scan_mtr,
- bool* mtr_committed)
+ mtr_t* scan_mtr)
{
big_rec_t* big_rec;
rec_t* rec;
@@ -150,11 +148,10 @@ public:
ut_ad(dtuple);
if (log_sys->check_flush_or_checkpoint) {
- if (!(*mtr_committed)) {
+ if (scan_mtr->is_active()) {
btr_pcur_move_to_prev_on_page(pcur);
btr_pcur_store_position(pcur, scan_mtr);
- mtr_commit(scan_mtr);
- *mtr_committed = true;
+ scan_mtr->commit();
}
log_free_check();
@@ -1589,7 +1586,6 @@ row_mtuple_cmp(
@param[in,out] sp_heap heap for tuples
@param[in,out] pcur cluster index cursor
@param[in,out] mtr mini transaction
-@param[in,out] mtr_committed whether scan_mtr got committed
@return DB_SUCCESS or error number */
static
dberr_t
@@ -1600,8 +1596,7 @@ row_merge_spatial_rows(
mem_heap_t* row_heap,
mem_heap_t* sp_heap,
btr_pcur_t* pcur,
- mtr_t* mtr,
- bool* mtr_committed)
+ mtr_t* mtr)
{
dberr_t err = DB_SUCCESS;
@@ -1612,9 +1607,7 @@ row_merge_spatial_rows(
ut_ad(sp_heap != NULL);
for (ulint j = 0; j < num_spatial; j++) {
- err = sp_tuples[j]->insert(
- trx_id, row_heap,
- pcur, mtr, mtr_committed);
+ err = sp_tuples[j]->insert(trx_id, row_heap, pcur, mtr);
if (err != DB_SUCCESS) {
return(err);
@@ -1716,7 +1709,7 @@ row_merge_read_clustered_index(
struct TABLE* eval_table)
{
dict_index_t* clust_index; /* Clustered index */
- mem_heap_t* row_heap; /* Heap memory to create
+ mem_heap_t* row_heap = NULL;/* Heap memory to create
clustered index tuples */
row_merge_buf_t** merge_buf; /* Temporary list for records*/
mem_heap_t* v_heap = NULL; /* Heap memory to process large
@@ -1903,22 +1896,19 @@ row_merge_read_clustered_index(
/* Scan the clustered index. */
for (;;) {
- const rec_t* rec;
- ulint* offsets;
- const dtuple_t* row;
- row_ext_t* ext;
- page_cur_t* cur = btr_pcur_get_page_cur(&pcur);
-
- mem_heap_empty(row_heap);
-
/* Do not continue if table pages are still encrypted */
- if (!old_table->is_readable() ||
- !new_table->is_readable()) {
+ if (!old_table->is_readable() || !new_table->is_readable()) {
err = DB_DECRYPTION_FAILED;
trx->error_key_num = 0;
goto func_exit;
}
+ const rec_t* rec;
+ ulint* offsets;
+ const dtuple_t* row;
+ row_ext_t* ext;
+ page_cur_t* cur = btr_pcur_get_page_cur(&pcur);
+
mem_heap_empty(row_heap);
page_cur_move_to_next(cur);
@@ -1953,18 +1943,15 @@ row_merge_read_clustered_index(
dbug_run_purge = true;);
/* Insert the cached spatial index rows. */
- bool mtr_committed = false;
-
err = row_merge_spatial_rows(
trx->id, sp_tuples, num_spatial,
- row_heap, sp_heap, &pcur,
- &mtr, &mtr_committed);
+ row_heap, sp_heap, &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
}
- if (mtr_committed) {
+ if (!mtr.is_active()) {
goto scan_next;
}
@@ -2019,7 +2006,9 @@ end_of_index:
row = NULL;
mtr_commit(&mtr);
mem_heap_free(row_heap);
+ row_heap = NULL;
ut_free(nonnull);
+ nonnull = NULL;
goto write_buffers;
}
} else {
@@ -2347,8 +2336,6 @@ write_buffers:
/* Temporary File is not used.
so insert sorted block to the index */
if (row != NULL) {
- bool mtr_committed = false;
-
/* We have to do insert the
cached spatial index rows, since
after the mtr_commit, the cluster
@@ -2359,8 +2346,7 @@ write_buffers:
trx->id, sp_tuples,
num_spatial,
row_heap, sp_heap,
- &pcur, &mtr,
- &mtr_committed);
+ &pcur, &mtr);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -2375,13 +2361,13 @@ write_buffers:
current row will be invalid, and
we must reread it on the next
loop iteration. */
- if (!mtr_committed) {
+ if (mtr.is_active()) {
btr_pcur_move_to_prev_on_page(
&pcur);
btr_pcur_store_position(
&pcur, &mtr);
- mtr_commit(&mtr);
+ mtr.commit();
}
}
@@ -2536,7 +2522,7 @@ write_buffers:
buf->n_tuples, path) < 0) {
err = DB_OUT_OF_MEMORY;
trx->error_key_num = i;
- goto func_exit;
+ break;
}
/* Ensure that duplicates in the
@@ -2614,12 +2600,12 @@ write_buffers:
}
func_exit:
- /* row_merge_spatial_rows may have committed
- the mtr before an error occurs. */
if (mtr.is_active()) {
mtr_commit(&mtr);
}
- mem_heap_free(row_heap);
+ if (row_heap) {
+ mem_heap_free(row_heap);
+ }
ut_free(nonnull);
all_done: