Skip to content

Commit 4fa8dd1

Browse files
author
Ajo Robert
committed
Bug#35395965 heap-use-after-free with functions, procedure
and Item_func_in::populate_bisection As part of a performance improvement, m_const_array is introduced to save IN list items across execution. This list is populated either at the end of preparation or at the start of execution based on the nature of its objects. Some of its elements (String class object) have memory allocated from runtime memory (example: input constants) that are not valid after the end of the current execution. Ownership of such memory is not passed to the String object at the assignment. But reuse is attempted in subsequent runs that can lead to unexpected behavior. Fix: Release all runtime memory and cleanup pointers in m_const_array at the end of statement execution. Change-Id: Ib56b047c54b1b0d9428e9ed515e097ab4e0d5e4d
1 parent fc524be commit 4fa8dd1

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

sql/item_cmpfunc.cc

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4375,22 +4375,24 @@ in_string::in_string(MEM_ROOT *mem_root, uint elements, const CHARSET_INFO *cs)
43754375
}
43764376
}
43774377

4378+
void in_string::cleanup() {
4379+
// Clear reference pointers and free any memory allocated for holding data.
4380+
for (uint i = 0; i < m_used_size; i++) {
4381+
String *str = base_pointers[i];
4382+
str->set(static_cast<const char *>(nullptr), 0, str->charset());
4383+
}
4384+
}
4385+
43784386
void in_string::set(uint pos, Item *item) {
43794387
String *str = base_pointers[pos];
43804388
String *res = eval_string_arg(collation, item, str);
4381-
if (res && res != str) {
4382-
if (res->uses_buffer_owned_by(str)) res->copy();
4383-
if (item->type() == Item::FUNC_ITEM)
4384-
str->copy(*res);
4385-
else
4386-
*str = *res;
4387-
}
4388-
if (!str->charset()) {
4389-
const CHARSET_INFO *cs;
4390-
if (!(cs = item->collation.collation))
4391-
cs = &my_charset_bin; // Should never happen for STR items
4392-
str->set_charset(cs);
4393-
}
4389+
if (res == nullptr || res == str) return;
4390+
4391+
if (res->uses_buffer_owned_by(str)) res->copy();
4392+
if (item->type() == Item::FUNC_ITEM)
4393+
str->copy(*res);
4394+
else
4395+
*str = *res;
43944396
}
43954397

43964398
static int srtcmp_in(const CHARSET_INFO *cs, const String *x, const String *y) {
@@ -5371,7 +5373,10 @@ void Item_func_in::cleanup() {
53715373
DBUG_TRACE;
53725374
Item_int_func::cleanup();
53735375
// Trigger re-population in next execution (if bisection is used)
5374-
if (m_need_populate) m_populated = false;
5376+
if (m_need_populate) {
5377+
if (m_const_array != nullptr) m_const_array->cleanup();
5378+
m_populated = false;
5379+
}
53755380

53765381
if (!first_resolve_call) {
53775382
/*

sql/item_cmpfunc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,7 @@ class in_vector {
16291629
@return true if any null values was found, false otherwise.
16301630
*/
16311631
bool fill(Item **items, uint item_count);
1632+
virtual void cleanup() {}
16321633

16331634
private:
16341635
virtual void set(uint pos, Item *item) = 0;
@@ -1655,6 +1656,7 @@ class in_string final : public in_vector {
16551656
}
16561657
bool find_item(Item *item) override;
16571658
bool compare_elems(uint pos1, uint pos2) const override;
1659+
void cleanup() override;
16581660

16591661
private:
16601662
void set(uint pos, Item *item) override;

0 commit comments

Comments
 (0)