Skip to content

Commit 32f66e1

Browse files
gurusamidahlerlend
authored andcommitted
Bug #28039477 SERVER CRASHES AT CHECKPOINT TIME
Problem: The function btr_cur_pessimistic_update() takes two mem_heap_t objects. One heap contains the dtuple_t object and this heap should not be emptied, while the other heap contains temporary stuff and can be emptied. This function was wrongly used in the DDTableBuffer::replace() routine by passing the same heap. Since it was getting emptied, there was subsequently a "memory use after free" problem. Solution: Pass two separate memory heap objects to btr_cur_pessimistic_update(). rb#19781 approved by Bin Su.
1 parent 54a0ac5 commit 32f66e1

File tree

5 files changed

+20
-3
lines changed

5 files changed

+20
-3
lines changed

storage/innobase/btr/btr0btr.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,6 +2350,7 @@ rec_t *btr_page_split_and_insert(
23502350
}
23512351
n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
23522352
func_start:
2353+
ut_ad(tuple->m_heap != *heap);
23532354
mem_heap_empty(*heap);
23542355
*offsets = NULL;
23552356

storage/innobase/dict/dict0dict.cc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6380,6 +6380,7 @@ void DDTableBuffer::init() {
63806380

63816381
m_heap = mem_heap_create(500);
63826382
m_dynamic_heap = mem_heap_create(1000);
6383+
m_replace_heap = mem_heap_create(1000);
63836384

63846385
create_tuples();
63856386
}
@@ -6478,6 +6479,7 @@ void DDTableBuffer::init_tuple_with_id(dtuple_t *tuple, table_id_t id) {
64786479
void DDTableBuffer::close() {
64796480
mem_heap_free(m_heap);
64806481
mem_heap_free(m_dynamic_heap);
6482+
mem_heap_free(m_replace_heap);
64816483

64826484
m_search_tuple = NULL;
64836485
m_replace_tuple = NULL;
@@ -6516,7 +6518,7 @@ upd_t *DDTableBuffer::update_set_metadata(const dtuple_t *entry,
65166518
return (nullptr);
65176519
}
65186520

6519-
update = upd_create(2, m_dynamic_heap);
6521+
update = upd_create(2, m_replace_heap);
65206522

65216523
upd_field = upd_get_nth_field(update, 0);
65226524
dfield_copy(&upd_field->new_val, version_field);
@@ -6558,7 +6560,7 @@ dberr_t DDTableBuffer::replace(table_id_t id, uint64_t version,
65586560
dfield_set_data(dfield, metadata, len);
65596561
/* Other system fields have been initialized */
65606562

6561-
entry = row_build_index_entry(m_replace_tuple, NULL, m_index, m_dynamic_heap);
6563+
entry = row_build_index_entry(m_replace_tuple, NULL, m_index, m_replace_heap);
65626564

65636565
/* Start to search for the to-be-replaced tuple */
65646566
mtr.start();
@@ -6581,6 +6583,7 @@ dberr_t DDTableBuffer::replace(table_id_t id, uint64_t version,
65816583
ut_a(error == DB_SUCCESS);
65826584

65836585
mem_heap_empty(m_dynamic_heap);
6586+
mem_heap_empty(m_replace_heap);
65846587

65856588
return (DB_SUCCESS);
65866589
}
@@ -6599,14 +6602,15 @@ dberr_t DDTableBuffer::replace(table_id_t id, uint64_t version,
65996602

66006603
error = btr_cur_pessimistic_update(
66016604
flags, btr_pcur_get_btr_cur(&pcur), &cur_offsets, &m_dynamic_heap,
6602-
m_dynamic_heap, &big_rec, update, 0, NULL, 0, 0, &mtr);
6605+
m_replace_heap, &big_rec, update, 0, NULL, 0, 0, &mtr);
66036606
ut_a(error == DB_SUCCESS);
66046607
/* We don't have big rec in this table */
66056608
ut_ad(!big_rec);
66066609
}
66076610

66086611
mtr.commit();
66096612
mem_heap_empty(m_dynamic_heap);
6613+
mem_heap_empty(m_replace_heap);
66106614

66116615
return (DB_SUCCESS);
66126616
}

storage/innobase/include/data0data.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ struct dtuple_t {
476476
/*!< data tuples can be linked into a
477477
list using this field */
478478
#ifdef UNIV_DEBUG
479+
480+
/** memory heap where this tuple is allocated. */
481+
mem_heap_t *m_heap;
482+
479483
ulint magic_n; /*!< magic number, used in
480484
debug assertions */
481485
/** Value of dtuple_t::magic_n */

storage/innobase/include/data0data.ic

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ dtuple_t *dtuple_create_with_vcol(mem_heap_t *heap, ulint n_fields,
466466

467467
tuple = dtuple_create_from_mem(buf, buf_size, n_fields, n_v_fields);
468468

469+
#ifdef UNIV_DEBUG
470+
tuple->m_heap = heap;
471+
#endif /* UNIV_DEBUG */
472+
469473
return (tuple);
470474
}
471475

storage/innobase/include/dict0dict.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,10 @@ class DDTableBuffer {
13651365
be freed before return */
13661366
mem_heap_t *m_dynamic_heap;
13671367

1368+
/** The heap used during replace() operation, which should always
1369+
be freed before return */
1370+
mem_heap_t *m_replace_heap;
1371+
13681372
/** The heap used to create the search tuple and replace tuple */
13691373
mem_heap_t *m_heap;
13701374

0 commit comments

Comments
 (0)