Commit e8e0d5c5 authored by bar@mysql.com's avatar bar@mysql.com

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).
parent 58ad5593
......@@ -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);
......
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$`;
--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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment