Below is the list of changes that have just been committed into a local
5.0 repository of alik. When alik 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@stripped, 2006-07-29 18:11:53+04:00, anozdrin@booka. +35 -0
Fix for BUG#16899: Possible buffer overflow in handling of DEFINER-clause
User name (host name) has limit on length. The server code relies on these
limits when storing the names. The problem was that sometimes these limits were
not checked properly, so that could lead to buffer overflow.
The fix is to:
1. Introduce User_name and Host_name classes, which incapsulate user name and
host name respectively. These classes check for limits. If the limit is
exceeded, the string should be trimmed and warning should be thrown.
2. Transform LEX_USER to class Lex_user, which contains User_name and
Host_name instances.
3. Change trigger-handling code so that statement query is produced once for
replication log and trigger file.
BitKeeper/etc/collapsed@stripped, 2006-07-29 12:38:33+04:00, anozdrin@booka. +2 -0
BitKeeper file /mnt/raid/alik/MySQL/devel/5.0-rt-bug16899/BitKeeper/etc/collapsed
BitKeeper/etc/collapsed@stripped, 2006-07-29 12:38:33+04:00, anozdrin@booka. +0 -0
client/mysqldump.c@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +46 -18
Updated parse_user().
include/m_string.h@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +18 -0
Moved LEX_STRING out of server directory.
include/my_user.h@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +13 -3
Updated parse_user().
mysql-test/r/sp.result@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +23 -0
Updated result file.
mysql-test/r/trigger.result@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +21 -0
Updated result file.
mysql-test/r/view.result@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +27 -0
Updated result file.
mysql-test/t/sp.test@stripped, 2006-07-29 18:11:48+04:00, anozdrin@booka. +36 -0
Added test for BUG#16899.
mysql-test/t/trigger.test@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +36 -0
Updated result file.
mysql-test/t/view.test@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +32 -0
Updated result file.
sql-common/my_user.c@stripped, 2006-07-29 18:11:50+04:00, anozdrin@booka. +54 -20
parse_user() impl.
sql/mysql_priv.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +4 -4
Added convenient get_field() function.
sql/set_var.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +28 -9
Updated set_var_password() to work with modified LEX_USER.
sql/set_var.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +8 -5
Updated set_var_password() to work with modified LEX_USER.
sql/share/errmsg.txt@stripped, 2006-07-29 18:11:50+04:00, anozdrin@booka. +4 -0
Aded new error messages.
sql/sp.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +37 -23
Updated.
sql/sp_head.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +17 -5
Use new parse_user().
sql/sp_head.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +1 -1
Use LEX_STRING.
sql/spatial.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +4 -1
Get rid of LEX_STRING_WITH_INIT.
sql/spatial.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +1 -1
Get rid of LEX_STRING_WITH_INIT.
sql/sql_acl.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +273 -183
Reflect LEX_USER changes.
sql/sql_acl.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +8 -8
LEX_USER -> Lex_user
sql/sql_class.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +27 -0
Provide server-wide callbacks for parse_user().
sql/sql_class.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +11 -0
Provide server-wide callbacks for parse_user().
sql/sql_lex.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +3 -3
LEX_USER -> Lex_user
sql/sql_parse.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +54 -80
1. Reflect LEX_USER changes.
2. Eleminate create_definer().
sql/sql_show.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +13 -6
Reflect LEX_USER changes.
sql/sql_string.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +0 -2
Get rid of STRING_WITH_LEN.
sql/sql_trigger.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +72 -71
1. Reflect LEX_USER changes.
2. Changed trigger-handling code so that there will be the one
place for generate statement string for replication log
and for trigger file.
sql/sql_trigger.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +2 -4
Changed trigger-handling code so that there will be the one
place for generate statement string for replication log
and for trigger file.
sql/sql_view.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +16 -16
Reflect LEX_USER changes.
sql/sql_yacc.yy@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +86 -74
Reflect LEX_USER changes.
sql/structs.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +0 -21
LEX_USER changed.
sql/table.cc@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +137 -19
Reflect LEX_USER changes.
sql/table.h@stripped, 2006-07-29 18:11:49+04:00, anozdrin@booka. +181 -1
Reflect LEX_USER changes.
# 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: anozdrin
# Host: booka.
# Root: /home/alik/MySQL/devel/5.0-rt-bug16899
--- 1.232/client/mysqldump.c 2006-07-29 18:12:00 +04:00
+++ 1.233/client/mysqldump.c 2006-07-29 18:12:00 +04:00
@@ -1893,6 +1893,24 @@ continue_xml:
} /* get_table_structure */
+static void mysqldump_on_user_name_truncated(const PARSE_USER_CB_CTX *ctx)
+{
+ fprintf(stderr,
+ "Warning: user name '%s' has been truncated to %d symbols\n",
+ (const char *) ctx->original_name,
+ (int) USERNAME_LENGTH);
+}
+
+
+static void mysqldump_on_host_name_truncated(const PARSE_USER_CB_CTX *ctx)
+{
+ fprintf(stderr,
+ "Warning: host name '%s' has been truncated to %d symbols\n",
+ (const char *) ctx->original_name,
+ (int) HOSTNAME_LENGTH);
+}
+
+
/*
dump_triggers_for_table
@@ -1949,20 +1967,25 @@ DELIMITER ;;\n");
we should check if we have this column before accessing it.
*/
- uint user_name_len;
- char user_name_str[USERNAME_LENGTH + 1];
+ LEX_STRING user_id= { row[7], strlen(row[7]) };
+
+ char user_name_holder[USERNAME_LENGTH + 1];
+ LEX_STRING user_name= { user_name_holder, USERNAME_LENGTH };
+
+ char host_name_holder[HOSTNAME_LENGTH + 1];
+ LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
+
char quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
- uint host_name_len;
- char host_name_str[HOSTNAME_LENGTH + 1];
char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
- parse_user(row[7], strlen(row[7]), user_name_str, &user_name_len,
- host_name_str, &host_name_len);
+ parse_user(&user_id, &user_name, &host_name,
+ mysqldump_on_user_name_truncated,
+ mysqldump_on_host_name_truncated);
fprintf(sql_file,
"/*!50017 DEFINER=%s@%s */ ",
- quote_name(user_name_str, quoted_user_name_str, FALSE),
- quote_name(host_name_str, quoted_host_name_str, FALSE));
+ quote_name(user_name.str, quoted_user_name_str, FALSE),
+ quote_name(host_name.str, quoted_host_name_str, FALSE));
}
fprintf(sql_file,
@@ -3465,29 +3488,34 @@ static my_bool get_view_structure(char *
Surround it with !50013 comments
*/
{
- uint user_name_len;
- char user_name_str[USERNAME_LENGTH + 1];
+ LEX_STRING user_id= { row[1], lengths[1] };
+
+ char user_name_holder[USERNAME_LENGTH + 1];
+ LEX_STRING user_name= { user_name_holder, USERNAME_LENGTH };
+
+ char host_name_holder[HOSTNAME_LENGTH + 1];
+ LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
+
char quoted_user_name_str[USERNAME_LENGTH * 2 + 3];
- uint host_name_len;
- char host_name_str[HOSTNAME_LENGTH + 1];
char quoted_host_name_str[HOSTNAME_LENGTH * 2 + 3];
- parse_user(row[1], lengths[1], user_name_str, &user_name_len,
- host_name_str, &host_name_len);
+ parse_user(&user_id, &user_name, &host_name,
+ mysqldump_on_user_name_truncated,
+ mysqldump_on_host_name_truncated);
ptr= search_buf;
search_len=
(ulong)(strxmov(ptr, "DEFINER=",
- quote_name(user_name_str, quoted_user_name_str, FALSE),
+ quote_name(user_name.str, quoted_user_name_str, FALSE),
"@",
- quote_name(host_name_str, quoted_host_name_str, FALSE),
+ quote_name(host_name.str, quoted_host_name_str, FALSE),
" SQL SECURITY ", row[2], NullS) - ptr);
ptr= replace_buf;
replace_len=
(ulong)(strxmov(ptr, "*/\n/*!50013 DEFINER=",
- quote_name(user_name_str, quoted_user_name_str, FALSE),
+ quote_name(user_name.str, quoted_user_name_str, FALSE),
"@",
- quote_name(host_name_str, quoted_host_name_str, FALSE),
+ quote_name(host_name.str, quoted_host_name_str, FALSE),
" SQL SECURITY ", row[2],
" */\n/*!50001", NullS) - ptr);
replace(&ds_view, search_buf, search_len, replace_buf, replace_len);
--- 1.37/include/m_string.h 2006-07-29 18:12:00 +04:00
+++ 1.38/include/m_string.h 2006-07-29 18:12:00 +04:00
@@ -259,4 +259,22 @@ extern int my_snprintf(char* to, size_t
#if defined(__cplusplus) && !defined(OS2)
}
#endif
+
+/*
+ LEX_STRING -- a pair of a C-string and its length.
+
+ NOTE: this exactly form of declaration is required for some C-compilers
+ (for one, Sun C 5.7 2005/01/07). Unfortunately with such declaration
+ LEX_STRING can not be forward declared.
+*/
+
+typedef struct
+{
+ char *str;
+ uint length;
+} LEX_STRING;
+
+#define STRING_WITH_LEN(X) (X), ((uint) (sizeof(X) - 1))
+#define C_STRING_WITH_LEN(X) ((char *) (X)), ((uint) (sizeof(X) - 1))
+
#endif
--- 1.399/sql/mysql_priv.h 2006-07-29 18:12:00 +04:00
+++ 1.400/sql/mysql_priv.h 2006-07-29 18:12:00 +04:00
@@ -551,10 +551,9 @@ bool create_table_precheck(THD *thd, TAB
int append_query_string(CHARSET_INFO *csinfo,
String const *from, String *to);
-void get_default_definer(THD *thd, LEX_USER *definer);
-LEX_USER *create_default_definer(THD *thd);
-LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
-LEX_USER *get_current_user(THD *thd, LEX_USER *user);
+void get_default_definer(THD *thd, Lex_user *definer);
+Lex_user *create_default_definer(THD *thd);
+Lex_user *get_current_user(THD *thd, Lex_user *user);
enum enum_mysql_completiontype {
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
@@ -1465,6 +1464,7 @@ int rename_file_ext(const char * from,co
bool check_db_name(char *db);
bool check_column_name(const char *name);
bool check_table_name(const char *name, uint length);
+bool get_field(MEM_ROOT *mem, Field *field, LEX_STRING *value);
char *get_field(MEM_ROOT *mem, Field *field);
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
--- 1.198/sql/sql_acl.cc 2006-07-29 18:12:00 +04:00
+++ 1.199/sql/sql_acl.cc 2006-07-29 18:12:00 +04:00
@@ -1737,7 +1737,7 @@ static bool test_if_create_new_users(THD
Handle GRANT commands
****************************************************************************/
-static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
+static int replace_user_table(THD *thd, TABLE *table, const Lex_user &combo,
ulong rights, bool revoke_grant,
bool can_create_user, bool no_auto_create)
{
@@ -1764,8 +1764,12 @@ static int replace_user_table(THD *thd,
password=combo.password.str;
}
- table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
- table->field[1]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
+ system_charset_info);
+ table->field[1]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
+ system_charset_info);
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
@@ -1777,7 +1781,9 @@ static int replace_user_table(THD *thd,
/* what == 'N' means revoke */
if (what == 'N')
{
- my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str);
+ my_error(ER_NONEXISTING_GRANT, MYF(0),
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str());
goto end;
}
/*
@@ -1795,7 +1801,9 @@ static int replace_user_table(THD *thd,
*/
else if (!password_len && no_auto_create)
{
- my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
+ my_error(ER_PASSWORD_NO_MATCH, MYF(0),
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str());
goto end;
}
else if (!can_create_user)
@@ -1806,9 +1814,11 @@ static int replace_user_table(THD *thd,
}
old_row_exists = 0;
restore_record(table,s->default_values);
- table->field[0]->store(combo.host.str,combo.host.length,
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
system_charset_info);
- table->field[1]->store(combo.user.str,combo.user.length,
+ table->field[1]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
system_charset_info);
table->field[2]->store(password, password_len,
system_charset_info);
@@ -1931,7 +1941,8 @@ end:
{
acl_cache->clear(1); // Clear privilege cache
if (old_row_exists)
- acl_update_user(combo.user.str, combo.host.str,
+ acl_update_user(combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
combo.password.str, password_len,
lex->ssl_type,
lex->ssl_cipher,
@@ -1940,7 +1951,9 @@ end:
&lex->mqh,
rights);
else
- acl_insert_user(combo.user.str, combo.host.str, password, password_len,
+ acl_insert_user(combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
+ password, password_len,
lex->ssl_type,
lex->ssl_cipher,
lex->x509_issuer,
@@ -1957,7 +1970,7 @@ end:
*/
static int replace_db_table(TABLE *table, const char *db,
- const LEX_USER &combo,
+ const Lex_user &combo,
ulong rights, bool revoke_grant)
{
uint i;
@@ -1975,15 +1988,20 @@ static int replace_db_table(TABLE *table
}
/* Check if there is such a user in user table in memory? */
- if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
+ if (!find_acl_user(combo.host_name.get_c_str(),
+ combo.user_name.get_c_str(), FALSE))
{
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
DBUG_RETURN(-1);
}
- table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
+ system_charset_info);
table->field[1]->store(db,(uint) strlen(db), system_charset_info);
- table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[2]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
+ system_charset_info);
key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length);
@@ -1994,14 +2012,20 @@ static int replace_db_table(TABLE *table
{
if (what == 'N')
{ // no row, no revoke
- my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str);
+ my_error(ER_NONEXISTING_GRANT, MYF(0),
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str());
goto abort;
}
old_row_exists = 0;
restore_record(table, s->default_values);
- table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
+ system_charset_info);
table->field[1]->store(db,(uint) strlen(db), system_charset_info);
- table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[2]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
+ system_charset_info);
}
else
{
@@ -2041,10 +2065,13 @@ static int replace_db_table(TABLE *table
acl_cache->clear(1); // Clear privilege cache
if (old_row_exists)
- acl_update_db(combo.user.str,combo.host.str,db,rights);
- else
- if (rights)
- acl_insert_db(combo.user.str,combo.host.str,db,rights);
+ acl_update_db(combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
+ db, rights);
+ else if (rights)
+ acl_insert_db(combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
+ db, rights);
DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */
@@ -2320,7 +2347,7 @@ column_hash_search(GRANT_TABLE *t, const
static int replace_column_table(GRANT_TABLE *g_t,
- TABLE *table, const LEX_USER &combo,
+ TABLE *table, const Lex_user &combo,
List <LEX_COLUMN> &columns,
const char *db, const char *table_name,
ulong rights, bool revoke_grant)
@@ -2331,11 +2358,13 @@ static int replace_column_table(GRANT_TA
KEY_PART_INFO *key_part= table->key_info->key_part;
DBUG_ENTER("replace_column_table");
- table->field[0]->store(combo.host.str,combo.host.length,
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
system_charset_info);
table->field[1]->store(db,(uint) strlen(db),
system_charset_info);
- table->field[2]->store(combo.user.str,combo.user.length,
+ table->field[2]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
system_charset_info);
table->field[3]->store(table_name,(uint) strlen(table_name),
system_charset_info);
@@ -2374,7 +2403,8 @@ static int replace_column_table(GRANT_TA
if (revoke_grant)
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- combo.user.str, combo.host.str,
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
table_name); /* purecov: inspected */
result= -1; /* purecov: inspected */
continue; /* purecov: inspected */
@@ -2508,7 +2538,7 @@ end:
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
- TABLE *table, const LEX_USER &combo,
+ TABLE *table, const Lex_user &combo,
const char *db, const char *table_name,
ulong rights, ulong col_rights,
bool revoke_grant)
@@ -2527,7 +2557,8 @@ static int replace_table_table(THD *thd,
The following should always succeed as new users are created before
this function is called!
*/
- if (!find_acl_user(combo.host.str,combo.user.str, FALSE))
+ if (!find_acl_user(combo.host_name.get_c_str(),
+ combo.user_name.get_c_str(), FALSE))
{
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
MYF(0)); /* purecov: deadcode */
@@ -2535,9 +2566,13 @@ static int replace_table_table(THD *thd,
}
restore_record(table, s->default_values); // Get empty record
- table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(),
+ system_charset_info);
table->field[1]->store(db,(uint) strlen(db), system_charset_info);
- table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[2]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(),
+ system_charset_info);
table->field[3]->store(table_name,(uint) strlen(table_name),
system_charset_info);
store_record(table,record[1]); // store at pos 1
key_copy(user_key, table->record[0], table->key_info,
@@ -2556,7 +2591,8 @@ static int replace_table_table(THD *thd,
if (revoke_grant)
{ // no row, no revoke
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- combo.user.str, combo.host.str,
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
table_name); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */
}
@@ -2627,7 +2663,7 @@ table_error:
static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
- TABLE *table, const LEX_USER &combo,
+ TABLE *table, const Lex_user &combo,
const char *db, const char *routine_name,
bool is_proc, ulong rights, bool revoke_grant)
{
@@ -2650,16 +2686,20 @@ static int replace_routine_table(THD *th
The following should always succeed as new users are created before
this function is called!
*/
- if (!find_acl_user(combo.host.str, combo.user.str, FALSE))
+ if (!find_acl_user(combo.host_name.get_c_str(),
+ combo.user_name.get_c_str(),
+ FALSE))
{
my_error(ER_PASSWORD_NO_MATCH,MYF(0));
DBUG_RETURN(-1);
}
restore_record(table, s->default_values); // Get empty record
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
+ table->field[0]->store(combo.host_name.get_c_str(),
+ combo.host_name.get_length(), &my_charset_latin1);
table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[2]->store(combo.user_name.get_c_str(),
+ combo.user_name.get_length(), &my_charset_latin1);
table->field[3]->store(routine_name,(uint) strlen(routine_name),
&my_charset_latin1);
table->field[4]->store((longlong)(is_proc ?
@@ -2679,7 +2719,9 @@ static int replace_routine_table(THD *th
if (revoke_grant)
{ // no row, no revoke
my_error(ER_NONEXISTING_PROC_GRANT, MYF(0),
- combo.user.str, combo.host.str, routine_name);
+ combo.user_name.get_c_str(),
+ combo.host_name.get_c_str(),
+ routine_name);
DBUG_RETURN(-1);
}
old_row_exists= 0;
@@ -2760,13 +2802,13 @@ table_error:
*/
bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
- List <LEX_USER> &user_list,
+ List <Lex_user> &user_list,
List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant)
{
ulong column_priv= 0;
- List_iterator <LEX_USER> str_list (user_list);
- LEX_USER *Str, *tmp_Str;
+ List_iterator <Lex_user> str_list (user_list);
+ Lex_user *Str, *tmp_Str;
TABLE_LIST tables[3];
bool create_new_users=0;
char *db_name, *table_name;
@@ -2899,15 +2941,8 @@ bool mysql_table_grant(THD *thd, TABLE_L
{
result= TRUE;
continue;
- }
- if (Str->host.length > HOSTNAME_LENGTH ||
- Str->user.length > USERNAME_LENGTH)
- {
- my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
- MYF(0));
- result= TRUE;
- continue;
}
+
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
@@ -2927,19 +2962,21 @@ bool mysql_table_grant(THD *thd, TABLE_L
table_list->table_name);
/* Find/create cached table grant */
- grant_table= table_hash_search(Str->host.str, NullS, db_name,
- Str->user.str, table_name, 1);
+ grant_table= table_hash_search(Str->host_name.get_c_str(), NullS, db_name,
+ Str->user_name.get_c_str(), table_name, 1);
if (!grant_table)
{
if (revoke_grant)
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- Str->user.str, Str->host.str, table_list->table_name);
+ Str->user_name.get_c_str(),
+ Str->host_name.get_c_str(),
+ table_list->table_name);
result= TRUE;
continue;
}
- grant_table = new GRANT_TABLE (Str->host.str, db_name,
- Str->user.str, table_name,
+ grant_table = new GRANT_TABLE (Str->host_name.get_c_str(), db_name,
+ Str->user_name.get_c_str(), table_name,
rights,
column_priv);
if (!grant_table) // end of memory
@@ -3031,11 +3068,11 @@ bool mysql_table_grant(THD *thd, TABLE_L
*/
bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
- List <LEX_USER> &user_list, ulong rights,
+ List <Lex_user> &user_list, ulong rights,
bool revoke_grant, bool no_error)
{
- List_iterator <LEX_USER> str_list (user_list);
- LEX_USER *Str, *tmp_Str;
+ List_iterator <Lex_user> str_list (user_list);
+ Lex_user *Str, *tmp_Str;
TABLE_LIST tables[2];
bool create_new_users=0, result=0;
char *db_name, *table_name;
@@ -3111,16 +3148,8 @@ bool mysql_routine_grant(THD *thd, TABLE
{
result= TRUE;
continue;
- }
- if (Str->host.length > HOSTNAME_LENGTH ||
- Str->user.length > USERNAME_LENGTH)
- {
- if (!no_error)
- my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
- MYF(0));
- result= TRUE;
- continue;
}
+
/* Create user if needed */
error=replace_user_table(thd, tables[0].table, *Str,
0, revoke_grant, create_new_users,
@@ -3135,20 +3164,23 @@ bool mysql_routine_grant(THD *thd, TABLE
db_name= table_list->db;
table_name= table_list->table_name;
- grant_name= routine_hash_search(Str->host.str, NullS, db_name,
- Str->user.str, table_name, is_proc, 1);
+ grant_name= routine_hash_search(Str->host_name.get_c_str(), NullS,
+ db_name, Str->user_name.get_c_str(),
+ table_name, is_proc, 1);
if (!grant_name)
{
if (revoke_grant)
{
if (!no_error)
my_error(ER_NONEXISTING_PROC_GRANT, MYF(0),
- Str->user.str, Str->host.str, table_name);
+ Str->user_name.get_c_str(),
+ Str->host_name.get_c_str(),
+ table_name);
result= TRUE;
continue;
}
- grant_name= new GRANT_NAME(Str->host.str, db_name,
- Str->user.str, table_name,
+ grant_name= new GRANT_NAME(Str->host_name.get_c_str(), db_name,
+ Str->user_name.get_c_str(), table_name,
rights);
if (!grant_name)
{
@@ -3176,11 +3208,11 @@ bool mysql_routine_grant(THD *thd, TABLE
}
-bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
+bool mysql_grant(THD *thd, const char *db, List <Lex_user> &list,
ulong rights, bool revoke_grant)
{
- List_iterator <LEX_USER> str_list (list);
- LEX_USER *Str, *tmp_Str;
+ List_iterator <Lex_user> str_list (list);
+ Lex_user *Str, *tmp_Str;
char tmp_db[NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
@@ -3245,15 +3277,8 @@ bool mysql_grant(THD *thd, const char *d
{
result= TRUE;
continue;
- }
- if (Str->host.length > HOSTNAME_LENGTH ||
- Str->user.length > USERNAME_LENGTH)
- {
- my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
- MYF(0));
- result= -1;
- continue;
}
+
if (replace_user_table(thd, tables[0].table, *Str,
(!db ? rights : 0), revoke_grant, create_new_users,
test(thd->variables.sql_mode &
@@ -4114,7 +4139,7 @@ static uint command_lengths[]=
};
-static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash,
+static int show_routine_grants(THD *thd, Lex_user *lex_user, HASH *hash,
const char *type, int typelen,
char *buff, int buffsize);
@@ -4126,7 +4151,7 @@ static int show_routine_grants(THD *thd,
Send to client grant-like strings depicting user@host privileges
*/
-bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
+bool mysql_show_grants(THD *thd,Lex_user *lex_user)
{
ulong want_access;
uint counter,index;
@@ -4144,25 +4169,27 @@ bool mysql_show_grants(THD *thd,LEX_USER
DBUG_RETURN(TRUE);
}
- if (lex_user->host.length > HOSTNAME_LENGTH ||
- lex_user->user.length > USERNAME_LENGTH)
+ if (lex_user->host_name.is_truncated() ||
+ lex_user->user_name.is_truncated())
{
- my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
- MYF(0));
+ my_message(ER_GRANT_WRONG_HOST_OR_USER,
+ ER(ER_GRANT_WRONG_HOST_OR_USER), MYF(0));
DBUG_RETURN(TRUE);
}
rw_rdlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- acl_user= find_acl_user(lex_user->host.str, lex_user->user.str, TRUE);
+ acl_user= find_acl_user(lex_user->host_name.get_c_str(),
+ lex_user->user_name.get_c_str(), TRUE);
if (!acl_user)
{
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
my_error(ER_NONEXISTING_GRANT, MYF(0),
- lex_user->user.str, lex_user->host.str);
+ lex_user->user_name.get_c_str(),
+ lex_user->host_name.get_c_str());
DBUG_RETURN(TRUE);
}
@@ -4170,8 +4197,8 @@ bool mysql_show_grants(THD *thd,LEX_USER
List<Item> field_list;
field->name=buff;
field->max_length=1024;
- strxmov(buff,"Grants for ",lex_user->user.str,"@",
- lex_user->host.str,NullS);
+ strxmov(buff, "Grants for ", lex_user->user_name.get_c_str(), "@",
+ lex_user->host_name.get_c_str(), NullS);
field_list.push_back(field);
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -4209,10 +4236,12 @@ bool mysql_show_grants(THD *thd,LEX_USER
}
}
global.append (STRING_WITH_LEN(" ON *.* TO '"));
- global.append(lex_user->user.str, lex_user->user.length,
+ global.append(lex_user->user_name.get_c_str(),
+ lex_user->user_name.get_length(),
system_charset_info);
global.append (STRING_WITH_LEN("'@'"));
- global.append(lex_user->host.str,lex_user->host.length,
+ global.append(lex_user->host_name.get_c_str(),
+ lex_user->host_name.get_length(),
system_charset_info);
global.append ('\'');
if (acl_user->salt_len)
@@ -4299,8 +4328,9 @@ bool mysql_show_grants(THD *thd,LEX_USER
if (!(host=acl_db->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info, lex_user->host_name.get_c_str(),
+ host))
{
want_access=acl_db->access;
if (want_access)
@@ -4331,10 +4361,12 @@ bool mysql_show_grants(THD *thd,LEX_USER
db.append (STRING_WITH_LEN(" ON "));
append_identifier(thd, &db, acl_db->db, strlen(acl_db->db));
db.append (STRING_WITH_LEN(".* TO '"));
- db.append(lex_user->user.str, lex_user->user.length,
+ db.append(lex_user->user_name.get_c_str(),
+ lex_user->user_name.get_length(),
system_charset_info);
db.append (STRING_WITH_LEN("'@'"));
- db.append(lex_user->host.str, lex_user->host.length,
+ db.append(lex_user->host_name.get_c_str(),
+ lex_user->host_name.get_length(),
system_charset_info);
db.append ('\'');
if (want_access & GRANT_ACL)
@@ -4362,8 +4394,10 @@ bool mysql_show_grants(THD *thd,LEX_USER
if (!(host= grant_table->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info,
+ lex_user->host_name.get_c_str(),
+ host))
{
ulong table_access= grant_table->privs;
if ((table_access | grant_table->cols) != 0)
@@ -4439,10 +4473,12 @@ bool mysql_show_grants(THD *thd,LEX_USER
append_identifier(thd, &global, grant_table->tname,
strlen(grant_table->tname));
global.append(STRING_WITH_LEN(" TO '"));
- global.append(lex_user->user.str, lex_user->user.length,
+ global.append(lex_user->user_name.get_c_str(),
+ lex_user->user_name.get_length(),
system_charset_info);
global.append(STRING_WITH_LEN("'@'"));
- global.append(lex_user->host.str,lex_user->host.length,
+ global.append(lex_user->host_name.get_c_str(),
+ lex_user->host_name.get_length(),
system_charset_info);
global.append('\'');
if (table_access & GRANT_ACL)
@@ -4480,7 +4516,7 @@ end:
DBUG_RETURN(error);
}
-static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
+static int show_routine_grants(THD* thd, Lex_user *lex_user, HASH *hash,
const char *type, int typelen,
char *buff, int buffsize)
{
@@ -4498,8 +4534,10 @@ static int show_routine_grants(THD* thd,
if (!(host= grant_proc->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info,
+ lex_user->host_name.get_c_str(),
+ host))
{
ulong proc_access= grant_proc->privs;
if (proc_access != 0)
@@ -4538,10 +4576,12 @@ static int show_routine_grants(THD* thd,
append_identifier(thd, &global, grant_proc->tname,
strlen(grant_proc->tname));
global.append(STRING_WITH_LEN(" TO '"));
- global.append(lex_user->user.str, lex_user->user.length,
+ global.append(lex_user->user_name.get_c_str(),
+ lex_user->user_name.get_length(),
system_charset_info);
global.append(STRING_WITH_LEN("'@'"));
- global.append(lex_user->host.str,lex_user->host.length,
+ global.append(lex_user->host_name.get_c_str(),
+ lex_user->host_name.get_length(),
system_charset_info);
global.append('\'');
if (proc_access & GRANT_ACL)
@@ -4700,7 +4740,7 @@ int open_grant_tables(THD *thd, TABLE_LI
*/
static int modify_grant_table(TABLE *table, Field *host_field,
- Field *user_field, LEX_USER *user_to)
+ Field *user_field, Lex_user *user_to)
{
int error;
DBUG_ENTER("modify_grant_table");
@@ -4709,9 +4749,11 @@ static int modify_grant_table(TABLE *tab
{
/* rename */
store_record(table, record[1]);
- host_field->store(user_to->host.str, user_to->host.length,
+ host_field->store(user_to->host_name.get_c_str(),
+ user_to->host_name.get_length(),
system_charset_info);
- user_field->store(user_to->user.str, user_to->user.length,
+ user_field->store(user_to->user_name.get_c_str(),
+ user_to->user_name.get_length(),
system_charset_info);
if ((error= table->file->update_row(table->record[1], table->record[0])))
table->file->print_error(error, MYF(0));
@@ -4760,15 +4802,15 @@ static int modify_grant_table(TABLE *tab
*/
static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
- LEX_USER *user_from, LEX_USER *user_to)
+ Lex_user *user_from, Lex_user *user_to)
{
int result= 0;
int error;
TABLE *table= tables[table_no].table;
Field *host_field= table->field[0];
Field *user_field= table->field[table_no ? 2 : 1];
- char *host_str= user_from->host.str;
- char *user_str= user_from->user.str;
+ char *host_str= user_from->host_name.get_c_str();
+ char *user_str= user_from->user_name.get_c_str();
const char *host;
const char *user;
byte user_key[MAX_KEY_LENGTH];
@@ -4788,8 +4830,10 @@ static int handle_grant_table(TABLE_LIST
*/
DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'",
table->s->table_name, user_str, host_str));
- host_field->store(host_str, user_from->host.length, system_charset_info);
- user_field->store(user_str, user_from->user.length, system_charset_info);
+ host_field->store(host_str, user_from->host_name.get_length(),
+ system_charset_info);
+ user_field->store(user_str, user_from->user_name.get_length(),
+ system_charset_info);
key_prefix_length= (table->key_info->key_part[0].store_length +
table->key_info->key_part[1].store_length);
@@ -4904,7 +4948,7 @@ static int handle_grant_table(TABLE_LIST
*/
static int handle_grant_struct(uint struct_no, bool drop,
- LEX_USER *user_from, LEX_USER *user_to)
+ Lex_user *user_from, Lex_user *user_to)
{
int result= 0;
uint idx;
@@ -4916,7 +4960,8 @@ static int handle_grant_struct(uint stru
GRANT_NAME *grant_name;
DBUG_ENTER("handle_grant_struct");
DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'",
- struct_no, user_from->user.str, user_from->host.str));
+ struct_no, user_from->user_name.get_c_str(),
+ user_from->host_name.get_c_str()));
LINT_INIT(acl_user);
LINT_INIT(acl_db);
@@ -4944,7 +4989,8 @@ static int handle_grant_struct(uint stru
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
- struct_no, user_from->user.str, user_from->host.str));
+ struct_no, user_from->user_name.get_c_str(),
+ user_from->host_name.get_c_str()));
#endif
/* Loop over all elements. */
for (idx= 0; idx < elements; idx++)
@@ -4986,8 +5032,10 @@ static int handle_grant_struct(uint stru
DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
struct_no, idx, user, host));
#endif
- if (strcmp(user_from->user.str, user) ||
- my_strcasecmp(system_charset_info, user_from->host.str, host))
+ if (strcmp(user_from->user_name.get_c_str(), user) ||
+ my_strcasecmp(system_charset_info,
+ user_from->host_name.get_c_str(),
+ host))
continue;
result= 1; /* At least one element found. */
@@ -5018,20 +5066,22 @@ static int handle_grant_struct(uint stru
{
switch ( struct_no ) {
case 0:
- acl_user->user= strdup_root(&mem, user_to->user.str);
- acl_user->host.hostname= strdup_root(&mem, user_to->host.str);
+ acl_user->user= strdup_root(&mem, user_to->user_name.get_c_str());
+ acl_user->host.hostname= strdup_root(&mem,
+ user_to->host_name.get_c_str());
break;
case 1:
- acl_db->user= strdup_root(&mem, user_to->user.str);
- acl_db->host.hostname= strdup_root(&mem, user_to->host.str);
+ acl_db->user= strdup_root(&mem, user_to->user_name.get_c_str());
+ acl_db->host.hostname= strdup_root(&mem,
+ user_to->host_name.get_c_str());
break;
case 2:
case 3:
- grant_name->user= strdup_root(&mem, user_to->user.str);
+ grant_name->user= strdup_root(&mem, user_to->user_name.get_c_str());
update_hostname(&grant_name->host,
- strdup_root(&mem, user_to->host.str));
+ strdup_root(&mem, user_to->host_name.get_c_str()));
break;
}
}
@@ -5074,7 +5124,7 @@ static int handle_grant_struct(uint stru
*/
static int handle_grant_data(TABLE_LIST *tables, bool drop,
- LEX_USER *user_from, LEX_USER *user_to)
+ Lex_user *user_from, Lex_user *user_to)
{
int result= 0;
int found;
@@ -5172,14 +5222,14 @@ static int handle_grant_data(TABLE_LIST
}
-static void append_user(String *str, LEX_USER *user)
+static void append_user(String *str, Lex_user *user)
{
if (str->length())
str->append(',');
str->append('\'');
- str->append(user->user.str);
+ str->append(user->user_name.get_c_str());
str->append(STRING_WITH_LEN("'@'"));
- str->append(user->host.str);
+ str->append(user->host_name.get_c_str());
str->append('\'');
}
@@ -5197,13 +5247,13 @@ static void append_user(String *str, LEX
TRUE Error.
*/
-bool mysql_create_user(THD *thd, List <LEX_USER> &list)
+bool mysql_create_user(THD *thd, List <Lex_user> &list)
{
int result;
String wrong_users;
ulong sql_mode;
- LEX_USER *user_name, *tmp_user_name;
- List_iterator <LEX_USER> user_list(list);
+ Lex_user *user_name, *tmp_user_name;
+ List_iterator <Lex_user> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_create_user");
@@ -5262,12 +5312,12 @@ bool mysql_create_user(THD *thd, List <L
TRUE Error.
*/
-bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
+bool mysql_drop_user(THD *thd, List <Lex_user> &list)
{
int result;
String wrong_users;
- LEX_USER *user_name, *tmp_user_name;
- List_iterator <LEX_USER> user_list(list);
+ Lex_user *user_name, *tmp_user_name;
+ List_iterator <Lex_user> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_drop_user");
@@ -5318,13 +5368,13 @@ bool mysql_drop_user(THD *thd, List <LEX
TRUE Error.
*/
-bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
+bool mysql_rename_user(THD *thd, List <Lex_user> &list)
{
int result;
String wrong_users;
- LEX_USER *user_from, *tmp_user_from;
- LEX_USER *user_to, *tmp_user_to;
- List_iterator <LEX_USER> user_list(list);
+ Lex_user *user_from, *tmp_user_from;
+ Lex_user *user_to, *tmp_user_to;
+ List_iterator <Lex_user> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
DBUG_ENTER("mysql_rename_user");
@@ -5388,7 +5438,7 @@ bool mysql_rename_user(THD *thd, List <L
< 0 Error. Error message not yet sent.
*/
-bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
+bool mysql_revoke_all(THD *thd, List <Lex_user> &list)
{
uint counter, revoked, is_proc;
int result;
@@ -5402,19 +5452,21 @@ bool mysql_revoke_all(THD *thd, List <L
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
- LEX_USER *lex_user, *tmp_lex_user;
- List_iterator <LEX_USER> user_list(list);
+ Lex_user *lex_user, *tmp_lex_user;
+ List_iterator <Lex_user> user_list(list);
while ((tmp_lex_user= user_list++))
{
if (!(lex_user= get_current_user(thd, tmp_lex_user)))
{
result= -1;
continue;
- }
- if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE))
+ }
+ if (!find_acl_user(lex_user->host_name.get_c_str(),
+ lex_user->user_name.get_c_str(), TRUE))
{
sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
- "exists", lex_user->user.str, lex_user->host.str);
+ "exists", lex_user->user_name.get_c_str(),
+ lex_user->host_name.get_c_str());
result= -1;
continue;
}
@@ -5444,8 +5496,10 @@ bool mysql_revoke_all(THD *thd, List <L
if (!(host=acl_db->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info,
+ lex_user->host_name.get_c_str(),
+ host))
{
if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, ~(ulong)0, 1))
{
@@ -5475,8 +5529,10 @@ bool mysql_revoke_all(THD *thd, List <L
if (!(host=grant_table->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info,
+ lex_user->host_name.get_c_str(),
+ host))
{
if (replace_table_table(thd,grant_table,tables[2].table,*lex_user,
grant_table->db,
@@ -5521,8 +5577,10 @@ bool mysql_revoke_all(THD *thd, List <L
if (!(host=grant_proc->host.hostname))
host= "";
- if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ if (!strcmp(lex_user->user_name.get_c_str(), user) &&
+ !my_strcasecmp(system_charset_info,
+ lex_user->host_name.get_c_str(),
+ host))
{
if (!replace_routine_table(thd,grant_proc,tables[4].table,*lex_user,
grant_proc->db,
@@ -5589,13 +5647,24 @@ bool sp_revoke_privileges(THD *thd, cons
if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) &&
!my_strcasecmp(system_charset_info, grant_proc->tname, sp_name))
{
- LEX_USER lex_user;
- lex_user.user.str= grant_proc->user;
- lex_user.user.length= strlen(grant_proc->user);
- lex_user.host.str= grant_proc->host.hostname ?
- grant_proc->host.hostname : (char*)"";
- lex_user.host.length= grant_proc->host.hostname ?
- strlen(grant_proc->host.hostname) : 0;
+ LEX_STRING user_name_str= { grant_proc->user,
+ strlen(grant_proc->user) };
+ LEX_STRING host_name_str;
+ Lex_user lex_user;
+
+ if (grant_proc->host.hostname)
+ {
+ host_name_str.str= grant_proc->host.hostname;
+ host_name_str.length= strlen(host_name_str.str);
+ }
+ else
+ {
+ host_name_str.str= (char *) "";
+ host_name_str.length= 1;
+ }
+
+ lex_user.set(thd, &user_name_str, &host_name_str, NULL);
+
if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user,
grant_proc->db, grant_proc->tname,
is_proc, ~(ulong)0, 1))
@@ -5638,35 +5707,62 @@ bool sp_grant_privileges(THD *thd, const
bool is_proc)
{
Security_context *sctx= thd->security_ctx;
- LEX_USER *combo;
+ Lex_user *combo;
TABLE_LIST tables[1];
- List<LEX_USER> user_list;
+ List<Lex_user> user_list;
bool result;
ACL_USER *au;
char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
DBUG_ENTER("sp_grant_privileges");
- if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ if (!(combo=(Lex_user*) thd->alloc(sizeof(Lex_user))))
DBUG_RETURN(TRUE);
- combo->user.str= sctx->user;
+ {
+ LEX_STRING user_name_str= { sctx->user, strlen(sctx->user) };
+ user_name_str.str= thd->strmake(user_name_str.str,
+ user_name_str.length);
- VOID(pthread_mutex_lock(&acl_cache->lock));
+ combo->user_name.set(thd, &user_name_str);
+ }
- if ((au=
find_acl_user(combo->host.str=(char*)sctx->host_or_ip,combo->user.str,FALSE)))
- goto found_acl;
- if ((au= find_acl_user(combo->host.str=(char*)sctx->host,
combo->user.str,FALSE)))
- goto found_acl;
- if ((au= find_acl_user(combo->host.str=(char*)sctx->ip,
combo->user.str,FALSE)))
- goto found_acl;
- if((au= find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE)))
- goto found_acl;
+ {
+ const char *user_name= combo->user_name.get_c_str();
+ const char *host_name= NULL;
+ const char *host_name_variants[]=
+ {
+ sctx->host_or_ip,
+ sctx->host,
+ sctx->ip,
+ "%",
+ NULL
+ };
- VOID(pthread_mutex_unlock(&acl_cache->lock));
- DBUG_RETURN(TRUE);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
- found_acl:
- VOID(pthread_mutex_unlock(&acl_cache->lock));
+ for (const char *var= host_name_variants[0]; var; ++var)
+ {
+ if ((au= find_acl_user(var, user_name, FALSE)))
+ {
+ host_name= var;
+ break;
+ }
+ }
+
+ if (host_name)
+ {
+ LEX_STRING host_name_str= { (char *) host_name, strlen(host_name) };
+ host_name_str.str= thd->strmake(host_name_str.str,
+ host_name_str.length);
+
+ combo->host_name.set(thd, &host_name_str);
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (!host_name)
+ DBUG_RETURN(TRUE);
+ }
bzero((char*)tables, sizeof(TABLE_LIST));
user_list.empty();
@@ -5674,12 +5770,6 @@ bool sp_grant_privileges(THD *thd, const
tables->db= (char*)sp_db;
tables->table_name= tables->alias= (char*)sp_name;
- combo->host.length= strlen(combo->host.str);
- combo->user.length= strlen(combo->user.str);
- combo->host.str= thd->strmake(combo->host.str,combo->host.length);
- combo->user.str= thd->strmake(combo->user.str,combo->user.length);
-
-
if(au && au->salt_len)
{
if (au->salt_len == SCRAMBLE_LENGTH)
@@ -5701,8 +5791,8 @@ bool sp_grant_privileges(THD *thd, const
}
else
{
- combo->password.str= (char*)"";
- combo->password.length= 0;
+ combo->password.str= (char *) "";
+ combo->password.length= 1;
}
if (user_list.push_back(combo))
@@ -5712,7 +5802,7 @@ bool sp_grant_privileges(THD *thd, const
bzero((char*) &thd->lex->mqh, sizeof(thd->lex->mqh));
result= mysql_routine_grant(thd, tables, is_proc, user_list,
- DEFAULT_CREATE_PROC_ACLS, 0, 1);
+ DEFAULT_CREATE_PROC_ACLS, 0, 1);
DBUG_RETURN(result);
}
@@ -5723,9 +5813,9 @@ bool sp_grant_privileges(THD *thd, const
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
template class List_iterator<LEX_COLUMN>;
-template class List_iterator<LEX_USER>;
+template class List_iterator<Lex_user>;
template class List<LEX_COLUMN>;
-template class List<LEX_USER>;
+template class List<Lex_user>;
#endif
#endif /*NO_EMBEDDED_ACCESS_CHECKS */
--- 1.50/sql/sql_acl.h 2006-07-29 18:12:00 +04:00
+++ 1.51/sql/sql_acl.h 2006-07-29 18:12:00 +04:00
@@ -188,13 +188,13 @@ bool check_change_password(THD *thd, con
char *password, uint password_len);
bool change_password(THD *thd, const char *host, const char *user,
char *password);
-bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
+bool mysql_grant(THD *thd, const char *db, List <Lex_user> &user_list,
ulong rights, bool revoke);
-bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
+bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <Lex_user> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
bool mysql_routine_grant(THD *thd, TABLE_LIST *table, bool is_proc,
- List <LEX_USER> &user_list, ulong rights,
+ List <Lex_user> &user_list, ulong rights,
bool revoke, bool no_error);
my_bool grant_init();
void grant_free(void);
@@ -216,13 +216,13 @@ ulong get_table_grant(THD *thd, TABLE_LI
ulong get_column_grant(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name,
const char *field_name);
-bool mysql_show_grants(THD *thd, LEX_USER *user);
+bool mysql_show_grants(THD *thd, Lex_user *user);
void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
-bool mysql_create_user(THD *thd, List <LEX_USER> &list);
-bool mysql_drop_user(THD *thd, List <LEX_USER> &list);
-bool mysql_rename_user(THD *thd, List <LEX_USER> &list);
-bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
+bool mysql_create_user(THD *thd, List <Lex_user> &list);
+bool mysql_drop_user(THD *thd, List <Lex_user> &list);
+bool mysql_rename_user(THD *thd, List <Lex_user> &list);
+bool mysql_revoke_all(THD *thd, List <Lex_user> &list);
void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
const char *db, const char *table);
bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
--- 1.239/sql/sql_class.cc 2006-07-29 18:12:00 +04:00
+++ 1.240/sql/sql_class.cc 2006-07-29 18:12:00 +04:00
@@ -2199,3 +2199,30 @@ void xid_cache_delete(XID_STATE *xid_sta
pthread_mutex_unlock(&LOCK_xid_cache);
}
+
+/**************************************************************************
+ Callbacks for parse_user() in MySQL-server.
+**************************************************************************/
+
+C_MODE_START
+
+void mysqld_on_user_name_truncated(const PARSE_USER_CB_CTX *ctx)
+{
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_USER_NAME_TRUNCATED,
+ ER(ER_USER_NAME_TRUNCATED),
+ (const char *) ctx->original_name,
+ USERNAME_LENGTH);
+}
+
+
+void mysqld_on_host_name_truncated(const PARSE_USER_CB_CTX *ctx)
+{
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_HOST_NAME_TRUNCATED,
+ ER(ER_HOST_NAME_TRUNCATED),
+ (const char *) ctx->original_name,
+ HOSTNAME_LENGTH);
+}
+
+C_MODE_END
--- 1.293/sql/sql_class.h 2006-07-29 18:12:00 +04:00
+++ 1.294/sql/sql_class.h 2006-07-29 18:12:00 +04:00
@@ -21,6 +21,8 @@
#pragma interface /* gcc class implementation */
#endif
+#include "my_user.h"
+
// TODO: create log.h and move all the log header stuff there
class Query_log_event;
@@ -2154,3 +2156,12 @@ public:
/* Functions in sql_class.cc */
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var);
+
+/* Callbacks for parse_user() in MySQL-server. */
+
+C_MODE_START
+
+extern void mysqld_on_user_name_truncated(const PARSE_USER_CB_CTX *ctx);
+extern void mysqld_on_host_name_truncated(const PARSE_USER_CB_CTX *ctx);
+
+C_MODE_END
--- 1.223/sql/sql_lex.h 2006-07-29 18:12:00 +04:00
+++ 1.224/sql/sql_lex.h 2006-07-29 18:12:00 +04:00
@@ -830,7 +830,7 @@ typedef struct st_lex : public Query_tab
select_result *result;
Item *default_value, *on_update_value;
LEX_STRING comment, ident;
- LEX_USER *grant_user;
+ Lex_user *grant_user;
XID *xid;
gptr yacc_yyss,yacc_yyvs;
THD *thd;
@@ -844,12 +844,12 @@ typedef struct st_lex : public Query_tab
The definer of the object being created (view, trigger, stored routine).
I.e. the value of DEFINER clause.
*/
- LEX_USER *definer;
+ Lex_user *definer;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
List<String> interval_list;
- List<LEX_USER> users_list;
+ List<Lex_user> users_list;
List<LEX_COLUMN> columns;
List<Key> key_list;
List<create_field> create_list;
--- 1.561/sql/sql_parse.cc 2006-07-29 18:12:00 +04:00
+++ 1.562/sql/sql_parse.cc 2006-07-29 18:12:00 +04:00
@@ -731,24 +731,28 @@ end:
}
-static void reset_mqh(LEX_USER *lu, bool get_them= 0)
+static void reset_mqh(Lex_user *lu, bool get_them= 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT
{
USER_CONN *uc;
- uint temp_len=lu->user.length+lu->host.length+2;
+ uint temp_len= lu->user_name.get_length() + lu->host_name.get_length() + 2;
char temp_user[USER_HOST_BUFF_SIZE];
- memcpy(temp_user,lu->user.str,lu->user.length);
- memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
- temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
+ memcpy(temp_user,lu->user_name.get_c_str(), lu->user_name.get_length());
+ memcpy(temp_user + lu->user_name.get_length() + 1,
+ lu->host_name.get_c_str(), lu->host_name.get_length());
+
+ temp_user[lu->user_name.get_length()]= '\0';
+ temp_user[temp_len - 1]= '\0';
+
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len)))
{
uc->questions=0;
- get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
+ get_mqh(temp_user,&temp_user[lu->user_name.get_length() + 1], uc);
uc->updates=0;
uc->conn_per_hour=0;
}
@@ -3898,27 +3902,29 @@ end_with_restore_list:
if (thd->security_ctx->user) // If not replication
{
- LEX_USER *user, *tmp_user;
+ Lex_user *user, *tmp_user;
- List_iterator <LEX_USER> user_list(lex->users_list);
+ List_iterator <Lex_user> user_list(lex->users_list);
while ((tmp_user= user_list++))
{
if (!(user= get_current_user(thd, tmp_user)))
goto error;
if (specialflag & SPECIAL_NO_RESOLVE &&
- hostname_requires_resolving(user->host.str))
+ hostname_requires_resolving(user->host_name.get_c_str()))
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_HOSTNAME_WONT_WORK,
ER(ER_WARN_HOSTNAME_WONT_WORK),
- user->host.str);
+ user->host_name.get_c_str());
// Are we trying to change a password of another user
- DBUG_ASSERT(user->host.str != 0);
- if (strcmp(thd->security_ctx->user, user->user.str) ||
+ DBUG_ASSERT(user->host_name.get_c_str() != 0);
+ if (strcmp(thd->security_ctx->user, user->user_name.get_c_str()) ||
my_strcasecmp(system_charset_info,
- user->host.str, thd->security_ctx->host_or_ip))
+ user->host_name.get_c_str(),
+ thd->security_ctx->host_or_ip))
{
// TODO: use check_change_password()
- if (is_acl_user(user->host.str, user->user.str) &&
+ if (is_acl_user(user->host_name.get_c_str(),
+ user->user_name.get_c_str()) &&
user->password.str &&
check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
{
@@ -3985,8 +3991,8 @@ end_with_restore_list:
}
if (lex->sql_command == SQLCOM_GRANT)
{
- List_iterator <LEX_USER> str_list(lex->users_list);
- LEX_USER *user, *tmp_user;
+ List_iterator <Lex_user> str_list(lex->users_list);
+ Lex_user *user, *tmp_user;
while ((tmp_user=str_list++))
{
if (!(user= get_current_user(thd, tmp_user)))
@@ -4048,11 +4054,12 @@ end_with_restore_list:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS:
{
- LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
+ Lex_user *grant_user= get_current_user(thd, lex->grant_user);
if (!grant_user)
goto error;
if ((thd->security_ctx->priv_user &&
- !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
+ !strcmp(thd->security_ctx->priv_user,
+ grant_user->user_name.get_c_str())) ||
!check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
{
res = mysql_show_grants(thd, grant_user);
@@ -4302,9 +4309,10 @@ end_with_restore_list:
routine under another user one must have SUPER privilege).
*/
- else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+ else if (strcmp(lex->definer->user_name.get_c_str(),
+ thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info,
- lex->definer->host.str,
+ lex->definer->host_name.get_c_str(),
thd->security_ctx->priv_host))
{
if (check_global_access(thd, SUPER_ACL))
@@ -4319,15 +4327,15 @@ end_with_restore_list:
/* Check that the specified definer exists. Emit a warning if not. */
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (!is_acl_user(lex->definer->host.str,
- lex->definer->user.str))
+ if (!is_acl_user(lex->definer->host_name.get_c_str(),
+ lex->definer->user_name.get_c_str()))
{
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
- lex->definer->user.str,
- lex->definer->host.str);
+ lex->definer->user_name.get_c_str(),
+ lex->definer->host_name.get_c_str());
}
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
@@ -6698,7 +6706,7 @@ bool reload_acl_and_cache(THD *thd, ulon
my_pthread_setspecific_ptr(THR_THD, 0);
thd= 0;
}
- reset_mqh((LEX_USER *)NULL, TRUE);
+ reset_mqh((Lex_user *)NULL, TRUE);
}
#endif
if (options & REFRESH_LOG)
@@ -6822,7 +6830,7 @@ bool reload_acl_and_cache(THD *thd, ulon
}
#endif
if (options & REFRESH_USER_RESOURCES)
- reset_mqh((LEX_USER *) NULL);
+ reset_mqh((Lex_user *) NULL);
*write_to_binlog= tmp_write_to_binlog;
return result;
}
@@ -7427,22 +7435,21 @@ Item *negate_expression(THD *thd, Item *
/*
Set the specified definer to the default value, which is the current user in
the thread.
-
+
SYNOPSIS
get_default_definer()
thd [in] thread handler
definer [out] definer
*/
-
-void get_default_definer(THD *thd, LEX_USER *definer)
-{
- const Security_context *sctx= thd->security_ctx;
- definer->user.str= (char *) sctx->priv_user;
- definer->user.length= strlen(definer->user.str);
+void get_default_definer(THD *thd, Lex_user *definer)
+{
+ LEX_STRING user_name_str= { (char *) thd->security_ctx->priv_user,
+ strlen(thd->security_ctx->priv_user) };
+ LEX_STRING host_name_str= { (char *) thd->security_ctx->priv_host,
+ strlen(thd->security_ctx->priv_host) };
- definer->host.str= (char *) sctx->priv_host;
- definer->host.length= strlen(definer->host.str);
+ definer->set(thd, &user_name_str, &host_name_str, NULL);
}
@@ -7455,15 +7462,15 @@ void get_default_definer(THD *thd, LEX_U
RETURN
On success, return a valid pointer to the created and initialized
- LEX_USER, which contains definer information.
+ Lex_user, which contains definer information.
On error, return 0.
*/
-LEX_USER *create_default_definer(THD *thd)
+Lex_user *create_default_definer(THD *thd)
{
- LEX_USER *definer;
+ Lex_user *definer;
- if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
+ if (! (definer= (Lex_user*) thd->alloc(sizeof(Lex_user))))
return 0;
get_default_definer(thd, definer);
@@ -7473,37 +7480,6 @@ LEX_USER *create_default_definer(THD *th
/*
- Create definer with the given user and host names.
-
- SYNOPSIS
- create_definer()
- thd [in] thread handler
- user_name [in] user name
- host_name [in] host name
-
- RETURN
- On success, return a valid pointer to the created and initialized
- LEX_USER, which contains definer information.
- On error, return 0.
-*/
-
-LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
-{
- LEX_USER *definer;
-
- /* Create and initialize. */
-
- if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
- return 0;
-
- definer->user= *user_name;
- definer->host= *host_name;
-
- return definer;
-}
-
-
-/*
Retuns information about user or current user.
SYNOPSIS
@@ -7513,20 +7489,18 @@ LEX_USER *create_definer(THD *thd, LEX_S
RETURN
On success, return a valid pointer to initialized
- LEX_USER, which contains user information.
- On error, return 0.
+ Lex_user, which contains user information.
+ On error, return NULL.
*/
-LEX_USER *get_current_user(THD *thd, LEX_USER *user)
+Lex_user *get_current_user(THD *thd, Lex_user *user)
{
- LEX_USER *curr_user;
- if (!user->user.str) // current_user
+ Lex_user *curr_user;
+ if (!user->user_name.get_c_str()) // current_user
{
- if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
- {
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER));
- return 0;
- }
+ if (!(curr_user= (Lex_user*) thd->alloc(sizeof(Lex_user))))
+ return NULL;
+
get_default_definer(thd, curr_user);
return curr_user;
}
--- 1.324/sql/sql_show.cc 2006-07-29 18:12:00 +04:00
+++ 1.325/sql/sql_show.cc 2006-07-29 18:12:00 +04:00
@@ -1097,7 +1097,10 @@ void
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
{
append_algorithm(table, buff);
- append_definer(thd, buff, &table->definer.user, &table->definer.host);
+ append_definer(thd, buff,
+ table->definer.user_name.get_str(),
+ table->definer.host_name.get_str());
+
if (table->view_suid)
buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
else
@@ -1107,7 +1110,7 @@ view_store_options(THD *thd, TABLE_LIST
/*
Append DEFINER clause to the given buffer.
-
+
SYNOPSIS
append_definer()
thd [in] thread handle
@@ -3093,9 +3096,11 @@ static int get_schema_views_record(THD *
ulong grant= SHOW_VIEW_ACL;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
char *save_table_name= tables->table_name;
- if (!my_strcasecmp(system_charset_info, tables->definer.user.str,
+ if (!my_strcasecmp(system_charset_info,
+ tables->definer.user_name.get_c_str(),
sctx->priv_user) &&
- !my_strcasecmp(system_charset_info, tables->definer.host.str,
+ !my_strcasecmp(system_charset_info,
+ tables->definer.host_name.get_c_str(),
sctx->priv_host))
grant= SHOW_VIEW_ACL;
else
@@ -3140,8 +3145,10 @@ static int get_schema_views_record(THD *
table->field[5]->store(STRING_WITH_LEN("YES"), cs);
else
table->field[5]->store(STRING_WITH_LEN("NO"), cs);
- definer_len= (strxmov(definer, tables->definer.user.str, "@",
- tables->definer.host.str, NullS) - definer);
+ definer_len= strxmov(definer,
+ tables->definer.user_name.get_c_str(), "@",
+ tables->definer.host_name.get_c_str(), NullS) -
+ definer;
table->field[6]->store(definer, definer_len, cs);
if (tables->view_suid)
table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
--- 1.60/sql/sql_string.h 2006-07-29 18:12:00 +04:00
+++ 1.61/sql/sql_string.h 2006-07-29 18:12:00 +04:00
@@ -24,8 +24,6 @@
#define NOT_FIXED_DEC 31
#endif
-#define STRING_WITH_LEN(X) ((const char*) X), ((uint) (sizeof(X) - 1))
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
--- 1.476/sql/sql_yacc.yy 2006-07-29 18:12:00 +04:00
+++ 1.477/sql/sql_yacc.yy 2006-07-29 18:12:00 +04:00
@@ -86,7 +86,7 @@ inline Item *is_truth_value(Item *A, boo
key_part_spec *key_part;
TABLE_LIST *table_list;
udf_func *udf;
- LEX_USER *lex_user;
+ Lex_user *lex_user;
struct sys_var_with_base variable;
enum enum_var_type var_type;
Key::Keytype key_type;
@@ -6529,10 +6529,10 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
- LEX_USER *curr_user;
- if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
- YYABORT;
- bzero(curr_user, sizeof(st_lex_user));
+ Lex_user *curr_user;
+ if (!(curr_user= (Lex_user*) lex->thd->alloc(sizeof(Lex_user))))
+ YYABORT;
+ bzero(curr_user, sizeof(Lex_user));
lex->grant_user= curr_user;
}
| GRANTS FOR_SYM user
@@ -6540,7 +6540,7 @@ show_param:
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_GRANTS;
lex->grant_user=$3;
- lex->grant_user->password=null_lex_str;
+ lex->grant_user->reset_password();
}
| CREATE DATABASE opt_if_not_exists ident
{
@@ -7466,30 +7466,30 @@ ident_or_text:
user:
ident_or_text
{
- THD *thd= YYTHD;
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ LEX_STRING host_name_str= { C_STRING_WITH_LEN("%") };
+
+ if (!($$=(Lex_user*) YYTHD->alloc(sizeof(Lex_user))))
YYABORT;
- $$->user = $1;
- $$->host.str= (char *) "%";
- $$->host.length= 1;
+
+ $$->set(YYTHD, &$1, &host_name_str, NULL);
}
| ident_or_text '@' ident_or_text
- {
- THD *thd= YYTHD;
- if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
- YYABORT;
- $$->user = $1; $$->host=$3;
- }
+ {
+ if (!($$=(Lex_user*) YYTHD->alloc(sizeof(Lex_user))))
+ YYABORT;
+
+ $$->set(YYTHD, &$1, &$3, NULL);
+ }
| CURRENT_USER optional_braces
{
- if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
- YYABORT;
- /*
- empty LEX_USER means current_user and
- will be handled in the get_current_user() function
- later
- */
- bzero($$, sizeof(LEX_USER));
+ if (!($$=(Lex_user*) YYTHD->alloc(sizeof(Lex_user))))
+ YYABORT;
+ /*
+ empty Lex_user means current_user and
+ will be handled in the get_current_user() function
+ later
+ */
+ bzero($$, sizeof(Lex_user));
};
/* Keyword that we allow for identifiers (except SP labels) */
@@ -8018,30 +8018,33 @@ option_value:
lex->var_list.push_back(new set_var_collation_client($3,$3,$3));
}
| PASSWORD equal text_or_password
- {
- THD *thd=YYTHD;
- LEX_USER *user;
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
- LEX_STRING pw;
+ {
+ THD *thd=YYTHD;
+ Lex_user *user;
+ LEX_STRING user_name_str= { thd->security_ctx->priv_user,
+ strlen(thd->security_ctx->priv_user) };
+ LEX *lex= Lex;
+ sp_pcontext *spc= lex->spcont;
+ LEX_STRING pw;
- pw.str= (char *)"password";
- pw.length= 8;
- if (spc && spc->find_variable(&pw))
- {
- my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
- YYABORT;
- }
- if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
- YYABORT;
- user->host=null_lex_str;
- user->user.str=thd->security_ctx->priv_user;
- thd->lex->var_list.push_back(new set_var_password(user, $3));
- }
- | PASSWORD FOR_SYM user equal text_or_password
+ pw.str= (char *)"password";
+ pw.length= 8;
+ if (spc && spc->find_variable(&pw))
{
- Lex->var_list.push_back(new set_var_password($3,$5));
+ my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
+ YYABORT;
}
+ thd->lex->var_list.push_back(
+ new set_var_password(thd, &user_name_str, NULL, $3));
+ }
+ | PASSWORD FOR_SYM user equal text_or_password
+ {
+ Lex->var_list.push_back(
+ new set_var_password(YYTHD,
+ $3->user_name.get_str(),
+ $3->host_name.get_str(),
+ $5));
+ }
;
internal_variable_name:
@@ -8569,33 +8572,40 @@ grant_list:
grant_user:
user IDENTIFIED_SYM BY TEXT_STRING
{
- $$=$1; $1->password=$4;
- if ($4.length)
- {
- if (YYTHD->variables.old_passwords)
- {
- char *buff=
- (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
- if (buff)
- make_scrambled_password_323(buff, $4.str);
- $1->password.str= buff;
- $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
- }
- else
- {
- char *buff=
- (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
- if (buff)
- make_scrambled_password(buff, $4.str);
- $1->password.str= buff;
- $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
- }
+ $$=$1;
+ $1->password= $4;
+ if ($4.length)
+ {
+ if (YYTHD->variables.old_passwords)
+ {
+ char *buff=
+ (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
+ if (buff)
+ make_scrambled_password_323(buff, $4.str);
+ $1->password.str= buff;
+ $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+ }
+ else
+ {
+ char *buff=
+ (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
+ if (buff)
+ make_scrambled_password(buff, $4.str);
+ $1->password.str= buff;
+ $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+ }
}
}
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
- { $$= $1; $1->password= $5; }
+ {
+ $$= $1;
+ $1->password= $5;
+ }
| user
- { $$= $1; $1->password= null_lex_str; }
+ {
+ $$= $1;
+ $1->reset_password();
+ }
;
@@ -8954,17 +8964,19 @@ definer:
from older master servers (i.e. to create non-suid trigger in this
case).
*/
- YYTHD->lex->definer= 0;
+ Lex->definer= NULL;
}
| DEFINER_SYM EQ CURRENT_USER optional_braces
{
- if (! (YYTHD->lex->definer= create_default_definer(YYTHD)))
- YYABORT;
+ if (! (YYTHD->lex->definer= create_default_definer(YYTHD)))
+ YYABORT;
}
| DEFINER_SYM EQ ident_or_text '@' ident_or_text
{
- if (!(YYTHD->lex->definer= create_definer(YYTHD, &$3, &$5)))
- YYABORT;
+ if (!(Lex->definer= (Lex_user *) YYTHD->alloc(sizeof (Lex_user))))
+ YYABORT;
+
+ Lex->definer->set(YYTHD, &$3, &$5, NULL);
}
;
--- 1.55/sql/structs.h 2006-07-29 18:12:00 +04:00
+++ 1.56/sql/structs.h 2006-07-29 18:12:00 +04:00
@@ -20,22 +20,6 @@
struct st_table;
class Field;
-typedef struct st_lex_string
-{
- char *str;
- uint length;
-} LEX_STRING;
-
-typedef struct st_lex_string_with_init :public st_lex_string
-{
- st_lex_string_with_init(const char *str_arg, uint length_arg)
- {
- str= (char*) str_arg;
- length= length_arg;
- }
-} LEX_STRING_WITH_INIT;
-
-
typedef struct st_date_time_format {
uchar positions[8];
char time_separator; /* Separator between hour and minute */
@@ -207,11 +191,6 @@ typedef struct show_var_st {
char *value;
SHOW_TYPE type;
} SHOW_VAR;
-
-
-typedef struct st_lex_user {
- LEX_STRING user, host, password;
-} LEX_USER;
/*
--- 1.229/sql/table.cc 2006-07-29 18:12:00 +04:00
+++ 1.230/sql/table.cc 2006-07-29 18:12:00 +04:00
@@ -1549,27 +1549,60 @@ bool get_field(MEM_ROOT *mem, Field *fie
SYNOPSIS
get_field()
- mem MEM_ROOT for allocating
- field Field for retrieving of string
+ mem [IN] MEM_ROOT for allocating
+ field [IN] Field for retrieving of string
+ value [OUT] Buffer for field value
RETURN VALUES
- NullS string is empty
+ TRUE out of memory
+ FALSE all ok
+*/
+
+bool get_field(MEM_ROOT *mem, Field *field, LEX_STRING *value)
+{
+ char buff[MAX_FIELD_WIDTH];
+ String str(buff, sizeof (buff), &my_charset_bin);
+
+ field->val_str(&str);
+ value->length= str.length();
+
+ if (!value->length)
+ return FALSE;
+
+ if (!(value->str= (char *) alloc_root(mem, value->length + 1)))
+ return TRUE;
+
+ memcpy(value->str, str.ptr(), value->length);
+ value->str[value->length]= '\0';
+
+ return FALSE;
+}
+
+
+/*
+ Allocate string field in MEM_ROOT and return it as NULL-terminated string
+
+ SYNOPSIS
+ get_field()
+ mem MEM_ROOT for allocating
+ field Field for retrieving of string
+
+ RETURN VALUES
+ NullS string is empty or out-of-memory error
# pointer to NULL-terminated string value of field
*/
char *get_field(MEM_ROOT *mem, Field *field)
{
- char buff[MAX_FIELD_WIDTH], *to;
- String str(buff,sizeof(buff),&my_charset_bin);
- uint length;
+ LEX_STRING value;
- field->val_str(&str);
- length= str.length();
- if (!length || !(to= (char*) alloc_root(mem,length+1)))
+ if (get_field(mem, field, &value))
return NullS;
- memcpy(to,str.ptr(),(uint) length);
- to[length]=0;
- return to;
+
+ if (!value.length)
+ return NullS;
+
+ return value.str;
}
@@ -2427,21 +2460,23 @@ bool st_table_list::prepare_view_securet
DBUG_PRINT("info", ("This table is suid view => load contest"));
DBUG_ASSERT(view && view_sctx);
if (acl_getroot_no_password(view_sctx,
- definer.user.str,
- definer.host.str,
- definer.host.str,
+ definer.user_name.get_c_str(),
+ definer.host_name.get_c_str(),
+ definer.host_name.get_c_str(),
thd->db))
{
if (thd->lex->sql_command == SQLCOM_SHOW_CREATE)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_NO_SUCH_USER,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
- definer.user.str, definer.host.str);
+ definer.user_name.get_c_str(),
+ definer.host_name.get_c_str());
}
else
{
- my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str);
+ my_error(ER_NO_SUCH_USER, MYF(0), definer.user_name.get_c_str(),
+ definer.host_name.get_c_str());
DBUG_RETURN(TRUE);
}
}
@@ -3024,3 +3059,86 @@ void st_table_list::reinit_before_use(TH
template class List<String>;
template class List_iterator<String>;
#endif
+
+
+/**************************************************************************
+ User_name implementation.
+**************************************************************************/
+
+void User_name::set(THD *thd, LEX_STRING *user_name)
+{
+ if (!user_name)
+ {
+ reset();
+ return;
+ }
+
+ if (user_name->length > USERNAME_LENGTH)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_USER_NAME_TRUNCATED,
+ ER(ER_USER_NAME_TRUNCATED),
+ (const char *) user_name->str,
+ USERNAME_LENGTH);
+
+ user_name->str[USERNAME_LENGTH]= '\0';
+ user_name->length= USERNAME_LENGTH;
+
+ truncated= TRUE;
+ }
+ else
+ truncated= FALSE;
+
+ value= *user_name;
+}
+
+
+/**************************************************************************
+ Host_name implementation.
+**************************************************************************/
+
+void Host_name::set(THD *thd, LEX_STRING *host_name)
+{
+ if (!host_name)
+ {
+ reset();
+ return;
+ }
+
+ if (host_name->length > HOSTNAME_LENGTH)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_HOST_NAME_TRUNCATED,
+ ER(ER_HOST_NAME_TRUNCATED),
+ (const char *) host_name->str,
+ HOSTNAME_LENGTH);
+
+ host_name->str[HOSTNAME_LENGTH]= '\0';
+ host_name->length= HOSTNAME_LENGTH;
+
+ truncated= TRUE;
+ }
+ else
+ truncated= FALSE;
+
+ value= *host_name;
+}
+
+
+/**************************************************************************
+ Lex_user implementation.
+**************************************************************************/
+
+void Lex_user::set(THD *thd,
+ LEX_STRING *user_name_arg,
+ LEX_STRING *host_name_arg,
+ LEX_STRING *password_arg)
+{
+ user_name.set(thd, user_name_arg);
+ host_name.set(thd, host_name_arg);
+
+ if (password_arg)
+ password= *password_arg;
+ else
+ reset_password();
+}
--- 1.131/sql/table.h 2006-07-29 18:12:00 +04:00
+++ 1.132/sql/table.h 2006-07-29 18:12:00 +04:00
@@ -24,6 +24,186 @@ class st_select_lex;
class COND_EQUAL;
class Security_context;
+
+/**************************************************************************
+ User_name declaration.
+**************************************************************************/
+
+class User_name
+{
+public:
+ inline User_name();
+
+public:
+ void set(THD *thd, LEX_STRING *user_name);
+
+ inline LEX_STRING *get_str();
+ inline char *get_c_str();
+ inline const char *get_c_str() const;
+ inline uint get_length() const;
+ inline bool is_truncated() const;
+
+ inline void reset();
+
+private:
+ LEX_STRING value;
+ bool truncated;
+};
+
+
+/**************************************************************************
+ User_name inline implementation.
+**************************************************************************/
+
+inline User_name::User_name()
+{
+ reset();
+}
+
+inline LEX_STRING *User_name::get_str()
+{
+ return &value;
+}
+
+inline char *User_name::get_c_str()
+{
+ return value.str;
+}
+
+inline const char *User_name::get_c_str() const
+{
+ return value.str;
+}
+
+inline uint User_name::get_length() const
+{
+ return value.length;
+}
+
+inline bool User_name::is_truncated() const
+{
+ return truncated;
+}
+
+inline void User_name::reset()
+{
+ value.str= NULL;
+ value.length= 0;
+
+ truncated= FALSE;
+}
+
+
+/**************************************************************************
+ Host_name declaration.
+**************************************************************************/
+
+class Host_name
+{
+public:
+ inline Host_name();
+
+public:
+ void set(THD *thd, LEX_STRING *host_name);
+
+ inline LEX_STRING *get_str();
+ inline char *get_c_str();
+ inline const char *get_c_str() const;
+ inline uint get_length() const;
+ inline bool is_truncated() const;
+
+ inline void reset();
+
+private:
+ LEX_STRING value;
+ bool truncated;
+};
+
+
+/**************************************************************************
+ Host_name inline implementation.
+**************************************************************************/
+
+inline Host_name::Host_name()
+{
+ reset();
+}
+
+inline LEX_STRING *Host_name::get_str()
+{
+ return &value;
+}
+
+inline char *Host_name::get_c_str()
+{
+ return value.str;
+}
+
+inline const char *Host_name::get_c_str() const
+{
+ return value.str;
+}
+
+inline uint Host_name::get_length() const
+{
+ return value.length;
+}
+
+inline bool Host_name::is_truncated() const
+{
+ return truncated;
+}
+
+inline void Host_name::reset()
+{
+ value.str= NULL;
+ value.length= 0;
+
+ truncated= FALSE;
+}
+
+
+/**************************************************************************
+ Lex_user declaration.
+**************************************************************************/
+
+class Lex_user
+{
+public:
+ inline Lex_user();
+
+public:
+ void set(THD *thd,
+ LEX_STRING *user_name_arg,
+ LEX_STRING *host_name_arg,
+ LEX_STRING *password_arg);
+
+ inline void reset_password();
+
+public:
+ User_name user_name;
+ Host_name host_name;
+
+ LEX_STRING password;
+};
+
+
+/**************************************************************************
+ Lex_user inline implementation.
+**************************************************************************/
+
+inline Lex_user::Lex_user()
+{
+ reset_password();
+}
+
+inline void Lex_user::reset_password()
+{
+ password.str= NULL;
+ password.length= 0;
+}
+
+
/* Order clause list element */
typedef struct st_order {
@@ -578,7 +758,7 @@ typedef struct st_table_list
LEX_STRING view_db; /* saved view database */
LEX_STRING view_name; /* saved view name */
LEX_STRING timestamp; /* GMT time stamp of last operation */
- st_lex_user definer; /* definer of view */
+ Lex_user definer; /* definer of view */
ulonglong file_version; /* version of file's field set */
ulonglong updatable_view; /* VIEW can be updated */
ulonglong revision; /* revision control number */
--- 1.65/sql/share/errmsg.txt 2006-07-29 18:12:00 +04:00
+++ 1.66/sql/share/errmsg.txt 2006-07-29 18:12:00 +04:00
@@ -5621,3 +5621,7 @@ ER_TABLE_CANT_HANDLE_SPKEYS
eng "The used table type doesn't support SPATIAL indexes"
ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
eng "Triggers can not be created on system tables"
+ER_USER_NAME_TRUNCATED
+ eng "User name '%s' has been truncated to %d symbols"
+ER_HOST_NAME_TRUNCATED
+ eng "Host name '%s' has been truncated to %d symbols"
--- New file ---
+++ BitKeeper/etc/collapsed 06/07/29 12:38:33
44c793b7N8P7mznmNrhnNJOzRGevvA
44ca353dafuBX_DtdKwAKcBQoxumbA
--- 1.1/include/my_user.h 2006-07-29 18:12:00 +04:00
+++ 1.2/include/my_user.h 2006-07-29 18:12:00 +04:00
@@ -23,12 +23,22 @@
#define _my_user_h_
#include <my_global.h>
+#include <m_string.h>
C_MODE_START
-void parse_user(const char *user_id_str, uint user_id_len,
- char *user_name_str, uint *user_name_len,
- char *host_name_str, uint *host_name_len);
+typedef struct
+{
+ const char *original_name;
+} PARSE_USER_CB_CTX;
+
+typedef void (*parse_user_cb)(const PARSE_USER_CB_CTX *);
+
+void parse_user(const LEX_STRING *user_id,
+ LEX_STRING *user_name,
+ LEX_STRING *host_name,
+ parse_user_cb on_user_name_truncated,
+ parse_user_cb on_host_name_truncated);
C_MODE_END
--- 1.1/sql-common/my_user.c 2006-07-29 18:12:00 +04:00
+++ 1.2/sql-common/my_user.c 2006-07-29 18:12:00 +04:00
@@ -14,6 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <my_global.h>
+#include <my_sys.h>
#include <my_user.h>
#include <m_string.h>
@@ -22,36 +24,68 @@
Parse user value to user name and host name parts.
SYNOPSIS
- user_id_str [IN] User value string (the source).
- user_id_len [IN] Length of the user value.
- user_name_str [OUT] Buffer to store user name part.
- Must be not less than USERNAME_LENGTH + 1.
- user_name_len [OUT] A place to store length of the user name part.
- host_name_str [OUT] Buffer to store host name part.
- Must be not less than HOSTNAME_LENGTH + 1.
- host_name_len [OUT] A place to store length of the host name part.
+ user_id [IN] User value string (the source).
+ user_name [IN/OUT] Buffer to store user name part.
+ IN: Maximal possible length of the user name part.
+ OUT: A place to store length of the user name part.
+ host_name [IN/OUT] Buffer to store host name part.
+ IN: Maximal possible length of the host name part.
+ OUT: A place to store length of the host name part.
+ on_user_name_truncated [IN] Function to report about user name truncation.
+ on_host_name_truncated [IN] Function to report about host name truncation.
*/
-void parse_user(const char *user_id_str, uint user_id_len,
- char *user_name_str, uint *user_name_len,
- char *host_name_str, uint *host_name_len)
+void parse_user(const LEX_STRING *user_id,
+ LEX_STRING *user_name,
+ LEX_STRING *host_name,
+ parse_user_cb on_user_name_truncated,
+ parse_user_cb on_host_name_truncated)
{
- char *p= strrchr(user_id_str, '@');
+ char *p= strrchr(user_id->str, '@');
if (!p)
{
- *user_name_len= 0;
- *host_name_len= 0;
+ user_name->length= 0;
+ host_name->length= 0;
}
else
{
- *user_name_len= p - user_id_str;
- *host_name_len= user_id_len - *user_name_len - 1;
+ uint max_user_name_len= user_name->length;
+ uint max_host_name_len= host_name->length;
- memcpy(user_name_str, user_id_str, *user_name_len);
- memcpy(host_name_str, p + 1, *host_name_len);
+ user_name->length= p - user_id->str;
+ host_name->length= user_id->length - user_name->length - 1;
+
+ if (user_name->length > max_user_name_len)
+ {
+ PARSE_USER_CB_CTX ctx;
+ ctx.original_name= my_malloc(user_name->length + 1, MYF(0));
+ strmake(ctx.original_name, user_id->str, user_name->length);
+
+ on_user_name_truncated(&ctx);
+
+ my_free(ctx.original_name, MYF(0));
+
+ user_name->length= max_user_name_len;
+ }
+
+ if (host_name->length > max_host_name_len)
+ {
+ PARSE_USER_CB_CTX ctx;
+ ctx.original_name= my_malloc(host_name->length + 1, MYF(0));
+ strmake(ctx.original_name, p + 1, host_name->length);
+
+ on_host_name_truncated(&ctx);
+
+ my_free(ctx.original_name, MYF(0));
+
+ host_name->length= max_host_name_len;
+ }
+
+ memcpy(user_name->str, user_id->str, user_name->length);
+ memcpy(host_name->str, p + 1, host_name->length);
}
- user_name_str[*user_name_len]= 0;
- host_name_str[*host_name_len]= 0;
+ user_name->str[user_name->length]= '\0';
+ host_name->str[host_name->length]= '\0';
}
--- 1.27/sql/spatial.cc 2006-07-29 18:12:00 +04:00
+++ 1.28/sql/spatial.cc 2006-07-29 18:12:00 +04:00
@@ -34,8 +34,11 @@ static Geometry::Class_info **ci_collect
Geometry::Class_info::Class_info(const char *name, int type_id,
void(*create_func)(void *)):
- m_name(name, strlen(name)), m_type_id(type_id), m_create_func(create_func)
+ m_type_id(type_id), m_create_func(create_func)
{
+ m_name.str= (char *) name;
+ m_name.length= strlen(name);
+
ci_collection[type_id]= this;
}
--- 1.20/sql/spatial.h 2006-07-29 18:12:00 +04:00
+++ 1.21/sql/spatial.h 2006-07-29 18:12:00 +04:00
@@ -200,7 +200,7 @@ public:
class Class_info
{
public:
- LEX_STRING_WITH_INIT m_name;
+ LEX_STRING m_name;
int m_type_id;
void (*m_create_func)(void *);
Class_info(const char *name, int type_id, void(*create_func)(void *));
--- 1.162/mysql-test/r/view.result 2006-07-29 18:12:00 +04:00
+++ 1.163/mysql-test/r/view.result 2006-07-29 18:12:00 +04:00
@@ -2736,3 +2736,30 @@ m e
1 b
DROP VIEW v1;
DROP TABLE IF EXISTS t1,t2;
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+CREATE TABLE t1(a INT, b INT);
+CREATE DEFINER=1234567890abcdefGHIKL@localhost
+VIEW v1 AS SELECT a FROM t1;
+Warnings:
+Note 1466 User name '1234567890abcdefGHIKL' has been truncated to 16 symbols
+Note 1449 There is no '1234567890abcdef'@'localhost' registered
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+VIEW v2 AS SELECT b FROM t1;
+Warnings:
+Note 1467 Host name '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY'
has been truncated to 60 symbols
+Note 1449 There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`1234567890abcdef`@`localhost` SQL SECURITY DEFINER
VIEW `v1` AS select `t1`.`a` AS `a` from `t1`
+Warnings:
+Note 1449 There is no '1234567890abcdef'@'localhost' registered
+SHOW CREATE VIEW v2;
+View Create View
+v2 CREATE ALGORITHM=UNDEFINED
DEFINER=`some_user_name`@`1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij`
SQL SECURITY DEFINER VIEW `v2` AS select `t1`.`b` AS `b` from `t1`
+Warnings:
+Note 1449 There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+DROP TABLE t1;
+DROP VIEW v1;
+DROP VIEW v2;
--- 1.147/mysql-test/t/view.test 2006-07-29 18:12:00 +04:00
+++ 1.148/mysql-test/t/view.test 2006-07-29 18:12:00 +04:00
@@ -2596,3 +2596,35 @@ SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE IF EXISTS t1,t2;
+
+
+#
+# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause.
+#
+
+# Prepare.
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+--enable_warnings
+
+CREATE TABLE t1(a INT, b INT);
+
+CREATE DEFINER=1234567890abcdefGHIKL@localhost
+ VIEW v1 AS SELECT a FROM t1;
+
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+ VIEW v2 AS SELECT b FROM t1;
+
+# Test.
+
+SHOW CREATE VIEW v1;
+SHOW CREATE VIEW v2;
+
+# Cleanup.
+
+DROP TABLE t1;
+DROP VIEW v1;
+DROP VIEW v2;
--- 1.90/sql/sql_view.cc 2006-07-29 18:12:00 +04:00
+++ 1.91/sql/sql_view.cc 2006-07-29 18:12:00 +04:00
@@ -235,10 +235,10 @@ bool mysql_create_view(THD *thd,
- same as current user
- current user has SUPER_ACL
*/
- if (strcmp(lex->definer->user.str,
+ if (strcmp(lex->definer->user_name.get_c_str(),
thd->security_ctx->priv_user) != 0 ||
my_strcasecmp(system_charset_info,
- lex->definer->host.str,
+ lex->definer->host_name.get_c_str(),
thd->security_ctx->priv_host) != 0)
{
if (!(thd->security_ctx->master_access & SUPER_ACL))
@@ -249,14 +249,14 @@ bool mysql_create_view(THD *thd,
}
else
{
- if (!is_acl_user(lex->definer->host.str,
- lex->definer->user.str))
+ if (!is_acl_user(lex->definer->host_name.get_c_str(),
+ lex->definer->user_name.get_c_str()))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
- lex->definer->user.str,
- lex->definer->host.str);
+ lex->definer->user_name.get_c_str(),
+ lex->definer->host_name.get_c_str());
}
}
}
@@ -536,10 +536,10 @@ static File_option view_parameters[]=
offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("definer_user")},
- offsetof(TABLE_LIST, definer.user),
+ offsetof(TABLE_LIST, definer.user_name),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("definer_host")},
- offsetof(TABLE_LIST, definer.host),
+ offsetof(TABLE_LIST, definer.host_name),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("suid")},
offsetof(TABLE_LIST, view_suid),
@@ -688,8 +688,8 @@ static int mysql_register_view(THD *thd,
lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
}
view->algorithm= lex->create_view_algorithm;
- view->definer.user= lex->definer->user;
- view->definer.host= lex->definer->host;
+ view->definer.user_name= lex->definer->user_name;
+ view->definer.host_name= lex->definer->host_name;
view->view_suid= lex->create_view_suid;
view->with_check= lex->create_view_check;
if ((view->updatable_view= (can_be_merged &&
@@ -834,8 +834,8 @@ bool mysql_make_view(THD *thd, File_pars
table->timestamp.str= table->timestamp_buffer;
/* prepare default values for old format */
table->view_suid= TRUE;
- table->definer.user.str= table->definer.host.str= 0;
- table->definer.user.length= table->definer.host.length= 0;
+ table->definer.user_name.set(thd, NULL);
+ table->definer.host_name.set(thd, NULL);
/*
TODO: when VIEWs will be stored in cache, table mem_root should
@@ -848,11 +848,11 @@ bool mysql_make_view(THD *thd, File_pars
/*
check old format view .frm
*/
- if (!table->definer.user.str)
+ if (!table->definer.user_name.get_c_str())
{
- DBUG_ASSERT(!table->definer.host.str &&
- !table->definer.user.length &&
- !table->definer.host.length);
+ DBUG_ASSERT(!table->definer.host_name.get_c_str() &&
+ !table->definer.user_name.get_length() &&
+ !table->definer.host_name.get_length());
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER),
table->db, table->table_name);
--- 1.43/mysql-test/r/trigger.result 2006-07-29 18:12:00 +04:00
+++ 1.44/mysql-test/r/trigger.result 2006-07-29 18:12:00 +04:00
@@ -1089,4 +1089,25 @@ begin
set @a:= 1;
end|
ERROR HY000: Triggers can not be created on system tables
+use test|
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1(c INT);
+CREATE TABLE t2(c INT);
+CREATE DEFINER=1234567890abcdefGHIKL@localhost
+TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1;
+Warnings:
+Note 1466 User name '1234567890abcdefGHIKL' has been truncated to 16 symbols
+Note 1449 There is no '1234567890abcdef'@'localhost' registered
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2;
+Warnings:
+Note 1467 Host name '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY'
has been truncated to 60 symbols
+Note 1449 There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+INSERT INTO t1 VALUES(1);
+ERROR HY000: There is no '1234567890abcdef'@'localhost' registered
+INSERT INTO t2 VALUES(2);
+ERROR HY000: There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+DROP TABLE t1;
+DROP TABLE t2;
End of 5.0 tests
--- 1.49/mysql-test/t/trigger.test 2006-07-29 18:12:00 +04:00
+++ 1.50/mysql-test/t/trigger.test 2006-07-29 18:12:00 +04:00
@@ -1301,6 +1301,42 @@ create trigger wont_work after update on
begin
set @a:= 1;
end|
+use test|
delimiter ;|
+
+
+#
+# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause.
+#
+
+# Prepare.
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+CREATE TABLE t1(c INT);
+CREATE TABLE t2(c INT);
+
+CREATE DEFINER=1234567890abcdefGHIKL@localhost
+ TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a = 1;
+
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+ TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2;
+
+# Test.
+
+--error ER_NO_SUCH_USER
+INSERT INTO t1 VALUES(1);
+
+--error ER_NO_SUCH_USER
+INSERT INTO t2 VALUES(2);
+
+# Cleanup.
+
+DROP TABLE t1;
+DROP TABLE t2;
+
--echo End of 5.0 tests
--- 1.54/sql/sql_trigger.cc 2006-07-29 18:12:00 +04:00
+++ 1.55/sql/sql_trigger.cc 2006-07-29 18:12:00 +04:00
@@ -158,11 +158,13 @@ bool mysql_create_or_drop_trigger(THD *t
{
TABLE *table;
bool result= TRUE;
- LEX_STRING definer_user;
- LEX_STRING definer_host;
+ String stmt_query;
DBUG_ENTER("mysql_create_or_drop_trigger");
+ /* Charset of the buffer for statement must be system one. */
+ stmt_query.set_charset(system_charset_info);
+
/*
QQ: This function could be merged in mysql_alter_table() function
But do we want this ?
@@ -264,8 +266,8 @@ bool mysql_create_or_drop_trigger(THD *t
}
result= (create ?
- table->triggers->create_trigger(thd, tables, &definer_user,
&definer_host):
- table->triggers->drop_trigger(thd, tables));
+ table->triggers->create_trigger(thd, tables, &stmt_query):
+ table->triggers->drop_trigger(thd, tables, &stmt_query));
end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -277,32 +279,9 @@ end:
{
thd->clear_error();
- String log_query(thd->query, thd->query_length, system_charset_info);
-
- if (create)
- {
- log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */
-
- log_query.append(STRING_WITH_LEN("CREATE "));
-
- if (definer_user.str && definer_host.str)
- {
- /*
- Append definer-clause if the trigger is SUID (a usual trigger in
- new MySQL versions).
- */
-
- append_definer(thd, &log_query, &definer_user, &definer_host);
- }
-
- log_query.append(thd->lex->stmt_definition_begin,
- (char *)thd->lex->sphead->m_body_begin -
- thd->lex->stmt_definition_begin +
- thd->lex->sphead->m_body.length);
- }
-
/* Such a statement can always go directly to binlog, no trans cache. */
- Query_log_event qinfo(thd, log_query.ptr(), log_query.length(), 0, FALSE);
+ Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0,
+ FALSE);
mysql_bin_log.write(&qinfo);
}
@@ -322,22 +301,8 @@ end:
LEX)
tables - table list containing one open table for which the
trigger is created.
- definer_user - [out] after a call it points to 0-terminated string or
- contains the NULL-string:
- - 0-terminated is returned if the trigger is SUID. The
- string contains user name part of the actual trigger
- definer.
- - NULL-string is returned if the trigger is non-SUID.
- Anyway, the caller is responsible to provide memory for
- storing LEX_STRING object.
- definer_host - [out] after a call it points to 0-terminated string or
- contains the NULL-string:
- - 0-terminated string is returned if the trigger is
- SUID. The string contains host name part of the
- actual trigger definer.
- - NULL-string is returned if the trigger is non-SUID.
- Anyway, the caller is responsible to provide memory for
- storing LEX_STRING object.
+ stmt_query - [OUT] after successful return, this string
contains
+ well-formed
statement for creation this trigger.
NOTE
- Assumes that trigger name is fully qualified.
@@ -352,8 +317,7 @@ end:
True - error
*/
bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
- LEX_STRING *definer_user,
- LEX_STRING *definer_host)
+ String *stmt_query)
{
LEX *lex= thd->lex;
TABLE *table= tables->table;
@@ -361,6 +325,8 @@ bool Table_triggers_list::create_trigger
trigname_path[FN_REFLEN];
LEX_STRING dir, file, trigname_file;
LEX_STRING *trg_def, *name;
+ LEX_STRING definer_user;
+ LEX_STRING definer_host;
ulonglong *trg_sql_mode;
char trg_definer_holder[USER_HOST_BUFF_SIZE];
LEX_STRING *trg_definer;
@@ -416,9 +382,10 @@ bool Table_triggers_list::create_trigger
*/
if (lex->definer &&
- (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
+ (strcmp(lex->definer->user_name.get_c_str(),
+ thd->security_ctx->priv_user) ||
my_strcasecmp(system_charset_info,
- lex->definer->host.str,
+ lex->definer->host_name.get_c_str(),
thd->security_ctx->priv_host)))
{
if (check_global_access(thd, SUPER_ACL))
@@ -508,20 +475,18 @@ bool Table_triggers_list::create_trigger
definers_list.push_back(trg_definer, &table->mem_root))
goto err_with_cleanup;
- trg_def->str= thd->query;
- trg_def->length= thd->query_length;
*trg_sql_mode= thd->variables.sql_mode;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (lex->definer && !is_acl_user(lex->definer->host.str,
- lex->definer->user.str))
+ if (lex->definer && !is_acl_user(lex->definer->host_name.get_c_str(),
+ lex->definer->user_name.get_c_str()))
{
push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_NO_SUCH_USER,
ER(ER_NO_SUCH_USER),
- lex->definer->user.str,
- lex->definer->host.str);
+ lex->definer->user_name.get_c_str(),
+ lex->definer->host_name.get_c_str());
}
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
@@ -529,27 +494,55 @@ bool Table_triggers_list::create_trigger
{
/* SUID trigger. */
- *definer_user= lex->definer->user;
- *definer_host= lex->definer->host;
+ definer_user= *lex->definer->user_name.get_str();
+ definer_host= *lex->definer->host_name.get_str();
trg_definer->str= trg_definer_holder;
- trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
- definer_host->str, NullS) - trg_definer->str;
+ trg_definer->length= strxmov(trg_definer->str, definer_user.str, "@",
+ definer_host.str, NullS) - trg_definer->str;
}
else
{
/* non-SUID trigger. */
- definer_user->str= 0;
- definer_user->length= 0;
+ definer_user.str= NULL;
+ definer_user.length= 0;
- definer_host->str= 0;
- definer_host->length= 0;
+ definer_host.str= NULL;
+ definer_host.length= 0;
trg_definer->str= (char*) "";
trg_definer->length= 0;
}
+ /*
+ Create well-formed trigger definition query. Original query is not
+ appropriated, because definer-clause can be not truncated.
+ */
+
+ stmt_query->append(STRING_WITH_LEN("CREATE "));
+
+ if (trg_definer)
+ {
+ /*
+ Append definer-clause if the trigger is SUID (a usual trigger in
+ new MySQL versions).
+ */
+
+ append_definer(thd, stmt_query, &definer_user, &definer_host);
+ }
+
+ stmt_query->append(thd->lex->stmt_definition_begin,
+ (char *) thd->lex->sphead->m_body_begin -
+ thd->lex->stmt_definition_begin +
+ thd->lex->sphead->m_body.length);
+
+ trg_def->str= stmt_query->c_ptr();
+ trg_def->length= stmt_query->length();
+
+ /* Create trigger definition file. */
+
+
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
(gptr)this, triggers_file_parameters, 0))
return 0;
@@ -647,15 +640,19 @@ static bool save_trigger_file(Table_trig
SYNOPSIS
drop_trigger()
- thd - current thread context (including trigger definition in LEX)
- tables - table list containing one open table for which trigger is
- dropped.
+ thd - current thread context
+ (including trigger definition in LEX)
+ tables - table list containing one open table for which trigger
+ is dropped.
+ stmt_query - [OUT] after successful return, this string
contains
+ well-formed
statement for creation this trigger.
RETURN VALUE
False - success
True - error
*/
-bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
+bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
+ String *stmt_query)
{
LEX *lex= thd->lex;
LEX_STRING *name;
@@ -665,6 +662,8 @@ bool Table_triggers_list::drop_trigger(T
List_iterator<LEX_STRING> it_definer(definers_list);
char path[FN_REFLEN];
+ stmt_query->append(thd->query, thd->query_length);
+
while ((name= it_name++))
{
it_def++;
@@ -974,6 +973,8 @@ bool Table_triggers_list::check_n_load(T
if (!trg_definer->length)
{
+ LEX_STRING empty_definer= { "", 0 };
+
/*
This trigger was created/imported from the previous version of
MySQL, which does not support triggers definers. We should emit
@@ -990,7 +991,7 @@ bool Table_triggers_list::check_n_load(T
schema.
*/
- lex.sphead->set_definer("", 0);
+ lex.sphead->set_definer(thd, &empty_definer);
/*
Triggers without definer information are executed under the
@@ -1000,7 +1001,7 @@ bool Table_triggers_list::check_n_load(T
lex.sphead->m_chistics->suid= SP_IS_NOT_SUID;
}
else
- lex.sphead->set_definer(trg_definer->str, trg_definer->length);
+ lex.sphead->set_definer(thd, trg_definer);
if (triggers->names_list.push_back(&lex.sphead->m_name,
&table->mem_root))
@@ -1437,8 +1438,8 @@ bool Table_triggers_list::change_table_n
}
if (table.triggers)
{
- LEX_STRING_WITH_INIT old_table_name(old_table, strlen(old_table));
- LEX_STRING_WITH_INIT new_table_name(new_table, strlen(new_table));
+ LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) };
+ LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
/*
Since triggers should be in the same schema as their subject tables
moving table with them between two schemas raises too many questions.
--- 1.20/sql/sql_trigger.h 2006-07-29 18:12:00 +04:00
+++ 1.21/sql/sql_trigger.h 2006-07-29 18:12:00 +04:00
@@ -92,10 +92,8 @@ public:
}
~Table_triggers_list();
- bool create_trigger(THD *thd, TABLE_LIST *table,
- LEX_STRING *definer_user,
- LEX_STRING *definer_host);
- bool drop_trigger(THD *thd, TABLE_LIST *table);
+ bool create_trigger(THD *thd, TABLE_LIST *table, String *stmt_query);
+ bool drop_trigger(THD *thd, TABLE_LIST *table, String *stmt_query);
bool process_triggers(THD *thd, trg_event_type event,
trg_action_time_type time_type,
bool old_row_is_record1);
--- 1.158/sql/set_var.cc 2006-07-29 18:12:00 +04:00
+++ 1.159/sql/set_var.cc 2006-07-29 18:12:00 +04:00
@@ -3292,25 +3292,42 @@ int set_var_user::update(THD *thd)
Functions to handle SET PASSWORD
*****************************************************************************/
+set_var_password::set_var_password(THD *thd,
+ LEX_STRING *user_name_arg,
+ LEX_STRING *host_name_arg,
+ char *password_arg)
+{
+ LEX_STRING password_str= { password_arg, strlen(password_arg) };
+
+ user.set(thd, user_name_arg, host_name_arg, &password_str);
+}
+
int set_var_password::check(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (!user->host.str)
+ if (!user.host_name.get_c_str())
{
+ LEX_STRING host_name_str;
+
if (*thd->security_ctx->priv_host != 0)
{
- user->host.str= (char *) thd->security_ctx->priv_host;
- user->host.length= strlen(thd->security_ctx->priv_host);
+ host_name_str.str= thd->security_ctx->priv_host;
+ host_name_str.length= strlen(host_name_str.str);
}
else
{
- user->host.str= (char *)"%";
- user->host.length= 1;
+ host_name_str.str= (char *) "%";
+ host_name_str.length= 1;
}
+
+ user.host_name.set(thd, &host_name_str);
}
/* Returns 1 as the function sends error to client */
- return check_change_password(thd, user->host.str, user->user.str,
- password, strlen(password)) ? 1 : 0;
+ return check_change_password(thd,
+ user.host_name.get_c_str(),
+ user.user_name.get_c_str(),
+ user.password.str,
+ user.password.length) ? 1 : 0;
#else
return 0;
#endif
@@ -3320,8 +3337,10 @@ int set_var_password::update(THD *thd)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Returns 1 as the function sends error to client */
- return change_password(thd, user->host.str, user->user.str, password) ?
- 1 : 0;
+ return change_password(thd,
+ user.host_name.get_c_str(),
+ user.user_name.get_c_str(),
+ user.password.str) ? 1 : 0;
#else
return 0;
#endif
--- 1.78/sql/set_var.h 2006-07-29 18:12:00 +04:00
+++ 1.79/sql/set_var.h 2006-07-29 18:12:00 +04:00
@@ -913,12 +913,15 @@ public:
class set_var_password: public set_var_base
{
- LEX_USER *user;
- char *password;
+ Lex_user user;
+
+public:
+ set_var_password(THD *thd,
+ LEX_STRING *user_name_arg,
+ LEX_STRING *host_name_arg,
+ char *password_arg);
+
public:
- set_var_password(LEX_USER *user_arg,char *password_arg)
- :user(user_arg), password(password_arg)
- {}
int check(THD *thd);
int update(THD *thd);
};
--- 1.204/mysql-test/r/sp.result 2006-07-29 18:12:00 +04:00
+++ 1.205/mysql-test/r/sp.result 2006-07-29 18:12:00 +04:00
@@ -5222,4 +5222,27 @@ CHARSET(p3) COLLATION(p3)
greek greek_general_ci
use test|
DROP DATABASE mysqltest1|
+DROP PROCEDURE IF EXISTS bug16899_p1|
+DROP FUNCTION IF EXISTS bug16899_f1|
+CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1()
+BEGIN
+SET @a = 1;
+END|
+Warnings:
+Note 1466 User name '1234567890abcdefGHIKL' has been truncated to 16 symbols
+Note 1449 There is no '1234567890abcdef'@'localhost' registered
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+FUNCTION bug16899_f1() RETURNS INT
+BEGIN
+RETURN 1;
+END|
+Warnings:
+Note 1467 Host name '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY'
has been truncated to 60 symbols
+Note 1449 There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+CALL bug16899_p1()|
+ERROR HY000: There is no '1234567890abcdef'@'localhost' registered
+SELECT bug16899_f1()|
+ERROR HY000: There is no
'some_user_name'@'1234567890abcdefghij1234567890abcdefghij1234567890abcdefghij'
registered
+DROP PROCEDURE bug16899_p1|
+DROP FUNCTION bug16899_f1|
drop table t1,t2;
--- 1.192/mysql-test/t/sp.test 2006-07-29 18:12:00 +04:00
+++ 1.193/mysql-test/t/sp.test 2006-07-29 18:12:00 +04:00
@@ -6148,6 +6148,42 @@ use test|
DROP DATABASE mysqltest1|
#
+# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause.
+#
+
+# Prepare.
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS bug16899_p1|
+DROP FUNCTION IF EXISTS bug16899_f1|
+--enable_warnings
+
+CREATE DEFINER=1234567890abcdefGHIKL@localhost PROCEDURE bug16899_p1()
+BEGIN
+ SET @a = 1;
+END|
+
+CREATE
DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY
+ FUNCTION bug16899_f1() RETURNS INT
+BEGIN
+ RETURN 1;
+END|
+
+# Test.
+
+--error ER_NO_SUCH_USER
+CALL bug16899_p1()|
+
+--error ER_NO_SUCH_USER
+SELECT bug16899_f1()|
+
+# Cleanup.
+
+DROP PROCEDURE bug16899_p1|
+DROP FUNCTION bug16899_f1|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
--- 1.115/sql/sp.cc 2006-07-29 18:12:00 +04:00
+++ 1.116/sql/sp.cc 2006-07-29 18:12:00 +04:00
@@ -37,7 +37,7 @@ static int
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
ulong sql_mode, const char *params, const char *returns,
const char *body, st_sp_chistics &chistics,
- const char *definer, longlong created, longlong modified);
+ const LEX_STRING *definer, longlong created, longlong modified);
/*
*
@@ -272,7 +272,7 @@ db_find_routine(THD *thd, int type, sp_n
TABLE *table;
const char *params, *returns, *body;
int ret;
- const char *definer;
+ LEX_STRING definer;
longlong created;
longlong modified;
st_sp_chistics chistics;
@@ -362,8 +362,8 @@ db_find_routine(THD *thd, int type, sp_n
}
// Get additional information
- if ((definer= get_field(thd->mem_root,
- table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
+ if (get_field(thd->mem_root, table->field[MYSQL_PROC_FIELD_DEFINER],
+ &definer) || definer.length == 0)
{
ret= SP_GET_FIELD_FAILED;
goto done;
@@ -387,7 +387,7 @@ db_find_routine(THD *thd, int type, sp_n
ret= db_load_routine(thd, type, name, sphp,
sql_mode, params, returns, body, chistics,
- definer, created, modified);
+ &definer, created, modified);
done:
if (table)
@@ -400,7 +400,7 @@ static int
db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
ulong sql_mode, const char *params, const char *returns,
const char *body, st_sp_chistics &chistics,
- const char *definer, longlong created, longlong modified)
+ const LEX_STRING *definer, longlong created, longlong modified)
{
LEX *old_lex= thd->lex, newlex;
String defstr;
@@ -410,15 +410,13 @@ db_load_routine(THD *thd, int type, sp_n
ulong old_sql_mode= thd->variables.sql_mode;
ha_rows old_select_limit= thd->variables.select_limit;
sp_rcontext *old_spcont= thd->spcont;
-
+
char definer_user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder,
- USERNAME_LENGTH);
+ LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH };
char definer_host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder,
- HOSTNAME_LENGTH);
-
+ LEX_STRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH };
+
int ret;
thd->variables.sql_mode= sql_mode;
@@ -427,9 +425,20 @@ db_load_routine(THD *thd, int type, sp_n
thd->lex= &newlex;
newlex.current_select= NULL;
- parse_user(definer, strlen(definer),
- definer_user_name.str, &definer_user_name.length,
- definer_host_name.str, &definer_host_name.length);
+ /*
+ Split the definer into user and host names.
+
+ If user name (host name) is longer than USERNAME_LENGTH (HOSTNAME_LENGTH),
+ it will be truncated and corresponding warning will be emitted. This
+ truncation can occur, when we are loading stored routine created in the
+ MySQL before 5.0.23 -- there was no checkings for length. As of 5.0.23
+ such checkings are before creating the stored routine, so we will never
+ truncate here.
+ */
+
+ parse_user(definer, &definer_user_name, &definer_host_name,
+ mysqld_on_user_name_truncated,
+ mysqld_on_host_name_truncated);
defstr.set_charset(system_charset_info);
@@ -531,8 +540,9 @@ db_create_routine(THD *thd, int type, sp
restore_record(table, s->default_values); // Get default values for fields
/* NOTE: all needed privilege checks have been already done. */
- strxmov(definer, thd->lex->definer->user.str, "@",
- thd->lex->definer->host.str, NullS);
+ strxmov(definer,
+ thd->lex->definer->user_name.get_c_str(), "@",
+ thd->lex->definer->host_name.get_c_str(), NullS);
if (table->s->fields != MYSQL_PROC_FIELD_COUNT)
{
@@ -631,8 +641,9 @@ db_create_routine(THD *thd, int type, sp
String log_query;
log_query.set_charset(system_charset_info);
log_query.append(STRING_WITH_LEN("CREATE "));
- append_definer(thd, &log_query, &thd->lex->definer->user,
- &thd->lex->definer->host);
+ append_definer(thd, &log_query,
+ thd->lex->definer->user_name.get_str(),
+ thd->lex->definer->host_name.get_str());
log_query.append(thd->lex->stmt_definition_begin,
(char *)sp->m_body_begin -
thd->lex->stmt_definition_begin +
@@ -983,7 +994,8 @@ sp_find_routine(THD *thd, int type, sp_n
ulong level;
sp_head *new_sp;
const char *returns= "";
- char definer[USER_HOST_BUFF_SIZE];
+ char definer_holder[USER_HOST_BUFF_SIZE];
+ LEX_STRING definer= { definer_holder, 0 };
/*
String buffer for RETURNS data type must have system charset;
@@ -1013,8 +1025,9 @@ sp_find_routine(THD *thd, int type, sp_n
DBUG_RETURN(0);
}
- strxmov(definer, sp->m_definer_user.str, "@",
- sp->m_definer_host.str, NullS);
+ definer.length= strxmov(definer.str, sp->m_definer_user.str, "@",
+ sp->m_definer_host.str, NullS) - definer.str;
+
if (type == TYPE_ENUM_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
@@ -1022,7 +1035,7 @@ sp_find_routine(THD *thd, int type, sp_n
}
if (db_load_routine(thd, type, name, &new_sp,
sp->m_sql_mode, sp->m_params.str, returns,
- sp->m_body.str, *sp->m_chistics, definer,
+ sp->m_body.str, *sp->m_chistics, &definer,
sp->m_created, sp->m_modified) == SP_OK)
{
sp->m_last_cached_sp->m_next_cached_sp= new_sp;
@@ -1823,6 +1836,7 @@ create_string(THD *thd, String *buf,
buf->append('\n');
}
buf->append(body, bodylen);
+
return TRUE;
}
--- 1.221/sql/sp_head.cc 2006-07-29 18:12:00 +04:00
+++ 1.222/sql/sp_head.cc 2006-07-29 18:12:00 +04:00
@@ -1949,16 +1949,28 @@ sp_head::set_info(longlong created, long
void
-sp_head::set_definer(const char *definer, uint definerlen)
+sp_head::set_definer(THD *thd, const LEX_STRING *definer)
{
char user_name_holder[USERNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH);
+ LEX_STRING user_name= { user_name_holder, USERNAME_LENGTH };
char host_name_holder[HOSTNAME_LENGTH + 1];
- LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH);
+ LEX_STRING host_name= { host_name_holder, HOSTNAME_LENGTH };
- parse_user(definer, definerlen, user_name.str, &user_name.length,
- host_name.str, &host_name.length);
+ /*
+ Split the definer into user and host names.
+
+ If user name (host name) is longer than USERNAME_LENGTH (HOSTNAME_LENGTH),
+ it will be truncated and corresponding warning will be emitted. This
+ truncation can occur, when we are loading stored routine or trigger
+ created in the MySQL before 5.0.23 -- there was no checkings for length.
+ As of 5.0.23 such checkings are before creating the stored routine, so we
+ will never truncate here.
+ */
+
+ parse_user(definer, &user_name, &host_name,
+ mysqld_on_user_name_truncated,
+ mysqld_on_host_name_truncated);
set_definer(&user_name, &host_name);
}
--- 1.87/sql/sp_head.h 2006-07-29 18:12:00 +04:00
+++ 1.88/sql/sp_head.h 2006-07-29 18:12:00 +04:00
@@ -293,7 +293,7 @@ public:
void set_info(longlong created, longlong modified,
st_sp_chistics *chistics, ulong sql_mode);
- void set_definer(const char *definer, uint definerlen);
+ void set_definer(THD *thd, const LEX_STRING *definer);
void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
void reset_thd_mem_root(THD *thd);
| Thread |
|---|
| • bk commit into 5.0 tree (anozdrin:1.2244) BUG#16899 | Alexander Nozdrin | 29 Jul |