From a63a250d40be0254c6a5633329a6b0577eaee74c Mon Sep 17 00:00:00 2001 From: Neha Kumari Date: Mon, 25 Jul 2016 20:34:20 +0530 Subject: [PATCH] BUG#23509275 :DBUG_PRINT in THD::decide_logging_format prints incorrectly, access out-of-bound Problem: In debug builds, there is a chance that an out-of-bounds read is performed when tables are locked in LTM_PRELOCKED_UNDER_LOCK_TABLES mode. It can happen because the debug code uses enum values as index for an array of mode descriptions, but it only takes into consideration 3 out of 4 of the enum values. Fix: This patch fixes it by implementing a getter for the enum which returns a string representation of the enum, effectively removing the out-of-bounds read. Moreover, it also fixes the lock mode descriptions that would be print out in debug builds. --- sql/sql_class.cc | 32 ++++++++++++++++++++++---------- sql/sql_class.h | 11 +++++++++++ 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4711009d7cd..0696021cfc0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, 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 @@ -4246,6 +4246,25 @@ has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) return 0; } +#ifndef DBUG_OFF +const char * get_locked_tables_mode_name(enum_locked_tables_mode locked_tables_mode) +{ + switch (locked_tables_mode) + { + case LTM_NONE: + return "LTM_NONE"; + case LTM_LOCK_TABLES: + return "LTM_LOCK_TABLES"; + case LTM_PRELOCKED: + return "LTM_PRELOCKED"; + case LTM_PRELOCKED_UNDER_LOCK_TABLES: + return "LTM_PRELOCKED_UNDER_LOCK_TABLES"; + default: + return "Unknown table lock mode"; + } +} +#endif + /** Decide on logging format to use for the statement and issue errors or warnings as needed. The decision depends on the following @@ -4397,15 +4416,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) TABLE* prev_access_table= NULL; #ifndef DBUG_OFF - { - static const char *prelocked_mode_name[] = { - "NON_PRELOCKED", - "PRELOCKED", - "PRELOCKED_UNDER_LOCK_TABLES", - }; - DBUG_PRINT("debug", ("prelocked_mode: %s", - prelocked_mode_name[locked_tables_mode])); - } + DBUG_PRINT("debug", ("prelocked_mode: %s", + get_locked_tables_mode_name(locked_tables_mode))); #endif if (variables.binlog_format != BINLOG_FORMAT_ROW && tables) diff --git a/sql/sql_class.h b/sql/sql_class.h index 0df8c70e184..dcc7458ee50 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -963,6 +963,8 @@ typedef I_List Item_change_list; /** Type of locked tables mode. See comment for THD::locked_tables_mode for complete description. + While adding new enum values add them to the getter method for this enum + declared below and defined in sql_class.cc as well. */ enum enum_locked_tables_mode @@ -973,6 +975,15 @@ enum enum_locked_tables_mode LTM_PRELOCKED_UNDER_LOCK_TABLES }; +#ifndef DBUG_OFF +/** + Getter for the enum enum_locked_tables_mode + @param locked_tables_mode enum for types of locked tables mode + + @return The string represantation of that enum value +*/ +const char * get_locked_tables_mode_name(enum_locked_tables_mode locked_tables_mode); +#endif /** Class that holds information about tables which were opened and locked