Commit aa3eb77e authored by unknown's avatar unknown
Browse files

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''
parent ef430928
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
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 −0
Original line number Diff line number Diff line
--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$`;
+92 −5
Original line number Diff line number Diff line
@@ -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
 
+10 −3
Original line number Diff line number Diff line
@@ -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,
  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;
}


Loading