[Commits] 325a9c7: MDEV-10777: Server crashed due to query_cache_info plugin

Oleksandr Byelkin sanja at mariadb.com
Wed Sep 14 19:15:04 EEST 2016


revision-id: 325a9c760c9b13a9748a0cee27a98455b558df30 (mariadb-10.1.17-11-g325a9c7)
parent(s): bb2c1a52c61706dde8c525a8887f2d364c0db1eb
committer: Oleksandr Byelkin
timestamp: 2016-09-14 18:15:03 +0200
message:

MDEV-10777: Server crashed due to query_cache_info plugin

Possible fix. Make the pluging more safe.

---
 plugin/qc_info/qc_info.cc | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/plugin/qc_info/qc_info.cc b/plugin/qc_info/qc_info.cc
index 4ccfdc8..da5d310 100644
--- a/plugin/qc_info/qc_info.cc
+++ b/plugin/qc_info/qc_info.cc
@@ -106,6 +106,9 @@ static ST_FIELD_INFO qc_info_fields[]=
   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
 };
 
+
+static const char unknown[]= "#UNKNOWN#";
+
 static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
                                               COND *cond)
 {
@@ -146,7 +149,8 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
 
     query_cache_block_raw = my_hash_element(queries, i);
     query_cache_block = (Query_cache_block*)query_cache_block_raw;
-    if (query_cache_block->type != Query_cache_block::QUERY)
+    if (unlikely(!query_cache_block ||
+                 query_cache_block->type != Query_cache_block::QUERY))
       continue;
 
     query_cache_query = query_cache_block->query();
@@ -169,14 +173,33 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
     table->field[COLUMN_GROUP_CONCAT_MAX_LENGTH]->store(flags.group_concat_max_len, 0);
 
     cs_client= get_charset(flags.character_set_client_num, MYF(MY_WME));
-    table->field[COLUMN_CHARACTER_SET_CLIENT]->store(cs_client->csname, strlen(cs_client->csname), scs);
+    if (likely(cs_client))
+      table->field[COLUMN_CHARACTER_SET_CLIENT]->
+        store(cs_client->csname, strlen(cs_client->csname), scs);
+    else
+      table->field[COLUMN_CHARACTER_SET_CLIENT]->
+        store(STRING_WITH_LEN(unknown), scs);
+
     cs_result= get_charset(flags.character_set_results_num, MYF(MY_WME));
-    table->field[COLUMN_CHARACTER_SET_RESULT]->store(cs_result->csname, strlen(cs_result->csname), scs);
+    if (likely(cs_result))
+      table->field[COLUMN_CHARACTER_SET_RESULT]->
+        store(cs_result->csname, strlen(cs_result->csname), scs);
+    else
+      table->field[COLUMN_CHARACTER_SET_RESULT]->
+        store(STRING_WITH_LEN(unknown), scs);
+
     collation= get_charset(flags.collation_connection_num, MYF(MY_WME));
-    table->field[COLUMN_COLLATION]->store(collation->name, strlen(collation->name), scs);
+    if (likely(collation))
+      table->field[COLUMN_COLLATION]->
+        store(collation->name, strlen(collation->name), scs);
+    else
+      table->field[COLUMN_COLLATION]-> store(STRING_WITH_LEN(unknown), scs);
 
     tz= flags.time_zone->get_name();
-    table->field[COLUMN_TIMEZONE]->store(tz->ptr(), tz->length(), scs);
+    if (likely(tz))
+      table->field[COLUMN_TIMEZONE]->store(tz->ptr(), tz->length(), scs);
+    else
+      table->field[COLUMN_TIMEZONE]-> store(STRING_WITH_LEN(unknown), scs);
     table->field[COLUMN_DEFAULT_WEEK_FORMAT]->store(flags.default_week_format, 0);
     table->field[COLUMN_DIV_PRECISION_INCREMENT]->store(flags.div_precision_increment, 0);
 
@@ -204,7 +227,9 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
 
     /* If we have result blocks, process them */
     first_result_block= query_cache_query->result();
-    if(first_result_block)
+    if(first_result_block &&
+       // better do not touch unfinished result
+       first_result_block->type == Query_cache_block::RESULT)
     {
       /* initialize so we can loop over the result blocks*/
       result_block= first_result_block;
@@ -231,7 +256,8 @@ static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
     }
     table->field[COLUMN_RESULT_BLOCKS_COUNT]->store(result_blocks_count, 0);
     table->field[COLUMN_RESULT_BLOCKS_SIZE]->store(result_blocks_size, 0);
-    table->field[COLUMN_RESULT_BLOCKS_SIZE_USED]->store(result_blocks_size_used, 0);
+    table->field[COLUMN_RESULT_BLOCKS_SIZE_USED]->
+      store(result_blocks_size_used, 0);
 
     if (schema_table_store_record(thd, table))
       goto cleanup;


More information about the commits mailing list