From cc6bba008d750196b8537025ab48d5f8e274bbcd Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 20 Oct 2021 10:21:00 +0200 Subject: MDEV-26647 (plugin name) Include password validation plugin information in the error message if the SQL statement is not satisfied password policy Add plugin name to the error message. --- sql/share/errmsg-utf8.txt | 3 ++- sql/sql_acl.cc | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index b05fa5e5412..97520facefe 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6925,7 +6925,8 @@ ER_INVALID_YEAR_COLUMN_LENGTH rus "Тип YEAR(%lu) более не поддерживается, вместо него будет создана колонка с типом YEAR(4)" ER_NOT_VALID_PASSWORD - eng "Your password does not satisfy the current policy requirements" + eng "Your password does not satisfy the current policy requirements (%s)" + ukr "Ваш пароль не відповідає поточним правилам (%s)" ER_MUST_CHANGE_PASSWORD eng "You must SET PASSWORD before executing this statement" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 4c68b4505a4..07d77d28753 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1450,7 +1450,12 @@ static my_bool do_validate(THD *, plugin_ref plugin, void *arg) struct validation_data *data= (struct validation_data *)arg; struct st_mariadb_password_validation *handler= (st_mariadb_password_validation *)plugin_decl(plugin)->info; - return handler->validate_password(data->user, data->password); + if (handler->validate_password(data->user, data->password)) + { + my_error(ER_NOT_VALID_PASSWORD, MYF(0), plugin_ref_to_int(plugin)->name.str); + return true; + } + return false; } @@ -1464,7 +1469,6 @@ static bool validate_password(LEX_USER *user, THD *thd) if (plugin_foreach(NULL, do_validate, MariaDB_PASSWORD_VALIDATION_PLUGIN, &data)) { - my_error(ER_NOT_VALID_PASSWORD, MYF(0)); return true; } } -- cgit v1.2.1 From cbcc0101ee3016b398490685d30db296b1892db7 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 28 Jul 2022 16:17:03 +0200 Subject: MDEV-29188 Crash in JSON_EXTRACT If we have null_value set then decimal/string value/result shoud be 0 pointer. --- sql/item_cmpfunc.cc | 4 ++++ sql/item_jsonfunc.cc | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f41414f8ae9..a3c0d4d95df 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -795,7 +795,9 @@ int Arg_comparator::compare_e_string() { String *res1,*res2; res1= (*a)->val_str(&value1); + DBUG_ASSERT((res1 == NULL) == (*a)->null_value); res2= (*b)->val_str(&value2); + DBUG_ASSERT((res2 == NULL) == (*b)->null_value); if (!res1 || !res2) return MY_TEST(res1 == res2); return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0); @@ -832,10 +834,12 @@ int Arg_comparator::compare_decimal() { my_decimal decimal1; my_decimal *val1= (*a)->val_decimal(&decimal1); + DBUG_ASSERT((val1 == NULL) == (*a)->null_value); if (!(*a)->null_value) { my_decimal decimal2; my_decimal *val2= (*b)->val_decimal(&decimal2); + DBUG_ASSERT((val2 == NULL) == (*b)->null_value); if (!(*b)->null_value) { if (set_null) diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index c0f063639bc..5166d9a78af 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1109,12 +1109,14 @@ my_decimal *Item_func_json_extract::val_decimal(my_decimal *to) case JSON_VALUE_OBJECT: case JSON_VALUE_ARRAY: case JSON_VALUE_FALSE: + // TODO: fix: NULL should be NULL case JSON_VALUE_NULL: - break; + int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to); + return to; }; } - int2my_decimal(E_DEC_FATAL_ERROR, 0, false/*unsigned_flag*/, to); - return to; + DBUG_ASSERT(null_value); + return 0; } -- cgit v1.2.1 From 25219920f55cc5218cec1139dc68d91b5f910514 Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Fri, 29 Jul 2022 15:41:43 +0530 Subject: MDEV-28762: recursive call of some json functions without stack control Fixup to MDEV-28762. Fixes warnings about unused variable "stack_used_up" during building with RelWithDebInfo --- sql/item_jsonfunc.cc | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'sql') diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 5166d9a78af..37dd2454116 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -150,10 +150,12 @@ int json_path_parts_compare( { int res, res2; - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); DBUG_EXECUTE_IF("json_check_min_stack_requirement", - {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);}); + { + long arbitrary_var; + long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); + ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); + }); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -1154,10 +1156,12 @@ static int check_contains(json_engine_t *js, json_engine_t *value) { json_engine_t loc_js; bool set_js; - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); DBUG_EXECUTE_IF("json_check_min_stack_requirement", - {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);}); + { + long arbitrary_var; + long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); + ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); + }); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -2050,10 +2054,12 @@ err_return: static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2) { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); DBUG_EXECUTE_IF("json_check_min_stack_requirement", - {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);}); + { + long arbitrary_var; + long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); + ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); + }); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -2389,10 +2395,12 @@ static int copy_value_patch(String *str, json_engine_t *je) static int do_merge_patch(String *str, json_engine_t *je1, json_engine_t *je2, bool *empty_result) { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); DBUG_EXECUTE_IF("json_check_min_stack_requirement", - {ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE);}); + { + long arbitrary_var; + long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); + ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); + }); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; -- cgit v1.2.1 From 6c7e3e5c13162b7ffa90eaa81b4ba5afaf3e0c1e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Jul 2022 10:24:45 +0200 Subject: bugfix: RAND is VCOL_SESSION_FUNC it's not "non deterministic", it's completely defined by @@rand_seed1 and @@rand_seed2. And as a session func it needs to be re-fixed at the beginning of every statement. --- sql/item_func.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_func.h b/sql/item_func.h index 754b1cd1eb2..7268b56eb97 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1513,7 +1513,7 @@ public: void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); } bool check_vcol_func_processor(void *arg) { - return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); + return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC); } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } -- cgit v1.2.1 From 8ea529ecbaf63213ef2097f7a1abeac4ae3dd481 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 29 Jul 2022 21:57:06 +0200 Subject: MDEV-29131 Assertion `status == 0' failed when renaming user after deleting table roles_mapping if mysql.roles_mapping table doesn't exist (it's optional, after all), we still update in-memory structures to keep them consistent --- sql/sql_acl.cc | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 07d77d28753..3a605f8e7b7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -10153,24 +10153,21 @@ static int handle_grant_data(THD *thd, Grant_tables& tables, bool drop, } /* Handle roles_mapping table. */ - if (tables.roles_mapping_table().table_exists()) + if (tables.roles_mapping_table().table_exists() && + (found= handle_grant_table(thd, tables.roles_mapping_table(), + ROLES_MAPPING_TABLE, drop, user_from, user_to)) < 0) { - if ((found= handle_grant_table(thd, tables.roles_mapping_table(), - ROLES_MAPPING_TABLE, drop, - user_from, user_to)) < 0) - { - /* Handle of table failed, don't touch the in-memory array. */ - result= -1; - } - else - { - /* Handle acl_roles_mappings array */ - if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) || found) - && ! result) - result= 1; /* At least one record/element found */ - if (search_only) - goto end; - } + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle acl_roles_mappings array */ + if ((handle_grant_struct(ROLES_MAPPINGS_HASH, drop, user_from, user_to) || found) + && ! result) + result= 1; /* At least one record/element found */ + if (search_only) + goto end; } /* Handle user table. */ -- cgit v1.2.1 From 40c2460d8c5b614cb84fac41f14de25d80f6fd1c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 1 Aug 2022 11:11:26 +0200 Subject: in INFORMATION_SCHEMA.ALL_PLUGINS match installed plugins better look for an installed plugin with the same name _and the same type_ (in case there are many plugins with the same name and different type, which is, technically, possible for built-in plugins). --- sql/sql_plugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 1858e9d81c8..b251df490c4 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2458,7 +2458,7 @@ static bool plugin_dl_foreach_internal(THD *thd, st_plugin_dl *plugin_dl, tmp.plugin_dl= plugin_dl; mysql_mutex_lock(&LOCK_plugin); - if ((plugin= plugin_find_internal(&tmp.name, MYSQL_ANY_PLUGIN)) && + if ((plugin= plugin_find_internal(&tmp.name, plug->type)) && plugin->plugin == plug) { -- cgit v1.2.1 From 231feabd2b7f537c9a216a8767763814a4de268b Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 1 Aug 2022 11:13:50 +0300 Subject: MDEV-21540 Initialization of already inited long unique index on reorganize partition Handler for existing partition was already index-inited at the beginning of copy_partitions(). In the case of REORGANIZE PARTITION we fill new partition by calling its ha_write_row() (handler is storage engine of new partition). From that we go through the below conditions: if (this->inited == RND) table->clone_handler_for_update(); handler *h= table->update_handler ? table->update_handler : table->file; First, the above misses the meaning of this->inited check. Now it is new partition and this handler is not inited. So, we assign table->file which is ha_partition and is really not known to be inited or not. It is supposed (this == table->file), otherwise we are out of the logic for using update_handler. This patch adds DBUG_ASSERT for that. Second, we call check_duplicate_long_entries() for table->file and that calls ha_partition::index_init() which calls index_init() for each partition's handler. But the existing parititions' handlers was already inited in copy_partitions() and we fail on assertion. The fix implies that we don't need check_duplicate_long_entries() per-partition as we've already done check_duplicate_long_entries() for ha_partition. For REORGANIZE PARTITION that means existing row was already checked at previous INSERT/UPDATE commands, so no need to check it again (see NOTE in handler::ha_write_row()). The fix also optimizes ha_update_row() so check_duplicate_long_entries_update() is not called per-partition considering it was already called for ha_partition. Besides, per-partition duplicate check is not really usable. --- sql/handler.cc | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index 56eda39127f..bf819733b81 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6782,7 +6782,18 @@ int handler::ha_write_row(const uchar *buf) mark_trx_read_write(); increment_statistics(&SSV::ha_write_count); - if (table->s->long_unique_table) + /* + NOTE: this != table->file is true in 3 cases: + + 1. under copy_partitions() (REORGANIZE PARTITION): that does not + require long unique check as it does not introduce new rows or new index. + 2. under partition's ha_write_row() (INSERT): check_duplicate_long_entries() + was already done by ha_partition::ha_write_row(), no need to check it + again for each single partition. + 3. under ha_mroonga::wrapper_write_row() + */ + + if (table->s->long_unique_table && this == table->file) { if (this->inited == RND) table->clone_handler_for_update(); @@ -6830,8 +6841,17 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str); mark_trx_read_write(); increment_statistics(&SSV::ha_update_count); - if (table->s->long_unique_table && - (error= check_duplicate_long_entries_update(table, table->file, (uchar *)new_data))) + + /* + NOTE: this != table->file is true under partition's ha_update_row(): + check_duplicate_long_entries_update() was already done by + ha_partition::ha_update_row(), no need to check it again for each single + partition. Same applies to ha_mroonga wrapper. + */ + + if (table->s->long_unique_table && this == table->file && + (error= check_duplicate_long_entries_update(table, table->file, + (uchar *)new_data))) { return error; } -- cgit v1.2.1 From 1ea5e402a89a1e3fb9ba8045e58570d23837714a Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 1 Aug 2022 11:13:50 +0300 Subject: MDEV-28727 ALTER TABLE ALGORITHM=NOCOPY does not work after upgrade MDEV-20704 changed the rules of how (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) flags are added. Older FRMs before that fix had these flags for DOUBLE index. After that fix when ALTER sees such old FRM it thinks it cannot do instant alter because of failed compare_keys_but_name(): it compares flags against tmp table created by ALTER. MDEV-20704 fix was actually not about DOUBLE type but about FIELDFLAG_BLOB which affected DOUBLE. So there is no direct knowledge that any other types were not affected. The proposed fix under CHECK TABLE checks if FRM has (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) flags and was created prior MDEV-20704 and if so issues "needs upgrade". When mysqlcheck and mysql_upgrade see such status they issue ALTER TABLE FORCE and upgrade the table to the version of server. --- sql/handler.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index bf819733b81..e6e665f0e12 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4370,17 +4370,32 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE || m_lock_type != F_UNLCK); - if ((table->s->mysql_version >= MYSQL_VERSION_ID) && + const ulong v= table->s->mysql_version; + + if ((v >= MYSQL_VERSION_ID) && (check_opt->sql_flags & TT_FOR_UPGRADE)) return 0; - if (table->s->mysql_version < MYSQL_VERSION_ID) + if (v < MYSQL_VERSION_ID) { if (unlikely((error= check_old_types()))) return error; error= ha_check_for_upgrade(check_opt); if (unlikely(error && (error != HA_ADMIN_NEEDS_CHECK))) return error; + if (table->s->table_category == TABLE_CATEGORY_USER && + (v < 100142 || + (v >= 100200 && v < 100228) || + (v >= 100300 && v < 100319) || + (v >= 100400 && v < 100409))) + { + for (const KEY *key= table->key_info, + *end= table->key_info + table->s->keys; key < end; key++) + { + if (key->flags & HA_BINARY_PACK_KEY && key->flags & HA_VAR_LENGTH_KEY) + return HA_ADMIN_NEEDS_UPGRADE; + } + } if (unlikely(!error && (check_opt->sql_flags & TT_FOR_UPGRADE))) return 0; } -- cgit v1.2.1