summaryrefslogtreecommitdiff
path: root/sql/sql_list.h
diff options
context:
space:
mode:
authorSachin <sachin.setiya@mariadb.com>2018-08-07 16:05:48 +0530
committerSachin <sachin.setiya@mariadb.com>2018-08-07 22:36:37 +0530
commit482d4da0a7a7f76e8ea9026978d49565f57a4192 (patch)
tree01c489934d37ece1061270016d48a70ade49598f /sql/sql_list.h
parent4cbadaeaea5b47a128b2ddf8ca487dbfd978227d (diff)
downloadmariadb-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.h5
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; }