diff options
author | hf@deer.(none) <> | 2004-10-05 21:19:40 +0500 |
---|---|---|
committer | hf@deer.(none) <> | 2004-10-05 21:19:40 +0500 |
commit | ee3b6340b03b303997fc6bb54499b9ead0316025 (patch) | |
tree | 625041aef3296bd1708b8cfa02da1b5db3a04bff /sql/sql_cache.cc | |
parent | 19c112dfb5d2a1ab787c4ee10efd92e996b17799 (diff) | |
download | mariadb-git-ee3b6340b03b303997fc6bb54499b9ead0316025.tar.gz |
Fix for #5730 (Query cache crashes server)
Recusive part leads to stack overflow
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r-- | sql/sql_cache.cc | 75 |
1 files changed, 37 insertions, 38 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 5118421464b..60f0cfadc8e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1843,7 +1843,6 @@ inline ulong Query_cache::get_min_append_result_data_size() /* Allocate one or more blocks to hold data */ - my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, ulong data_len, 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)) + ALIGN_SIZE(sizeof(Query_cache_result))); - ulong len= data_len + all_headers_len; - ulong align_len= ALIGN_SIZE(len); - DBUG_ENTER("Query_cache::allocate_data_chain"); - DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", - data_len, all_headers_len)); - ulong min_size = (first_block_arg ? get_min_first_result_data_size(): get_min_append_result_data_size()); - *result_block = allocate_block(max(min_size, align_len), - min_result_data_size == 0, - all_headers_len + min_result_data_size, - 1); - my_bool success = (*result_block != 0); - if (success) + Query_cache_block *prev_block= NULL; + Query_cache_block *new_block; + DBUG_ENTER("Query_cache::allocate_data_chain"); + DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu", + data_len, all_headers_len)); + + do { - Query_cache_block *new_block= *result_block; + ulong len= data_len + all_headers_len; + ulong align_len= ALIGN_SIZE(len); + + if (!(new_block= allocate_block(max(min_size, align_len), + min_result_data_size == 0, + all_headers_len + min_result_data_size, + 1))) + { + DBUG_PRINT("warning", ("Can't allocate block for results")); + DBUG_RETURN(FALSE); + } + 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->next = new_block->prev = new_block; Query_cache_result *header = new_block->result(); header->parent(query_block); - if (new_block->length < len) - { - /* - We got less memory then we need (no big memory blocks) => - Continue to allocated more blocks until we got everything we need. - */ - Query_cache_block *next_block; - if ((success = allocate_data_chain(&next_block, - len - new_block->length, - 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_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 - DBUG_PRINT("warning", ("Can't allocate block for continue")); - } - else - DBUG_PRINT("warning", ("Can't allocate block for results")); - DBUG_RETURN(success); + *result_block= new_block; + if (new_block->length >= len) + break; + + /* + We got less memory then we need (no big memory blocks) => + Continue to allocated more blocks until we got everything we need. + */ + data_len= len - new_block->length; + prev_block= new_block; + } while(1); + + DBUG_RETURN(TRUE); } /***************************************************************************** |