mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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). include/my_sys.h: Adding new function declaration mysys/my_access.c: 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$". sql/sql_table.cc: Check if a dangerous table name and append @@@ strings/ctype-utf8.c: Treat "@@@" sequence in a table name as a end-of-line. mysql-test/r/ctype_filename.result: New BitKeeper file ``mysql-test/r/ctype_filename.result'' mysql-test/t/ctype_filename.test: New BitKeeper file ``mysql-test/t/ctype_filename.test''
This commit is contained in:
@ -608,6 +608,7 @@ extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
|
||||
#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);
|
||||
|
13
mysql-test/r/ctype_filename.result
Normal file
13
mysql-test/r/ctype_filename.result
Normal file
@ -0,0 +1,13 @@
|
||||
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$`;
|
21
mysql-test/t/ctype_filename.test
Normal file
21
mysql-test/t/ctype_filename.test
Normal file
@ -0,0 +1,21 @@
|
||||
--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$`;
|
@ -54,24 +54,111 @@ int my_access(const char *path, int amode)
|
||||
|
||||
#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
|
||||
|
||||
|
@ -72,12 +72,19 @@ uint filename_to_tablename(const char *from, char *to, uint to_length)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3943,6 +3943,11 @@ my_mb_wc_filename(CHARSET_INFO *cs __attribute__((unused)),
|
||||
*pwc= touni[code];
|
||||
return 3;
|
||||
}
|
||||
if (byte1 == '@' && byte2 == '@')
|
||||
{
|
||||
*pwc= 0;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (s + 4 > e)
|
||||
|
Reference in New Issue
Block a user