mariadb/mysql-test/suite/roles/rebuild_role_grants.test
Vicențiu Ciorbaru 9e6c383867 MDEV-17964: Assertion `status == 0' failed in add_role_user_mapping_action
This happens upon CREATE USER and DROP ROLE.

The underlying problem is that our HASH implementation shuffles elements
around when performing an update or delete. This means that when doing a
scan through the HASH table by index, in search of elements to delete or
update one must restart the scan to make sure nothing is missed if at least
one delete / update happened.

More specifically, what happened in this case:
The hash has 131 element, DROP ROLE removes the element
[119]. Its [119]->next was element [129], so [129] is moved to [119].
Now we need to compact the hash, removing the last element [130]. It
gets one bit off its hash value and becomes element [2]. The existing
element [2] is moved to [129], and old [130] is moved to [2].

We cannot simply move [130] to [129] and make [2]->next=130, it won't
work if [2] is itself in the collision list and doesn't belong in [2].

The handle_grant_struct code assumed that it is safe to continue by only
reexamining the currently modified / deleted element index, but that is
not true.

Missing to delete an element in the hash triggered the assertion in
the test case. DROP ROLE would not clear all necessary role->role or
role->user mappings.

To fix the problem we ensure that the scan is restarted, only if an
element was deleted / updated, similar to how bubble-sort keeps sorting
until it finds no more elements to swap.
2021-10-15 19:19:36 +03:00

100 lines
1.8 KiB
Text

source include/not_embedded.inc;
create role r1;
create user u1;
grant r1 to u1;
#CHECK IF GRANTS ARE UPDATED ON GRANT
--sorted_result
show grants for u1;
create user u2;
#CHECK THAT GRANTS ARE UPDATED ON ACL_USERS CHANGE
--sorted_result
show grants for u1;
--sorted_result
show grants for u2;
--sorted_result
select * from mysql.roles_mapping;
revoke r1 from u1;
#TEST ERROR MESSAGE
--error ER_CANNOT_REVOKE_ROLE
revoke r1 from u1;
--sorted_result
show grants for u1;
--sorted_result
select * from mysql.roles_mapping;
# granting twice is ok
grant r1 to u1;
grant r1 to u1;
--sorted_result
show grants for u1;
--sorted_result
select * from mysql.roles_mapping;
drop role r1;
--sorted_result
show grants for u1;
--sorted_result
select * from mysql.roles_mapping;
create role r1;
grant r1 to u1;
--sorted_result
select * from mysql.roles_mapping;
drop user u1;
--error ER_NONEXISTING_GRANT
show grants for u1;
--sorted_result
select * from mysql.roles_mapping;
drop role r1;
drop user u2;
#
# MDEV-8614 Assertion `status == 0' failed in add_role_user_mapping_action on RENAME USER
#
create user foo@localhost;
grant create user on *.* to foo@localhost;
--connect (con1, localhost, foo,,)
create role look, isp, xxx, ppp;
rename user current_user to nnnn@'%';
drop role look, isp, xxx, ppp;
connection default;
disconnect con1;
drop user nnnn@'%';
#
# MDEV-17964 Assertion `status == 0' failed in add_role_user_mapping_action
# upon CREATE USER and DROP ROLE
#
CREATE USER u@localhost;
--let $n= 1
while ($n < 129)
{
eval CREATE ROLE r$n;
inc $n;
}
CREATE ROLE n;
CREATE ROLE d WITH ADMIN n;
CREATE ROLE '%' WITH ADMIN u@localhost;
DROP ROLE n;
CREATE USER 't';
--let $n= 1
while ($n < 129)
{
eval DROP ROLE r$n;
inc $n;
}
DROP ROLE d;
DROP ROLE '%';
DROP USER 't';
DROP USER u@localhost;