Commit cd156e2c authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-20971 ASAN heap-use-after-free in list_delete / heap_close

Don't save/restore HP_INFO as it could be changed by a concurrent thread.
different parts of HP_INFO are protected by different mutexes and
the mutex that protect most of the HP_INFO does not protect its open_list
data.

As a bonus, make heap_check_heap() to take const HP_INFO* and not
make any changes there whatsoever.
parent 9277b6ec
...@@ -245,7 +245,7 @@ int hp_panic(enum ha_panic_function flag); ...@@ -245,7 +245,7 @@ int hp_panic(enum ha_panic_function flag);
int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key, int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key,
key_part_map keypart_map, enum ha_rkey_function find_flag); key_part_map keypart_map, enum ha_rkey_function find_flag);
extern uchar * heap_find(HP_INFO *info,int inx,const uchar *key); extern uchar * heap_find(HP_INFO *info,int inx,const uchar *key);
extern int heap_check_heap(HP_INFO *info, my_bool print_status); extern int heap_check_heap(const HP_INFO *info, my_bool print_status);
extern uchar *heap_position(HP_INFO *info); extern uchar *heap_position(HP_INFO *info);
/* The following is for programs that uses the old HEAP interface where /* The following is for programs that uses the old HEAP interface where
......
...@@ -18,10 +18,8 @@ ...@@ -18,10 +18,8 @@
#include "heapdef.h" #include "heapdef.h"
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, static int check_one_key(HP_KEYDEF *, uint, ulong, ulong, my_bool);
ulong blength, my_bool print_status); static int check_one_rb_key(const HP_INFO *, uint, ulong, my_bool);
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
my_bool print_status);
/* /*
...@@ -40,13 +38,13 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, ...@@ -40,13 +38,13 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
1 error 1 error
*/ */
int heap_check_heap(HP_INFO *info, my_bool print_status) int heap_check_heap(const HP_INFO *info, my_bool print_status)
{ {
int error; int error;
uint key; uint key;
ulong records=0, deleted=0, pos, next_block; ulong records=0, deleted=0, pos, next_block;
HP_SHARE *share=info->s; HP_SHARE *share=info->s;
HP_INFO save_info= *info; /* Needed because scan_init */ uchar *current_ptr= info->current_ptr;
DBUG_ENTER("heap_check_heap"); DBUG_ENTER("heap_check_heap");
for (error=key= 0 ; key < share->keys ; key++) for (error=key= 0 ; key < share->keys ; key++)
...@@ -65,7 +63,7 @@ int heap_check_heap(HP_INFO *info, my_bool print_status) ...@@ -65,7 +63,7 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
{ {
if (pos < next_block) if (pos < next_block)
{ {
info->current_ptr+= share->block.recbuffer; current_ptr+= share->block.recbuffer;
} }
else else
{ {
...@@ -77,9 +75,9 @@ int heap_check_heap(HP_INFO *info, my_bool print_status) ...@@ -77,9 +75,9 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
break; /* End of file */ break; /* End of file */
} }
} }
hp_find_record(info,pos); current_ptr= hp_find_block(&share->block, pos);
if (!info->current_ptr[share->visible]) if (!current_ptr[share->visible])
deleted++; deleted++;
else else
records++; records++;
...@@ -92,7 +90,6 @@ int heap_check_heap(HP_INFO *info, my_bool print_status) ...@@ -92,7 +90,6 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
deleted, (ulong) share->deleted)); deleted, (ulong) share->deleted));
error= 1; error= 1;
} }
*info= save_info;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -165,7 +162,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, ...@@ -165,7 +162,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
return error; return error;
} }
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, static int check_one_rb_key(const HP_INFO *info, uint keynr, ulong records,
my_bool print_status) my_bool print_status)
{ {
HP_KEYDEF *keydef= info->s->keydef + keynr; HP_KEYDEF *keydef= info->s->keydef + keynr;
...@@ -174,9 +171,11 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, ...@@ -174,9 +171,11 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
uchar *key, *recpos; uchar *key, *recpos;
uint key_length; uint key_length;
uint not_used[2]; uint not_used[2];
TREE_ELEMENT **last_pos;
TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1];
if ((key= tree_search_edge(&keydef->rb_tree, info->parents, if ((key= tree_search_edge(&keydef->rb_tree, parents,
&info->last_pos, offsetof(TREE_ELEMENT, left)))) &last_pos, offsetof(TREE_ELEMENT, left))))
{ {
do do
{ {
...@@ -191,7 +190,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records, ...@@ -191,7 +190,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
} }
else else
found++; found++;
key= tree_search_next(&keydef->rb_tree, &info->last_pos, key= tree_search_next(&keydef->rb_tree, &last_pos,
offsetof(TREE_ELEMENT, left), offsetof(TREE_ELEMENT, left),
offsetof(TREE_ELEMENT, right)); offsetof(TREE_ELEMENT, right));
} while (key); } while (key);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment