summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPraveenkumar Hulakund <praveenkumar.hulakund@oracle.com>2015-07-02 15:31:55 +0530
committerPraveenkumar Hulakund <praveenkumar.hulakund@oracle.com>2015-07-02 15:31:55 +0530
commit7ce304dff0e268304c8c13708ff9a3f034cce50a (patch)
treee402185f21ec817cdeb90df3f2b3049051cfda8b
parent7c5d18e2271ce4fcd9294511860841dbb4fec31a (diff)
downloadmariadb-git-7ce304dff0e268304c8c13708ff9a3f034cce50a.tar.gz
Bug#18487951 - QUERY_CACHE_MIN_RES_UNIT SET TO ZERO, CRASHES IN QUERY_CACHE::FIND_BIN
Valid min value for query_cache_min_res_unit is 512. But attempt to set value greater than or equal to the ULONG_MAX(max value) is resulting query_cache_min_res_unit value to 0. This result in crash while searching for memory block lesser than the valid min value to store query results. Free memory blocks in query cache are stored in bins according to their size. The bins are stored in size descending order. For the memory block request the appropriate bin is searched using binary search algorithm. The minimum free memory block request expected is 512 bytes. And the appropriate bin is searched for block greater than or equals to 512 bytes. Because of the bug the query_cache_min_res_unit is set to 0. Due to which there is a chance of request for memory blocks lesser than the minimum size in free memory block bins. Search for bin for this invalid input size fails and returns garbage index. Accessing bins array element with this index is causing the issue reported. The valid value range for the query_cache_min_res_unit is 512 to ULONG_MAX(when value is greater than the max allowed value, max allowed value is used i.e ULONG_MAX). While setting result unit block size (query_cache_min_res_unit), size is memory aligned by using a macro ALIGN_SIZE. The ALIGN_SIZE logic is as below, (input_size + sizeof(double) - 1) & ~(sizeof(double) - 1) For unsigned long type variable when input_size is greater than equal to ULONG_MAX-(sizeof(double)-1), above expression is resulting in value 0. Fix: ----- Comparing value set for query_cache_min_res_unit with max aligned value which can be stored in ulong type variable. If it is greater then setting it to the max aligned value for ulong type variable.
-rw-r--r--sql/sql_cache.cc9
1 files changed, 8 insertions, 1 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index ca3db3b48c0..e1f9e68ff83 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2013, 2015, Oracle and/or its affiliates. All rights
+ reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -399,6 +400,9 @@ TODO list:
#define QC_DEBUG_SYNC(name)
#endif
+// Max aligned size for ulong type query_cache_min_res_unit.
+static const ulong max_aligned_min_res_unit_size= ((ULONG_MAX) &
+ (~(sizeof(double) - 1)));
/**
Thread state to be used when the query cache lock needs to be acquired.
@@ -1158,6 +1162,9 @@ ulong Query_cache::set_min_res_unit(ulong size)
{
if (size < min_allocation_unit)
size= min_allocation_unit;
+ else if (size > max_aligned_min_res_unit_size)
+ size= max_aligned_min_res_unit_size;
+
return (min_result_data_size= ALIGN_SIZE(size));
}