Commit 4cb69791 authored by Michael Widenius's avatar Michael Widenius

Added detection of memory overwrite with multi_malloc

This detected two bugs in the code, which are both fixed
parent c00c12df
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
#include "mysys_priv.h" #include "mysys_priv.h"
#include <stdarg.h> #include <stdarg.h>
#ifndef DBUG_OFF
/* Put a protected barrier after every element when using my_multi_malloc() */
#define ALLOC_BARRIER
#endif
/* /*
Malloc many pointers at the same time Malloc many pointers at the same time
Only ptr1 can be free'd, and doing this will free all Only ptr1 can be free'd, and doing this will free all
...@@ -45,6 +50,9 @@ void* my_multi_malloc(PSI_memory_key key, myf myFlags, ...) ...@@ -45,6 +50,9 @@ void* my_multi_malloc(PSI_memory_key key, myf myFlags, ...)
{ {
length=va_arg(args,uint); length=va_arg(args,uint);
tot_length+=ALIGN_SIZE(length); tot_length+=ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
tot_length+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
...@@ -58,6 +66,10 @@ void* my_multi_malloc(PSI_memory_key key, myf myFlags, ...) ...@@ -58,6 +66,10 @@ void* my_multi_malloc(PSI_memory_key key, myf myFlags, ...)
*ptr=res; *ptr=res;
length=va_arg(args,uint); length=va_arg(args,uint);
res+=ALIGN_SIZE(length); res+=ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
TRASH_FREE(res, ALIGN_SIZE(1));
res+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
DBUG_RETURN((void*) start); DBUG_RETURN((void*) start);
...@@ -89,6 +101,9 @@ void *my_multi_malloc_large(PSI_memory_key key, myf myFlags, ...) ...@@ -89,6 +101,9 @@ void *my_multi_malloc_large(PSI_memory_key key, myf myFlags, ...)
{ {
length=va_arg(args,ulonglong); length=va_arg(args,ulonglong);
tot_length+=ALIGN_SIZE(length); tot_length+=ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
tot_length+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
...@@ -102,6 +117,10 @@ void *my_multi_malloc_large(PSI_memory_key key, myf myFlags, ...) ...@@ -102,6 +117,10 @@ void *my_multi_malloc_large(PSI_memory_key key, myf myFlags, ...)
*ptr=res; *ptr=res;
length=va_arg(args,ulonglong); length=va_arg(args,ulonglong);
res+=ALIGN_SIZE(length); res+=ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
TRASH_FREE(res, ALIGN_SIZE(1));
res+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
DBUG_RETURN((void*) start); DBUG_RETURN((void*) start);
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#ifndef DBUG_OFF
/* Put a protected barrier after every element when using multi_alloc_root() */
#define ALLOC_BARRIER
#endif
#undef EXTRA_DEBUG #undef EXTRA_DEBUG
#define EXTRA_DEBUG #define EXTRA_DEBUG
...@@ -396,6 +401,9 @@ void *multi_alloc_root(MEM_ROOT *root, ...) ...@@ -396,6 +401,9 @@ void *multi_alloc_root(MEM_ROOT *root, ...)
{ {
length= va_arg(args, uint); length= va_arg(args, uint);
tot_length+= ALIGN_SIZE(length); tot_length+= ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
tot_length+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
...@@ -409,6 +417,10 @@ void *multi_alloc_root(MEM_ROOT *root, ...) ...@@ -409,6 +417,10 @@ void *multi_alloc_root(MEM_ROOT *root, ...)
*ptr= res; *ptr= res;
length= va_arg(args, uint); length= va_arg(args, uint);
res+= ALIGN_SIZE(length); res+= ALIGN_SIZE(length);
#ifdef ALLOC_BARRIER
TRASH_FREE(res, ALIGN_SIZE(1));
res+= ALIGN_SIZE(1);
#endif
} }
va_end(args); va_end(args);
DBUG_RETURN((void*) start); DBUG_RETURN((void*) start);
......
...@@ -6276,6 +6276,7 @@ class TMP_TABLE_PARAM :public Sql_alloc ...@@ -6276,6 +6276,7 @@ class TMP_TABLE_PARAM :public Sql_alloc
@see opt_sum_query, count_field_types @see opt_sum_query, count_field_types
*/ */
uint sum_func_count; uint sum_func_count;
uint copy_func_count; // Allocated copy fields
uint hidden_field_count; uint hidden_field_count;
uint group_parts,group_length,group_null_parts; uint group_parts,group_length,group_null_parts;
uint quick_group; uint quick_group;
......
...@@ -5357,7 +5357,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, ...@@ -5357,7 +5357,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/* Initialize POSITION objects */ /* Initialize POSITION objects */
for (i=0 ; i <= table_count ; i++) for (i=0 ; i <= table_count ; i++)
(void) new ((char*) (join->positions + i)) POSITION; (void) new ((char*) (join->positions + i)) POSITION;
for (i=0 ; i <= sort_space ; i++) for (i=0 ; i < sort_space ; i++)
(void) new ((char*) (join->sort_positions + i)) POSITION; (void) new ((char*) (join->sort_positions + i)) POSITION;
join->best_ref= stat_vector; join->best_ref= stat_vector;
...@@ -20631,6 +20631,7 @@ TABLE *Create_tmp_table::start(THD *thd, ...@@ -20631,6 +20631,7 @@ TABLE *Create_tmp_table::start(THD *thd,
*/ */
if (param->precomputed_group_by) if (param->precomputed_group_by)
copy_func_count+= param->sum_func_count; copy_func_count+= param->sum_func_count;
param->copy_func_count= copy_func_count;
init_sql_alloc(key_memory_TABLE, &own_root, TABLE_ALLOC_BLOCK_SIZE, 0, init_sql_alloc(key_memory_TABLE, &own_root, TABLE_ALLOC_BLOCK_SIZE, 0,
MYF(MY_THREAD_SPECIFIC)); MYF(MY_THREAD_SPECIFIC));
...@@ -20837,8 +20838,9 @@ bool Create_tmp_table::add_fields(THD *thd, ...@@ -20837,8 +20838,9 @@ bool Create_tmp_table::add_fields(THD *thd,
We here distinguish between UNION and multi-table-updates by the fact We here distinguish between UNION and multi-table-updates by the fact
that in the later case group is set to the row pointer. that in the later case group is set to the row pointer.
The test for item->marker == 4 is ensure we don't create a group-by The test for item->marker == MARKER_NULL_KEY is ensure we
key over a bit field as heap tables can't handle that. don't create a group-by key over a bit field as heap tables
can't handle that.
*/ */
DBUG_ASSERT(!param->schema_table); DBUG_ASSERT(!param->schema_table);
Field *new_field= Field *new_field=
...@@ -20905,6 +20907,7 @@ bool Create_tmp_table::add_fields(THD *thd, ...@@ -20905,6 +20907,7 @@ bool Create_tmp_table::add_fields(THD *thd,
new_field->flags|= FIELD_PART_OF_TMP_UNIQUE; new_field->flags|= FIELD_PART_OF_TMP_UNIQUE;
} }
} }
DBUG_ASSERT(fieldnr == m_field_count[other] + m_field_count[distinct]); DBUG_ASSERT(fieldnr == m_field_count[other] + m_field_count[distinct]);
DBUG_ASSERT(m_blob_count == m_blobs_count[other] + m_blobs_count[distinct]); DBUG_ASSERT(m_blob_count == m_blobs_count[other] + m_blobs_count[distinct]);
share->fields= fieldnr; share->fields= fieldnr;
...@@ -20912,7 +20915,9 @@ bool Create_tmp_table::add_fields(THD *thd, ...@@ -20912,7 +20915,9 @@ bool Create_tmp_table::add_fields(THD *thd,
table->field[fieldnr]= 0; // End marker table->field[fieldnr]= 0; // End marker
share->blob_field[m_blob_count]= 0; // End marker share->blob_field[m_blob_count]= 0; // End marker
copy_func[0]= 0; // End marker copy_func[0]= 0; // End marker
DBUG_ASSERT((copy_func - param->items_to_copy) <= param->copy_func_count);
param->func_count= (uint) (copy_func - param->items_to_copy); param->func_count= (uint) (copy_func - param->items_to_copy);
share->column_bitmap_size= bitmap_buffer_size(share->fields); share->column_bitmap_size= bitmap_buffer_size(share->fields);
thd->mem_root= mem_root_save; thd->mem_root= mem_root_save;
...@@ -344,6 +344,7 @@ select_unit::create_result_table(THD *thd_arg, List<Item> *column_types, ...@@ -344,6 +344,7 @@ select_unit::create_result_table(THD *thd_arg, List<Item> *column_types,
DBUG_ASSERT(table == 0); DBUG_ASSERT(table == 0);
tmp_table_param.init(); tmp_table_param.init();
tmp_table_param.field_count= column_types->elements; tmp_table_param.field_count= column_types->elements;
tmp_table_param.func_count= tmp_table_param.field_count;
tmp_table_param.bit_fields_as_long= bit_fields_as_long; tmp_table_param.bit_fields_as_long= bit_fields_as_long;
tmp_table_param.hidden_field_count= hidden; tmp_table_param.hidden_field_count= hidden;
......
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