diff options
author | Sachin <sachin.setiya@mariadb.com> | 2018-08-07 16:05:48 +0530 |
---|---|---|
committer | Sachin <sachin.setiya@mariadb.com> | 2018-08-07 22:36:37 +0530 |
commit | 482d4da0a7a7f76e8ea9026978d49565f57a4192 (patch) | |
tree | 01c489934d37ece1061270016d48a70ade49598f /sql/sql_list.h | |
parent | 4cbadaeaea5b47a128b2ddf8ca487dbfd978227d (diff) | |
download | mariadb-git-482d4da0a7a7f76e8ea9026978d49565f57a4192.tar.gz |
MDEV-15127 AddressSanitizer: stack-buffer-overflow in base_list::push_back ..
Problem:-
If we try to run this query with -WITH_ASAN=ON compiled server
CREATE TABLE t1 (i INT);
SET debug_dbug="+d,test_completely_invisible,test_invisible_index";
CREATE TABLE t2 LIKE t1;
This will generate a stack buffer overflow error.
==8922==ERROR: AddressSanitizer: stack-buffer-overflow on address #ADDR
Analyze:-
Error is generated on this line
if (((*last)=new list_node(info, &end_of_list)))
So info is our Key*, &end_of_list is global variable and last == #ADDR
So last is suspicious variable. And last is the variable present in alter_info
->key_list. Now the question is how this key_list->last gets wrong/
different stack variable. In the backtrace, we can see that key_list is
generated in mysql_create_table_like_table by calling
mysql_preapre_alter_table_function and dummy key_list is created by
mysql_create_like_table. In the end on mysql_prepare_alter_table we call
alter_info->key_list.swap(new_key_list);
So there is two options either key_list is empty or not empty , IF it is not
empty then there is no issues last ptr is replaced by thd->mem_root (allocated ptr)
So problem arises when key_list is empty. It swaps the dummy last ptr by
mysql_prepare_alter_table declared ptr. which is wrong.
Solution:-
We wont swap variable if list does not have any element.
Diffstat (limited to 'sql/sql_list.h')
-rw-r--r-- | sql/sql_list.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sql/sql_list.h b/sql/sql_list.h index 0219c226803..39a1c3375e0 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -278,10 +278,13 @@ public: */ inline void swap(base_list &rhs) { + list_node **rhs_last=rhs.last; swap_variables(list_node *, first, rhs.first); - swap_variables(list_node **, last, rhs.last); swap_variables(uint, elements, rhs.elements); + rhs.last= last == &first ? &rhs.first : last; + last = rhs_last == &rhs.first ? &first : rhs_last; } + inline list_node* last_node() { return *last; } inline list_node* first_node() { return first;} inline void *head() { return first->info; } |