From: Date: April 11 2006 3:16pm Subject: bk commit into 5.1 tree (bar:1.2293) BUG#17870 List-Archive: http://lists.mysql.com/commits/4791 X-Bug: 17870 Message-Id: <200604111316.k3BDGNdW040446@bar.intranet.mysql.r18.ru> Below is the list of changes that have just been committed into a local 5.1 repository of bar. When bar does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2293 06/04/11 18:16:14 bar@stripped +6 -0 bug#17870 Table names conflict with Windows device names It was impossible to create some table names on Windows (e.g. LPT1, AUX, COM1, etc). Fixed to pad dangerous names with thee "at" signs (e.g. LPT1@@@, AUX@@@, COM1@@@, and so on). mysql-test/t/ctype_filename.test 1.1 06/04/11 18:16:03 bar@stripped +21 -0 New BitKeeper file ``mysql-test/t/ctype_filename.test'' mysql-test/r/ctype_filename.result 1.1 06/04/11 18:16:03 bar@stripped +13 -0 New BitKeeper file ``mysql-test/r/ctype_filename.result'' strings/ctype-utf8.c 1.103 06/04/11 18:16:03 bar@stripped +5 -0 Treat "@@@" sequence in a table name as a end-of-line. sql/sql_table.cc 1.325 06/04/11 18:16:03 bar@stripped +10 -3 Check if a dangerous table name and append @@@ mysys/my_access.c 1.8 06/04/11 18:16:03 bar@stripped +92 -5 Adding new function check_if_legal_tablename(). It works almost like check_if_legal_filename(), but accepts a table name without extension and path, and does not check "CLOCK$". mysql-test/t/ctype_filename.test 1.0 06/04/11 18:16:03 bar@stripped +0 -0 BitKeeper file /usr/home/bar/mysql-5.1-new.b17870v1/mysql-test/t/ctype_filename.test mysql-test/r/ctype_filename.result 1.0 06/04/11 18:16:03 bar@stripped +0 -0 BitKeeper file /usr/home/bar/mysql-5.1-new.b17870v1/mysql-test/r/ctype_filename.result include/my_sys.h 1.189 06/04/11 18:16:02 bar@stripped +1 -0 Adding new function declaration # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: bar # Host: bar.intranet.mysql.r18.ru # Root: /usr/home/bar/mysql-5.1-new.b17870v1 --- 1.188/include/my_sys.h 2006-02-25 01:20:42 +04:00 +++ 1.189/include/my_sys.h 2006-04-11 18:16:02 +05:00 @@ -608,6 +608,7 @@ extern File my_sopen(const char *path, i #define my_access access #endif extern int check_if_legal_filename(const char *path); +extern int check_if_legal_tablename(const char *path); #ifndef TERMINATE extern void TERMINATE(FILE *file); --- 1.324/sql/sql_table.cc 2006-04-01 12:38:29 +05:00 +++ 1.325/sql/sql_table.cc 2006-04-11 18:16:03 +05:00 @@ -72,12 +72,19 @@ uint filename_to_tablename(const char *f uint tablename_to_filename(const char *from, char *to, uint to_length) { - uint errors; + uint errors, length; if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX, MYSQL50_TABLE_NAME_PREFIX_LENGTH)) return my_snprintf(to, to_length, "%s", from + 9); - return strconvert(system_charset_info, from, - &my_charset_filename, to, to_length, &errors); + length= strconvert(system_charset_info, from, + &my_charset_filename, to, to_length, &errors); + if (check_if_legal_tablename(to) && + length + 4 < to_length) + { + memcpy(to + length, "@@@", 4); + length+= 3; + } + return length; } --- 1.102/strings/ctype-utf8.c 2006-03-23 21:40:47 +04:00 +++ 1.103/strings/ctype-utf8.c 2006-04-11 18:16:03 +05:00 @@ -3943,6 +3943,11 @@ my_mb_wc_filename(CHARSET_INFO *cs __att *pwc= touni[code]; return 3; } + if (byte1 == '@' && byte2 == '@') + { + *pwc= 0; + return 3; + } } if (s + 4 > e) --- New file --- +++ mysql-test/r/ctype_filename.result 06/04/11 18:16:03 drop table if exists con, aux, nul, lpt1, com1, `clock$`; create table con (a int); drop table con; create table aux (a int); drop table aux; create table nul (a int); drop table nul; create table lpt1 (a int); drop table lpt1; create table com1 (a int); drop table com1; create table `clock$` (a int); drop table `clock$`; --- New file --- +++ mysql-test/t/ctype_filename.test 06/04/11 18:16:03 --disable_warnings drop table if exists con, aux, nul, lpt1, com1, `clock$`; --enable_warnings create table con (a int); drop table con; create table aux (a int); drop table aux; create table nul (a int); drop table nul; create table lpt1 (a int); drop table lpt1; create table com1 (a int); drop table com1; create table `clock$` (a int); drop table `clock$`; --- 1.7/mysys/my_access.c 2005-09-01 07:11:41 +05:00 +++ 1.8/mysys/my_access.c 2006-04-11 18:16:03 +05:00 @@ -54,23 +54,110 @@ int my_access(const char *path, int amod #endif /* __WIN__ */ -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) /* List of file names that causes problem on windows NOTE that one can also not have file names of type CON.TXT + + NOTE: it is important to keep "CLOCK$" on the first place, + we skip it in check_if_legal_tablename. */ - static const char *reserved_names[]= { - "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", - "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", - "LPT7", "LPT8", "LPT9", "CLOCK$", + "CLOCK$", + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", NullS }; #define MAX_RESERVED_NAME_LENGTH 6 + + +/* + Looks up a null-terminated string in a list, + case insensitively. + + SYNOPSIS + str_list_find() + list list of items + str item to find + + RETURN + 0 ok + 1 reserved file name +*/ +static int str_list_find(const char **list, const char *str) +{ + const char **name; + for (name= list; *name; name++) + { + if (!my_strcasecmp(&my_charset_latin1, *name, str)) + return 1; + } + return 0; +} + + +/* + A map for faster reserved_names lookup, + helps to avoid loops in many cases. + 1 - can be the first letter + 2 - can be the second letter + 4 - can be the third letter +*/ +static char reserved_map[256]= +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* !"#$%&'()*+,-./ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0123456789:;<=>? */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* @ABCDEFGHIJKLMNO */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* PQRSTUVWXYZ[\]^_ */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* bcdefghijklmno */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* pqrstuvwxyz{|}~. */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* ................ */ +}; + + +/* + Check if a table name may cause problems + + SYNOPSIS + check_if_legal_tablename + name Table name (without any extensions) + + DESCRIPTION + We don't check 'CLOCK$' because dollar sign is encoded as @0024, + making table file name 'CLOCK@0024', which is safe. + This is why we start lookup from the second element + (i.e. &reserver_name[1]) + + RETURN + 0 ok + 1 reserved file name +*/ + +int check_if_legal_tablename(const char *name) +{ + DBUG_ENTER("check_if_legal_tablename"); + DBUG_RETURN((reserved_map[(uchar) name[0]] & 1) && + (reserved_map[(uchar) name[1]] & 2) && + (reserved_map[(uchar) name[2]] & 4) && + str_list_find(&reserved_names[1], name)); +} + + +#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) + /* Check if a path will access a reserverd file name that may cause problems