From 9c54c2e31aa5bef478a457125b5519c00cbb7788 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Mon, 7 Aug 2023 11:10:30 +0500 Subject: [PATCH] * Fixed heap use after free issue. * CharsetRegressionTest -> testBug95139() fixed Set mysql-default_collation_connection to 'utf8mb4_0900_ai_ci' for MySQL 8.0.33 --- lib/MySQL_Thread.cpp | 56 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index f1a17a2150..17eb021550 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -116,21 +116,51 @@ const MARIADB_CHARSET_INFO * proxysql_find_charset_nr(unsigned int nr) { return NULL; } +/** + * @brief Finds the default (first) collation for the supplied 'charset name'. + * @details Previously, this function just returned the first collation found (default). Since v2.5.3, this + * function takes into consideration the thread variable 'SQL_COLLATION_CONNECTION' + * ('mysql-default_collation_connection'). This was introduced for being able to serve the same default + * collation as the server (for bootstrap mode) in case it's detected to be a MySQL 8 + * ('utf8mb4_0900_ai_ci'), instead of the retrocompatible default collation ('utf8mb4_general_ci'). This + * change also allows users to select the default collation that they please for a particular charset, if + * the collection specified via 'mysql-default_collation_connection', isn't found, the first found collation + * (original default) will be retrieved. + * @param name The 'charset name' for which to find the default collation. + * @return The collation found, NULL if none is find. + */ MARIADB_CHARSET_INFO * proxysql_find_charset_name(const char *name_) { + const char* default_collation = mysql_thread___default_variables[SQL_COLLATION_CONNECTION]; MARIADB_CHARSET_INFO *c = (MARIADB_CHARSET_INFO *)mariadb_compiled_charsets; + MARIADB_CHARSET_INFO* charset_collation = nullptr; + const char *name; if (strcasecmp(name_,(const char *)"utf8mb3")==0) { name = (const char *)"utf8"; } else { name = name_; } + do { if (!strcasecmp(c->csname, name)) { - return c; + if (charset_collation == nullptr) { + charset_collation = c; + } + + if (default_collation == nullptr) { + charset_collation = c; + break; + } else { + if (!strcmp(default_collation, c->name)) { + charset_collation = c; + break; + } + } } ++c; } while (c[0].nr != 0); - return NULL; + + return charset_collation; } MARIADB_CHARSET_INFO * proxysql_find_charset_collate_names(const char *csname_, const char *collatename_) { @@ -2004,16 +2034,17 @@ bool MySQL_Threads_Handler::set_variable(char *name, const char *value) { // thi return false; } else if (value[0] == '/') { char *full_path = strdup(value); - char *eval_dirname = dirname(full_path); - DIR* eventlog_dir = opendir(eval_dirname); - free(full_path); - if (eventlog_dir) { + char *eval_dirname = dirname(full_path); + DIR* eventlog_dir = opendir(eval_dirname); + if (eventlog_dir) { closedir(eventlog_dir); free(variables.auditlog_filename); variables.auditlog_filename=strdup(value); - return true; + free(full_path); + return true; } else { proxy_error("%s is an invalid value for auditlog_filename path, the directory cannot be accessed\n", eval_dirname); + free(full_path); return false; } } else { @@ -2028,16 +2059,17 @@ bool MySQL_Threads_Handler::set_variable(char *name, const char *value) { // thi return false; } else if (value[0] == '/') { char *full_path = strdup(value); - char *eval_dirname = dirname(full_path); - DIR* eventlog_dir = opendir(eval_dirname); - free(full_path); - if (eventlog_dir) { + char *eval_dirname = dirname(full_path); + DIR* eventlog_dir = opendir(eval_dirname); + if (eventlog_dir) { closedir(eventlog_dir); free(variables.eventslog_filename); variables.eventslog_filename=strdup(value); - return true; + free(full_path); + return true; } else { proxy_error("%s is an invalid value for eventslog_filename path, the directory cannot be accessed\n", eval_dirname); + free(full_path); return false; } } else {