From 5d1ccce58ac10b2abff245734cd8e3f5ed2e9f67 Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com/june.mysql.com" <> Date: Wed, 24 Oct 2007 16:09:30 +0500 Subject: BUG#31159 - fulltext search on ucs2 column crashes server ucs2 doesn't provide required by fulltext ctype array. Crash happens because fulltext attempts to use unitialized ctype array. Fixed by converting ucs2 fields to compatible utf8 analogue. --- mysys/charset.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'mysys') diff --git a/mysys/charset.c b/mysys/charset.c index 6f2d4d3c347..f0ac61ceed5 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -673,3 +673,43 @@ CHARSET_INFO *fs_character_set() return fs_cset_cache; } #endif + + +/** + @brief Find compatible character set with ctype. + + @param[in] original_cs Original character set + + @note + 128 my_charset_ucs2_general_uca ->192 my_charset_utf8_general_uca_ci + 129 my_charset_ucs2_icelandic_uca_ci ->193 my_charset_utf8_icelandic_uca_ci + 130 my_charset_ucs2_latvian_uca_ci ->194 my_charset_utf8_latvian_uca_ci + 131 my_charset_ucs2_romanian_uca_ci ->195 my_charset_utf8_romanian_uca_ci + 132 my_charset_ucs2_slovenian_uca_ci ->196 my_charset_utf8_slovenian_uca_ci + 133 my_charset_ucs2_polish_uca_ci ->197 my_charset_utf8_polish_uca_ci + 134 my_charset_ucs2_estonian_uca_ci ->198 my_charset_utf8_estonian_uca_ci + 135 my_charset_ucs2_spanish_uca_ci ->199 my_charset_utf8_spanish_uca_ci + 136 my_charset_ucs2_swedish_uca_ci ->200 my_charset_utf8_swedish_uca_ci + 137 my_charset_ucs2_turkish_uca_ci ->201 my_charset_utf8_turkish_uca_ci + 138 my_charset_ucs2_czech_uca_ci ->202 my_charset_utf8_czech_uca_ci + 139 my_charset_ucs2_danish_uca_ci ->203 my_charset_utf8_danish_uca_ci + 140 my_charset_ucs2_lithuanian_uca_ci->204 my_charset_utf8_lithuanian_uca_ci + 141 my_charset_ucs2_slovak_uca_ci ->205 my_charset_utf8_slovak_uca_ci + 142 my_charset_ucs2_spanish2_uca_ci ->206 my_charset_utf8_spanish2_uca_ci + 143 my_charset_ucs2_roman_uca_ci ->207 my_charset_utf8_roman_uca_ci + 144 my_charset_ucs2_persian_uca_ci ->208 my_charset_utf8_persian_uca_ci + + @return Compatible character set or NULL. +*/ + +CHARSET_INFO *get_compatible_charset_with_ctype(CHARSET_INFO *original_cs) +{ + CHARSET_INFO *compatible_cs= 0; + DBUG_ENTER("get_compatible_charset_with_ctype"); + if (!strcmp(original_cs->csname, "ucs2") && + (compatible_cs= get_charset(original_cs->number + 64, MYF(0))) && + (!compatible_cs->ctype || + strcmp(original_cs->name + 4, compatible_cs->name + 4))) + compatible_cs= 0; + DBUG_RETURN(compatible_cs); +} -- cgit v1.2.1 From d06e2f922354bb1f98f5fe434ea5445c99af215d Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com/june.mysql.com" <> Date: Tue, 6 Nov 2007 18:09:33 +0400 Subject: BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE RENAME TABLE against a table with DATA/INDEX DIRECTORY overwrites the file to which the symlink points. This is security issue, because it is possible to create a table with some name in some non-system database and set DATA/INDEX DIRECTORY to mysql system database. Renaming this table to one of mysql system tables (e.g. user, host) would overwrite the system table. Return an error when the file to which the symlink points exist. --- mysys/my_symlink2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'mysys') diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 913f632fbb4..4d58699412a 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -120,6 +120,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) int was_symlink= (!my_disable_symlinks && !my_readlink(link_name, from, MYF(0))); int result=0; + int name_is_different; DBUG_ENTER("my_rename_with_symlink"); if (!was_symlink) @@ -128,6 +129,14 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) /* Change filename that symlink pointed to */ strmov(tmp_name, to); fn_same(tmp_name,link_name,1); /* Copy dir */ + name_is_different= strcmp(link_name, tmp_name); + if (name_is_different && !access(tmp_name, F_OK)) + { + my_errno= EEXIST; + if (MyFlags & MY_WME) + my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST); + DBUG_RETURN(1); + } /* Create new symlink */ if (my_symlink(tmp_name, to, MyFlags)) @@ -139,7 +148,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) the same basename and different directories. */ - if (strcmp(link_name, tmp_name) && my_rename(link_name, tmp_name, MyFlags)) + if (name_is_different && my_rename(link_name, tmp_name, MyFlags)) { int save_errno=my_errno; my_delete(to, MyFlags); /* Remove created symlink */ -- cgit v1.2.1 From ef59ca3d78b80285c11e59b20451c88496abe513 Mon Sep 17 00:00:00 2001 From: "tsmith@ramayana.hindu.god" <> Date: Wed, 7 Nov 2007 15:23:50 -0700 Subject: Bug #20748: Configuration files should not be read more than once A user could not override system-wide settings in their ~/.my.cnf, because the DEFAULT_SYSCONFDIR was being searched last. Also, in some configurations (especially when the --sysconfdir compile-time option is set to /etc or /etc/mysql), the system-wide my.cnf file was read multiple times, causing confusion and potential problems. Rearrange default directories to conform to the manual and logic. Move --sysconfdir= (DEFAULT_SYSCONFDIR) from the last default directory to the middle of the list. $HOME/.my.cnf should be last, so the user is able to override the system-wide settings. Change init_default_directories() to remove duplicates from the list. --- mysys/CMakeLists.txt | 2 +- mysys/Makefile.am | 2 +- mysys/default.c | 192 +++++++++++++++++++++++++++++++++----------------- mysys/mf_arr_appstr.c | 61 ++++++++++++++++ 4 files changed, 192 insertions(+), 65 deletions(-) create mode 100644 mysys/mf_arr_appstr.c (limited to 'mysys') diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 8aaf0b5f00f..cd3e7afd6a5 100755 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -26,7 +26,7 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c - mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_tempdir.c + mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_arr_appstr.c mf_tempdir.c mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c diff --git a/mysys/Makefile.am b/mysys/Makefile.am index a835492e670..8c6bf5f7006 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -38,7 +38,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ my_symlink.c my_symlink2.c \ - mf_pack.c mf_unixpath.c mf_strip.c \ + mf_pack.c mf_unixpath.c mf_strip.c mf_arr_appstr.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ ptr_cmp.c mf_radix.c queues.c \ diff --git a/mysys/default.c b/mysys/default.c index aff38b6af0b..74d016ce53c 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -47,7 +47,7 @@ char *my_defaults_extra_file=0; /* Which directories are searched for options (and in which order) */ -#define MAX_DEFAULT_DIRS 7 +#define MAX_DEFAULT_DIRS 6 const char *default_directories[MAX_DEFAULT_DIRS + 1]; #ifdef __WIN__ @@ -83,7 +83,22 @@ static int search_default_file_with_ext(Process_option_func func, void *func_ctx, const char *dir, const char *ext, const char *config_file, int recursion_level); -static void init_default_directories(); + + + +/** + Create the list of default directories. + + @details + On all systems, if a directory is already in the list, it will be moved + to the end of the list. This avoids reading defaults files multiple times, + while ensuring the correct precedence. + + @return void +*/ + +static void (*init_default_directories)(); + static char *remove_end_comment(char *ptr); @@ -913,6 +928,25 @@ void print_defaults(const char *conf_file, const char **groups) #include +#define ADD_DIRECTORY(DIR) \ + do { \ + my_bool rc= \ + array_append_string_unique((DIR), default_directories, \ + array_elements(default_directories)); \ + DBUG_ASSERT(rc == FALSE); /* Success */ \ + } while (0) + + +#define ADD_COMMON_DIRECTORIES() \ + do { \ + char *env; \ + if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \ + ADD_DIRECTORY(env); \ + /* Placeholder for --defaults-extra-file= */ \ + ADD_DIRECTORY(""); \ + } while (0) + + #ifdef __WIN__ /* This wrapper for GetSystemWindowsDirectory() will dynamically bind to the @@ -947,73 +981,33 @@ static uint my_get_system_windows_directory(char *buffer, uint size) } return count; } -#endif -/* - Create the list of default directories. +/** + Initialize default directories for Microsoft Windows - On Microsoft Windows, this is: - 1. C:/ + @details + 1. GetSystemWindowsDirectory() 2. GetWindowsDirectory() - 3. GetSystemWindowsDirectory() - 4. getenv(DEFAULT_HOME_ENV) - 5. Directory above where the executable is located - 6. "" - 7. --sysconfdir= - - On Novell NetWare, this is: - 1. sys:/etc/ - 2. getenv(DEFAULT_HOME_ENV) - 3. "" - 4. --sysconfdir= - - On OS/2, this is: - 1. getenv(ETC) - 2. /etc/ - 3. getenv(DEFAULT_HOME_ENV) - 4. "" - 5. "~/" - 6. --sysconfdir= - - Everywhere else, this is: - 1. /etc/ - 2. getenv(DEFAULT_HOME_ENV) - 3. "" - 4. "~/" - 5. --sysconfdir= - - */ + 3. C:/ + 4. Directory above where the executable is located + 5. getenv(DEFAULT_HOME_ENV) + 6. --defaults-extra-file= (run-time option) +*/ -static void init_default_directories() +static void init_default_directories_win() { - const char *env, **ptr= default_directories; + bzero(default_directories, sizeof(default_directories)); -#ifdef __WIN__ - *ptr++= "C:/"; + if (my_get_system_windows_directory(shared_system_dir, + sizeof(shared_system_dir))) + ADD_DIRECTORY(&shared_system_dir); if (GetWindowsDirectory(system_dir,sizeof(system_dir))) - *ptr++= (char*)&system_dir; - if (my_get_system_windows_directory(shared_system_dir, - sizeof(shared_system_dir)) && - strcmp(system_dir, shared_system_dir)) - *ptr++= (char *)&shared_system_dir; + ADD_DIRECTORY(&system_dir); + + ADD_DIRECTORY("C:/"); -#elif defined(__NETWARE__) - *ptr++= "sys:/etc/"; -#else -#if defined(__EMX__) || defined(OS2) - if ((env= getenv("ETC"))) - *ptr++= env; -#endif - *ptr++= "/etc/"; -#endif - if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) - *ptr++= env; - *ptr++= ""; /* Place for defaults_extra_file */ -#if !defined(__WIN__) && !defined(__NETWARE__) - *ptr++= "~/";; -#elif defined(__WIN__) if (GetModuleFileName(NULL, config_dir, sizeof(config_dir))) { char *last= NULL, *end= strend(config_dir); @@ -1043,12 +1037,84 @@ static void init_default_directories() last= end; } } - *ptr++= (char *)&config_dir; + ADD_DIRECTORY(&config_dir); } -#endif + + ADD_COMMON_DIRECTORIES(); +} + +static void (*init_default_directories)()= init_default_directories_win; + +#elif defined(__NETWARE__) + +/** + Initialize default directories for Novell Netware + + @details + 1. sys:/etc/ + 2. getenv(DEFAULT_HOME_ENV) + 3. --defaults-extra-file= (run-time option) +*/ + +static void init_default_directories_netware() +{ + bzero(default_directories, sizeof(default_directories)); + ADD_DIRECTORY("sys:/etc/"); + ADD_COMMON_DIRECTORIES(); +} + +static void (*init_default_directories)()= init_default_directories_netware; + +#elif defined(__EMX__) || defined(OS2) + +/** + Initialize default directories for OS/2 + + @details + 1. /etc/ + 2. getenv(ETC) + 3. getenv(DEFAULT_HOME_ENV) + 4. --defaults-extra-file= (run-time option) +*/ + +static void init_default_directories_os2() +{ + const char *env; + + bzero(default_directories, sizeof(default_directories)); + ADD_DIRECTORY("/etc/"); + if ((env= getenv("ETC"))) + ADD_DIRECTORY(env); + ADD_COMMON_DIRECTORIES(); +} + +static void (*init_default_directories)()= init_default_directories_os2; + +#else + +/** + Initialize default directories for Unix + + @details + 1. /etc/ + 2. --sysconfdir= (compile-time option) + 3. getenv(DEFAULT_HOME_ENV) + 4. --defaults-extra-file= (run-time option) + 5. "~/" +*/ + +static void init_default_directories_unix() +{ + bzero(default_directories, sizeof(default_directories)); + ADD_DIRECTORY("/etc/"); #ifdef DEFAULT_SYSCONFDIR if (DEFAULT_SYSCONFDIR != "") - *ptr++= DEFAULT_SYSCONFDIR; + ADD_DIRECTORY(DEFAULT_SYSCONFDIR); #endif - *ptr= 0; /* end marker */ + ADD_COMMON_DIRECTORIES(); + ADD_DIRECTORY("~/"); } + +static void (*init_default_directories)()= init_default_directories_unix; + +#endif diff --git a/mysys/mf_arr_appstr.c b/mysys/mf_arr_appstr.c new file mode 100644 index 00000000000..1edbea9df4a --- /dev/null +++ b/mysys/mf_arr_appstr.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2007 MySQL AB + + 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysys_priv.h" +#include /* strcmp() */ + + +/** + Append str to array, or move to the end if it already exists + + @param str String to be appended + @param array The array, terminated by a NULL element, all unused elements + pre-initialized to NULL + @param size Size of the array; array must be terminated by a NULL + pointer, so can hold size - 1 elements + + @retval FALSE Success + @retval TRUE Failure, array is full +*/ + +my_bool array_append_string_unique(const char *str, + const char **array, size_t size) +{ + const char **p; + /* end points at the terminating NULL element */ + const char **end= array + size - 1; + DBUG_ASSERT(*end == NULL); + + for (p= array; *p; ++p) + { + if (strcmp(*p, str) == 0) + break; + } + if (p >= end) + return TRUE; /* Array is full */ + + DBUG_ASSERT(*p == NULL || strcmp(*p, str) == 0); + + while (*(p + 1)) + { + *p= *(p + 1); + ++p; + } + + DBUG_ASSERT(p < end); + *p= str; + + return FALSE; /* Success */ +} -- cgit v1.2.1 From faf9d4e922d1f3247ee228e23e68aedd24db234d Mon Sep 17 00:00:00 2001 From: "tsmith@ramayana.hindu.god" <> Date: Fri, 9 Nov 2007 18:27:20 -0700 Subject: Fix Windows build problems. --- mysys/default.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'mysys') diff --git a/mysys/default.c b/mysys/default.c index 74d016ce53c..a24f6583004 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -997,14 +997,14 @@ static uint my_get_system_windows_directory(char *buffer, uint size) static void init_default_directories_win() { - bzero(default_directories, sizeof(default_directories)); + bzero((char *) default_directories, sizeof(default_directories)); if (my_get_system_windows_directory(shared_system_dir, sizeof(shared_system_dir))) - ADD_DIRECTORY(&shared_system_dir); + ADD_DIRECTORY(shared_system_dir); if (GetWindowsDirectory(system_dir,sizeof(system_dir))) - ADD_DIRECTORY(&system_dir); + ADD_DIRECTORY(system_dir); ADD_DIRECTORY("C:/"); @@ -1037,7 +1037,7 @@ static void init_default_directories_win() last= end; } } - ADD_DIRECTORY(&config_dir); + ADD_DIRECTORY(config_dir); } ADD_COMMON_DIRECTORIES(); @@ -1058,7 +1058,7 @@ static void (*init_default_directories)()= init_default_directories_win; static void init_default_directories_netware() { - bzero(default_directories, sizeof(default_directories)); + bzero((char *) default_directories, sizeof(default_directories)); ADD_DIRECTORY("sys:/etc/"); ADD_COMMON_DIRECTORIES(); } @@ -1081,7 +1081,7 @@ static void init_default_directories_os2() { const char *env; - bzero(default_directories, sizeof(default_directories)); + bzero((char *) default_directories, sizeof(default_directories)); ADD_DIRECTORY("/etc/"); if ((env= getenv("ETC"))) ADD_DIRECTORY(env); @@ -1105,7 +1105,7 @@ static void (*init_default_directories)()= init_default_directories_os2; static void init_default_directories_unix() { - bzero(default_directories, sizeof(default_directories)); + bzero((char *) default_directories, sizeof(default_directories)); ADD_DIRECTORY("/etc/"); #ifdef DEFAULT_SYSCONFDIR if (DEFAULT_SYSCONFDIR != "") -- cgit v1.2.1 From de0d55edf431141ba60f5f9d2c8e1935ee6b1037 Mon Sep 17 00:00:00 2001 From: "tsmith@ramayana.hindu.god" <> Date: Fri, 16 Nov 2007 14:56:37 -0700 Subject: Eliminate 'unused variable' warnings when compiling non-debug build --- mysys/default.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'mysys') diff --git a/mysys/default.c b/mysys/default.c index a24f6583004..e58903d6d64 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -928,13 +928,22 @@ void print_defaults(const char *conf_file, const char **groups) #include +/* + This extra complexity is to avoid declaring 'rc' if it won't be + used. +*/ +#define ADD_DIRECTORY_INTERNAL(DIR) \ + array_append_string_unique((DIR), default_directories, \ + array_elements(default_directories)) +#ifdef DBUG_OFF +# define ADD_DIRECTORY(DIR) (void) ADD_DIRECTORY_INTERNAL(DIR) +#else #define ADD_DIRECTORY(DIR) \ do { \ - my_bool rc= \ - array_append_string_unique((DIR), default_directories, \ - array_elements(default_directories)); \ + my_bool rc= ADD_DIRECTORY_INTERNAL(DIR); \ DBUG_ASSERT(rc == FALSE); /* Success */ \ } while (0) +#endif #define ADD_COMMON_DIRECTORIES() \ -- cgit v1.2.1