summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmokmss <tomookam@live.jp>2022-06-05 08:04:18 +0000
committerNikita Malyavin <nikitamalyavin@gmail.com>2022-08-26 12:40:58 +0300
commit827b049e1e7df204feb744a270b4dca619a61de1 (patch)
tree607c8f72697c91d696c7a931af1698d545e57f00
parent851058a3e6f40cd2714762916235ebe93fc594b5 (diff)
downloadmariadb-git-827b049e1e7df204feb744a270b4dca619a61de1.tar.gz
MDEV-18873 Server crashes in Compare_identifiers::operator or in my_strcasecmp_utf8 upon ADD PERIOD IF NOT EXISTS with empty name
empty identifier specified as `` ends up with a NULL LEX_CSTRING::str in lexer. This is not considered correct in upper layers, for example in Compare_identifiers::operator(). Empty column name is usually avoided by a check_column_name() call while parsing, and period name matches the column name completely. Hence, this fix uses the mentioned call for verification, too.
-rw-r--r--mysql-test/suite/period/r/alter.result14
-rw-r--r--mysql-test/suite/period/t/alter.test23
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/table.cc6
-rw-r--r--sql/table.h1
-rw-r--r--sql/vers_string.h2
6 files changed, 52 insertions, 0 deletions
diff --git a/mysql-test/suite/period/r/alter.result b/mysql-test/suite/period/r/alter.result
index a6466c8944b..875dab93b68 100644
--- a/mysql-test/suite/period/r/alter.result
+++ b/mysql-test/suite/period/r/alter.result
@@ -190,3 +190,17 @@ alter table t1 add primary key(x, s, e);
ERROR 23000: Duplicate entry '1-2020-03-01-2020-03-02' for key 'PRIMARY'
alter table t1 add system versioning;
drop table t1;
+#
+# MDEV-18873 Server crashes in Compare_identifiers::operator or in
+# my_strcasecmp_utf8 upon ADD PERIOD IF NOT EXISTS with empty name
+#
+alter table t add period if not exists for `` (s,e);
+ERROR 42000: Incorrect column name ''
+create table t(s DATE, e DATE);
+alter table t add period if not exists for `` (s,e);
+ERROR 42000: Incorrect column name ''
+alter table t add period if not exists for ` ` (s,e);
+ERROR 42000: Incorrect column name ' '
+create table t2 (period for `` (s,e)) select * from t;
+ERROR 42000: Incorrect column name ''
+drop table t;
diff --git a/mysql-test/suite/period/t/alter.test b/mysql-test/suite/period/t/alter.test
index 3fa3c5c87d5..2a82f74b670 100644
--- a/mysql-test/suite/period/t/alter.test
+++ b/mysql-test/suite/period/t/alter.test
@@ -151,3 +151,26 @@ alter table t1 add system versioning;
# cleanup
drop table t1;
+
+--echo #
+--echo # MDEV-18873 Server crashes in Compare_identifiers::operator or in
+--echo # my_strcasecmp_utf8 upon ADD PERIOD IF NOT EXISTS with empty name
+--echo #
+
+# When there is no table defined.
+--error ER_WRONG_COLUMN_NAME
+alter table t add period if not exists for `` (s,e);
+
+# When there is an actual table.
+create table t(s DATE, e DATE);
+--error ER_WRONG_COLUMN_NAME
+alter table t add period if not exists for `` (s,e);
+
+# When the last character is space
+--error ER_WRONG_COLUMN_NAME
+alter table t add period if not exists for ` ` (s,e);
+
+# Create table with an empty period name
+--error ER_WRONG_COLUMN_NAME
+create table t2 (period for `` (s,e)) select * from t;
+drop table t;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index be41b45c335..976d1b79cad 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -33,6 +33,7 @@
#include "sql_tvc.h"
#include "item.h"
#include "sql_schema.h"
+#include "table.h"
/* Used for flags of nesting constructs */
#define SELECT_NESTING_MAP_SIZE 64
@@ -4449,6 +4450,11 @@ public:
int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end)
{
+ if (check_period_name(name.str)) {
+ my_error(ER_WRONG_COLUMN_NAME, MYF(0), name.str);
+ return 1;
+ }
+
if (lex_string_cmp(system_charset_info, &start, &end) == 0)
{
my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), start.str);
diff --git a/sql/table.cc b/sql/table.cc
index 7957f2da593..1a30809cde9 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4918,6 +4918,12 @@ bool check_column_name(const char *name)
}
+bool check_period_name(const char *name)
+{
+ return check_column_name(name);
+}
+
+
/**
Checks whether a table is intact. Should be done *just* after the table has
been opened.
diff --git a/sql/table.h b/sql/table.h
index c9503b54934..3f750e7b221 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -3231,6 +3231,7 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
bool check_db_name(LEX_STRING *db);
bool check_column_name(const char *name);
+bool check_period_name(const char *name);
bool check_table_name(const char *name, size_t length, bool check_for_path_chars);
int rename_file_ext(const char * from,const char * to,const char * ext);
char *get_field(MEM_ROOT *mem, Field *field);
diff --git a/sql/vers_string.h b/sql/vers_string.h
index 2349cc0cac1..cfadc890dcd 100644
--- a/sql/vers_string.h
+++ b/sql/vers_string.h
@@ -39,6 +39,8 @@ struct Compare_identifiers
{
int operator()(const LEX_CSTRING& a, const LEX_CSTRING& b) const
{
+ DBUG_ASSERT(a.str != NULL);
+ DBUG_ASSERT(b.str != NULL);
DBUG_ASSERT(a.str[a.length] == 0);
DBUG_ASSERT(b.str[b.length] == 0);
return my_strcasecmp(system_charset_info, a.str, b.str);