MDEV-6733: Add DEFINER support to ALTER PROCEDURE#5060
MDEV-6733: Add DEFINER support to ALTER PROCEDURE#5060amrSherif12 wants to merge 1 commit intoMariaDB:mainfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request implements the ability to change the definer of a stored procedure using the ALTER PROCEDURE statement. The changes include updates to the parser, the routine update handler, and the addition of privilege checks. Feedback includes addressing a potential buffer overflow when handling user/host strings, utilizing existing helper functions for more robust privilege and hostname checks, ensuring the procedure cache is invalidated only upon successful updates, and correcting a type mismatch in the grammar definition.
| char definer_str[USER_HOST_BUFF_SIZE]; | ||
| uint definer_len= strxmov(definer_str, definer->user.str, "@", | ||
| definer->host.str, NullS) - | ||
| definer_str; | ||
| table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull(); | ||
| table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str, definer_len, | ||
| system_charset_info); |
There was a problem hiding this comment.
Using a fixed-size buffer of USER_HOST_BUFF_SIZE (142 bytes) is unsafe. In modern MariaDB, usernames can be up to 128 characters, which in UTF-8 can exceed this buffer size when combined with the hostname. This could lead to a buffer overflow. It is safer to use the String class which handles dynamic allocation and correctly manages lengths.
String definer_str;
definer_str.append(definer->user.str, definer->user.length);
definer_str.append('@');
definer_str.append(definer->host.str, definer->host.length);
table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull();
table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str.ptr(),
definer_str.length(),
system_charset_info);| if (lex->definer) | ||
| { | ||
| if ((!lex_string_eq(&lex->definer->user, thd->security_ctx->priv_user, strlen(thd->security_ctx->priv_user)) || | ||
| !lex_string_eq(&lex->definer->host, thd->security_ctx->priv_host, strlen(thd->security_ctx->priv_host))) && | ||
| check_global_access(thd, SET_USER_ACL | SUPER_ACL)) | ||
| return 1; | ||
| } |
There was a problem hiding this comment.
Instead of manually implementing the privilege check, you should use the existing check_definer_access() function. This improves maintainability and fixes a bug in the current implementation: lex_string_eq is case-sensitive, but hostnames in MariaDB should be compared case-insensitively. check_definer_access() handles this correctly using my_strcasecmp for the host part.
if (lex->definer && check_definer_access(thd, lex->definer))
return 1;| table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull(); | ||
| table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str, definer_len, | ||
| system_charset_info); | ||
| sp_cache_invalidate(); |
There was a problem hiding this comment.
The call to sp_cache_invalidate() should ideally be placed after the successful execution of ha_update_row(). This ensures the cache is only invalidated if the database record was actually updated. Furthermore, consider if the cache should be invalidated for any characteristic change (like COMMENT), as the cached sp_head object contains these values and might become stale.
| %type <lex_user> user grant_user grant_role user_or_role current_role | ||
| admin_option_for_role user_maybe_role role_name | ||
| user_name | ||
| user_name sp_a_chistic |
There was a problem hiding this comment.
Declaring sp_a_chistic as <lex_user> is technically incorrect because the sp_chistic branch of this rule does not return a LEX_USER* value. Since the value of sp_a_chistic is not used by the parent sp_a_chistics rule, it should remain untyped to avoid potential issues with uninitialized values in the parser.
user_name
This PR implements the ALTER PROCEDURE ... DEFINER = ... syntax