mirror of
https://github.com/MariaDB/server.git
synced 2026-05-03 13:45:34 +02:00
MDEV-20366 Server crashes in get_current_user upon SET PASSWORD via SP
The opt_for_user subrule was incorrectly scanned before sp_create_assignment_lex(),
so the user name and the host were created on a wrong memory root.
- Reoganizing the grammar to make sure that sp_create_assignment_lex()
is called immediately after PASSWORD_SYM is scanned, so all attributes
are then allocated on its memory root.
- Moving the semantic code as methods to LEX, so the grammar looks as simple as possible.
- Changing text_or_password to be of the data type USER_AUTH*.
As a side effect, the LEX::definer member is now not used when processing
the SET PASSWORD statement. Everything is done using Bison's stack.
The bug sas introduced by this commit:
commit bf5a144e16
This commit is contained in:
parent
ccdfcedf10
commit
0bf843cd13
5 changed files with 118 additions and 36 deletions
|
|
@ -802,3 +802,21 @@ connection default;
|
|||
DROP DATABASE u1;
|
||||
DROP USER u1@localhost;
|
||||
set @@global.character_set_server=@save_character_set_server;
|
||||
#
|
||||
# Start of 10.5 tests
|
||||
#
|
||||
#
|
||||
# MDEV-20366 Server crashes in get_current_user upon SET PASSWORD via SP
|
||||
#
|
||||
CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x');
|
||||
CALL p1();
|
||||
ERROR 28000: Can't find any matching row in the user table
|
||||
DROP PROCEDURE p1;
|
||||
CREATE USER foo@localhost;
|
||||
CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x');
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
DROP USER foo@localhost;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1078,3 +1078,30 @@ DROP DATABASE u1;
|
|||
DROP USER u1@localhost;
|
||||
|
||||
set @@global.character_set_server=@save_character_set_server;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-20366 Server crashes in get_current_user upon SET PASSWORD via SP
|
||||
--echo #
|
||||
|
||||
# Testing without the user
|
||||
CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x');
|
||||
--error ER_PASSWORD_NO_MATCH
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
# Testing with the user
|
||||
CREATE USER foo@localhost;
|
||||
CREATE PROCEDURE p1() SET PASSWORD FOR foo@localhost=PASSWORD('x');
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
DROP USER foo@localhost;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
|
|
|||
|
|
@ -11393,3 +11393,36 @@ bool LEX::stmt_revoke_proxy(THD *thd, LEX_USER *user)
|
|||
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_grant_proxy(sql_command,
|
||||
NO_ACL));
|
||||
}
|
||||
|
||||
|
||||
LEX_USER *LEX::current_user_for_set_password(THD *thd)
|
||||
{
|
||||
LEX_CSTRING pw= { STRING_WITH_LEN("password") };
|
||||
if (unlikely(spcont && spcont->find_variable(&pw, false)))
|
||||
{
|
||||
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
|
||||
return NULL;
|
||||
}
|
||||
LEX_USER *res;
|
||||
if (unlikely(!(res= (LEX_USER*) thd->calloc(sizeof(LEX_USER)))))
|
||||
return NULL;
|
||||
res->user= current_user;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_create_set_password_instr(THD *thd,
|
||||
LEX_USER *user,
|
||||
USER_AUTH *auth,
|
||||
bool no_lookahead)
|
||||
{
|
||||
user->auth= auth;
|
||||
set_var_password *var= new (thd->mem_root) set_var_password(user);
|
||||
if (unlikely(var == NULL) ||
|
||||
unlikely(var_list.push_back(var, thd->mem_root)))
|
||||
return true;
|
||||
autocommit= true;
|
||||
if (sphead)
|
||||
sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
|
||||
return sp_create_assignment_instr(thd, no_lookahead);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3864,6 +3864,21 @@ public:
|
|||
const Column_definition &ref,
|
||||
Row_definition_list *fields,
|
||||
Item *def);
|
||||
|
||||
LEX_USER *current_user_for_set_password(THD *thd);
|
||||
bool sp_create_set_password_instr(THD *thd,
|
||||
LEX_USER *user,
|
||||
USER_AUTH *auth,
|
||||
bool no_lookahead);
|
||||
bool sp_create_set_password_instr(THD *thd,
|
||||
USER_AUTH *auth,
|
||||
bool no_lookahead)
|
||||
{
|
||||
LEX_USER *user;
|
||||
return !(user= current_user_for_set_password(thd)) ||
|
||||
sp_create_set_password_instr(thd, user, auth, no_lookahead);
|
||||
}
|
||||
|
||||
bool sp_handler_declaration_init(THD *thd, int type);
|
||||
bool sp_handler_declaration_finalize(THD *thd, int type);
|
||||
|
||||
|
|
|
|||
|
|
@ -1543,6 +1543,7 @@ End SQL_MODE_ORACLE_SPECIFIC */
|
|||
admin_option_for_role user_maybe_role
|
||||
|
||||
%type <user_auth> opt_auth_str auth_expression auth_token
|
||||
text_or_password
|
||||
|
||||
%type <charset>
|
||||
opt_collate
|
||||
|
|
@ -16433,25 +16434,30 @@ option_value_no_option_type:
|
|||
unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| PASSWORD_SYM opt_for_user text_or_password
|
||||
| PASSWORD_SYM equal
|
||||
{
|
||||
if (sp_create_assignment_lex(thd, $1.pos()))
|
||||
MYSQL_YYABORT;
|
||||
LEX *lex = Lex;
|
||||
set_var_password *var= (new (thd->mem_root)
|
||||
set_var_password(lex->definer));
|
||||
if (unlikely(var == NULL) ||
|
||||
unlikely(lex->var_list.push_back(var, thd->mem_root)))
|
||||
}
|
||||
text_or_password
|
||||
{
|
||||
if (unlikely(Lex->sp_create_set_password_instr(thd, $4,
|
||||
yychar == YYEMPTY)))
|
||||
MYSQL_YYABORT;
|
||||
lex->autocommit= TRUE;
|
||||
if (lex->sphead)
|
||||
lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
|
||||
if (unlikely(sp_create_assignment_instr(thd, yychar == YYEMPTY)))
|
||||
}
|
||||
| PASSWORD_SYM FOR_SYM
|
||||
{
|
||||
if (sp_create_assignment_lex(thd, $1.pos()))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
user equal text_or_password
|
||||
{
|
||||
if (unlikely(Lex->sp_create_set_password_instr(thd, $4, $6,
|
||||
yychar == YYEMPTY)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
transaction_characteristics:
|
||||
transaction_access_mode
|
||||
| isolation_level
|
||||
|
|
@ -16508,42 +16514,25 @@ isolation_types:
|
|||
| SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; }
|
||||
;
|
||||
|
||||
opt_for_user:
|
||||
equal
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
sp_pcontext *spc= lex->spcont;
|
||||
LEX_CSTRING pw= { STRING_WITH_LEN("password") };
|
||||
|
||||
if (unlikely(spc && spc->find_variable(&pw, false)))
|
||||
my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
|
||||
if (unlikely(!(lex->definer= (LEX_USER*)
|
||||
thd->calloc(sizeof(LEX_USER)))))
|
||||
MYSQL_YYABORT;
|
||||
lex->definer->user= current_user;
|
||||
lex->definer->auth= new (thd->mem_root) USER_AUTH();
|
||||
}
|
||||
| FOR_SYM user equal { Lex->definer= $2; }
|
||||
;
|
||||
|
||||
text_or_password:
|
||||
TEXT_STRING
|
||||
{
|
||||
Lex->definer->auth= new (thd->mem_root) USER_AUTH();
|
||||
Lex->definer->auth->auth_str= $1;
|
||||
$$= new (thd->mem_root) USER_AUTH();
|
||||
$$->auth_str= $1;
|
||||
}
|
||||
| PASSWORD_SYM '(' TEXT_STRING ')'
|
||||
{
|
||||
Lex->definer->auth= new (thd->mem_root) USER_AUTH();
|
||||
Lex->definer->auth->pwtext= $3;
|
||||
$$= new (thd->mem_root) USER_AUTH();
|
||||
$$->pwtext= $3;
|
||||
}
|
||||
| OLD_PASSWORD_SYM '(' TEXT_STRING ')'
|
||||
{
|
||||
Lex->definer->auth= new (thd->mem_root) USER_AUTH();
|
||||
Lex->definer->auth->pwtext= $3;
|
||||
Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd,
|
||||
$$= new (thd->mem_root) USER_AUTH();
|
||||
$$->pwtext= $3;
|
||||
$$->auth_str.str= Item_func_password::alloc(thd,
|
||||
$3.str, $3.length, Item_func_password::OLD);
|
||||
Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
|
||||
$$->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue