mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
MDEV-4951 drop user leaves privileges
It's safe to delete from HASH when traversing it *backwards*, but not *forwards*.
This commit is contained in:
parent
1906f1388e
commit
d126993404
4 changed files with 31 additions and 28 deletions
|
@ -1615,8 +1615,8 @@ ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't
|
|||
show grants for mysqluser10@localhost;
|
||||
Grants for mysqluser10@localhost
|
||||
GRANT USAGE ON *.* TO 'mysqluser10'@'localhost'
|
||||
GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser10'@'localhost'
|
||||
GRANT SELECT ON `mysqltest1`.`t11` TO 'mysqluser10'@'localhost'
|
||||
GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser10'@'localhost'
|
||||
GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser10'@'localhost'
|
||||
GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser10'@'localhost'
|
||||
select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost';
|
||||
|
|
|
@ -1154,6 +1154,8 @@ drop user olga@localhost;
|
|||
drop user pjotr@localhost;
|
||||
drop user quintessa@localhost;
|
||||
drop database mysqltest1;
|
||||
select * from information_schema.table_privileges;
|
||||
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
|
||||
End of 5.0 tests.
|
||||
DROP VIEW IF EXISTS v1;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
|
|
|
@ -1595,6 +1595,12 @@ disconnect root;
|
|||
|
||||
connection default;
|
||||
|
||||
#
|
||||
# MDEV-4951 drop user leaves privileges
|
||||
#
|
||||
#verify that no privileges were left after the above
|
||||
select * from information_schema.table_privileges;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
||||
|
||||
|
|
|
@ -6137,8 +6137,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
LEX_USER *user_from, LEX_USER *user_to)
|
||||
{
|
||||
int result= 0;
|
||||
uint idx;
|
||||
uint elements;
|
||||
int idx;
|
||||
int elements;
|
||||
const char *user;
|
||||
const char *host;
|
||||
ACL_USER *acl_user= NULL;
|
||||
|
@ -6187,8 +6187,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
|
||||
struct_no, user_from->user.str, user_from->host.str));
|
||||
#endif
|
||||
/* Loop over all elements. */
|
||||
for (idx= 0; idx < elements; idx++)
|
||||
/* Loop over all elements *backwards* (see the comment below). */
|
||||
for (idx= elements - 1; idx >= 0; idx--)
|
||||
{
|
||||
/*
|
||||
Get a pointer to the element.
|
||||
|
@ -6239,6 +6239,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
result= 1; /* At least one element found. */
|
||||
if ( drop )
|
||||
{
|
||||
elements--;
|
||||
switch ( struct_no ) {
|
||||
case USER_ACL:
|
||||
delete_dynamic_element(&acl_users, idx);
|
||||
|
@ -6252,6 +6253,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
case PROC_PRIVILEGES_HASH:
|
||||
case FUNC_PRIVILEGES_HASH:
|
||||
my_hash_delete(grant_name_hash, (uchar*) grant_name);
|
||||
/*
|
||||
In our HASH implementation on deletion one elements
|
||||
is moved into a place where a deleted element was,
|
||||
and the last element is moved into the empty space.
|
||||
Thus we need to re-examine the current element, but
|
||||
we don't have to restart the search from the beginning.
|
||||
*/
|
||||
if (idx != elements)
|
||||
idx++;
|
||||
break;
|
||||
|
||||
case PROXY_USERS_ACL:
|
||||
|
@ -6259,21 +6269,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
break;
|
||||
|
||||
}
|
||||
elements--;
|
||||
/*
|
||||
- If we are iterating through an array then we just have moved all
|
||||
elements after the current element one position closer to its head.
|
||||
This means that we have to take another look at the element at
|
||||
current position as it is a new element from the array's tail.
|
||||
- If we are iterating through a hash the current element was replaced
|
||||
with one of elements from the tail. So we also have to take a look
|
||||
at the new element in current position.
|
||||
Note that in our HASH implementation hash_delete() won't move any
|
||||
elements with position after current one to position before the
|
||||
current (i.e. from the tail to the head), so it is safe to continue
|
||||
iteration without re-starting.
|
||||
*/
|
||||
idx--;
|
||||
}
|
||||
else if ( user_to )
|
||||
{
|
||||
|
@ -6314,15 +6309,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
|||
my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
|
||||
old_key_length);
|
||||
/*
|
||||
hash_update() operation could have moved element from the tail
|
||||
of the hash to the current position. So we need to take a look
|
||||
at the element in current position once again.
|
||||
Thanks to the fact that hash_update() for our HASH implementation
|
||||
won't move any elements from the tail of the hash to the positions
|
||||
before the current one (a.k.a. head) it is safe to continue
|
||||
iteration without restarting.
|
||||
hash_update() operation could have moved element from the tail or
|
||||
the head of the hash to the current position. But it can never
|
||||
move an element from the head to the tail or from the tail to the
|
||||
head over the current element.
|
||||
So we need to examine the current element once again, but
|
||||
we don't need to restart the search from the beginning.
|
||||
*/
|
||||
idx--;
|
||||
if (idx != elements)
|
||||
idx++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue