mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Fix for #5730 (Query cache crashes server)
Recusive part leads to stack overflow sql/sql_cache.cc: Recursion removed from Query_cache::allocate_data_chain
This commit is contained in:
@ -1843,7 +1843,6 @@ inline ulong Query_cache::get_min_append_result_data_size()
|
|||||||
/*
|
/*
|
||||||
Allocate one or more blocks to hold data
|
Allocate one or more blocks to hold data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
||||||
ulong data_len,
|
ulong data_len,
|
||||||
Query_cache_block *query_block,
|
Query_cache_block *query_block,
|
||||||
@ -1851,55 +1850,55 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
|
|||||||
{
|
{
|
||||||
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
|
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
|
||||||
ALIGN_SIZE(sizeof(Query_cache_result)));
|
ALIGN_SIZE(sizeof(Query_cache_result)));
|
||||||
ulong len= data_len + all_headers_len;
|
ulong min_size = (first_block_arg ?
|
||||||
ulong align_len= ALIGN_SIZE(len);
|
get_min_first_result_data_size():
|
||||||
|
get_min_append_result_data_size());
|
||||||
|
Query_cache_block *prev_block= NULL;
|
||||||
|
Query_cache_block *new_block;
|
||||||
DBUG_ENTER("Query_cache::allocate_data_chain");
|
DBUG_ENTER("Query_cache::allocate_data_chain");
|
||||||
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
|
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
|
||||||
data_len, all_headers_len));
|
data_len, all_headers_len));
|
||||||
|
|
||||||
ulong min_size = (first_block_arg ?
|
do
|
||||||
get_min_first_result_data_size():
|
{
|
||||||
get_min_append_result_data_size());
|
ulong len= data_len + all_headers_len;
|
||||||
*result_block = allocate_block(max(min_size, align_len),
|
ulong align_len= ALIGN_SIZE(len);
|
||||||
|
|
||||||
|
if (!(new_block= allocate_block(max(min_size, align_len),
|
||||||
min_result_data_size == 0,
|
min_result_data_size == 0,
|
||||||
all_headers_len + min_result_data_size,
|
all_headers_len + min_result_data_size,
|
||||||
1);
|
1)))
|
||||||
my_bool success = (*result_block != 0);
|
|
||||||
if (success)
|
|
||||||
{
|
{
|
||||||
Query_cache_block *new_block= *result_block;
|
DBUG_PRINT("warning", ("Can't allocate block for results"));
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
new_block->n_tables = 0;
|
new_block->n_tables = 0;
|
||||||
new_block->used = 0;
|
new_block->used = min(len, new_block->length);
|
||||||
new_block->type = Query_cache_block::RES_INCOMPLETE;
|
new_block->type = Query_cache_block::RES_INCOMPLETE;
|
||||||
new_block->next = new_block->prev = new_block;
|
new_block->next = new_block->prev = new_block;
|
||||||
Query_cache_result *header = new_block->result();
|
Query_cache_result *header = new_block->result();
|
||||||
header->parent(query_block);
|
header->parent(query_block);
|
||||||
|
|
||||||
if (new_block->length < len)
|
DBUG_PRINT("qcache", ("Block len %lu used %lu",
|
||||||
{
|
new_block->length, new_block->used));
|
||||||
|
|
||||||
|
if (prev_block)
|
||||||
|
double_linked_list_join(prev_block, new_block);
|
||||||
|
else
|
||||||
|
*result_block= new_block;
|
||||||
|
if (new_block->length >= len)
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We got less memory then we need (no big memory blocks) =>
|
We got less memory then we need (no big memory blocks) =>
|
||||||
Continue to allocated more blocks until we got everything we need.
|
Continue to allocated more blocks until we got everything we need.
|
||||||
*/
|
*/
|
||||||
Query_cache_block *next_block;
|
data_len= len - new_block->length;
|
||||||
if ((success = allocate_data_chain(&next_block,
|
prev_block= new_block;
|
||||||
len - new_block->length,
|
} while(1);
|
||||||
query_block, first_block_arg)))
|
|
||||||
double_linked_list_join(new_block, next_block);
|
|
||||||
}
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
new_block->used = min(len, new_block->length);
|
|
||||||
|
|
||||||
DBUG_PRINT("qcache", ("Block len %lu used %lu",
|
DBUG_RETURN(TRUE);
|
||||||
new_block->length, new_block->used));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DBUG_PRINT("warning", ("Can't allocate block for continue"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DBUG_PRINT("warning", ("Can't allocate block for results"));
|
|
||||||
DBUG_RETURN(success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
Reference in New Issue
Block a user