Commit 6c55e52b authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

MDEV-7774: Crash when dropping user within rebuild_role_grants

The issue comes from not taking all possibilities to match an entry
within the roles_mapping HASH, when updating the data structure.
parent acab0faa
......@@ -46,3 +46,21 @@ Note 1449 The user specified as a definer ('u1'@'%') does not exist
create user foo@bar;
drop user foo@bar;
drop role r1;
CREATE USER u1;
CREATE ROLE r1;
CREATE USER r1@localhost;
CREATE ROLE r2;
GRANT r2 to r1;
GRANT r2 to r1@localhost;
DROP ROLE r1;
SELECT * FROM mysql.roles_mapping;
Host User Role Admin_option
localhost r1 r2 N
localhost root r2 Y
SHOW GRANTS FOR r1@localhost;
Grants for r1@localhost
GRANT r2 TO 'r1'@'localhost'
GRANT USAGE ON *.* TO 'r1'@'localhost'
DROP USER u1;
DROP ROLE r2;
DROP USER r1@localhost;
......@@ -68,3 +68,22 @@ create user foo@bar;
drop user foo@bar;
drop role r1;
#
# MDEV-7774 Assertion `status == 0' fails when dropping in this order:
#
CREATE USER u1;
CREATE ROLE r1;
CREATE USER r1@localhost;
CREATE ROLE r2;
GRANT r2 to r1;
GRANT r2 to r1@localhost;
# MDEV-7774: Dropping in this order caused the crash.
DROP ROLE r1;
--sorted_result
SELECT * FROM mysql.roles_mapping;
SHOW GRANTS FOR r1@localhost; # Related to MDEV-7774, also caused a crash, by
# not updating the internal acl_roles_mapping
# data structure correctly;
DROP USER u1;
DROP ROLE r2;
DROP USER r1@localhost;
......@@ -8802,10 +8802,30 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
if (struct_no == ROLES_MAPPINGS_HASH)
{
const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: "";
if (user_from->is_role() ? strcmp(user_from->user.str, role) :
(strcmp(user_from->user.str, user) ||
my_strcasecmp(system_charset_info, user_from->host.str, host)))
continue;
if (user_from->is_role())
{
/* When searching for roles within the ROLES_MAPPINGS_HASH, we have
to check both the user field as well as the role field for a match.
It is possible to have a role granted to a role. If we are going
to modify the mapping entry, it needs to be done on either on the
"user" end (here represented by a role) or the "role" end. At least
one part must match.
If the "user" end has a not-empty host string, it can never match
as we are searching for a role here. A role always has an empty host
string.
*/
if ((*host || strcmp(user_from->user.str, user)) &&
strcmp(user_from->user.str, role))
continue;
}
else
{
if (strcmp(user_from->user.str, user) ||
my_strcasecmp(system_charset_info, user_from->host.str, host))
continue;
}
}
else
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment