From 15259e7e8aef731caf725ca0fc45223a040e9732 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 May 2007 10:39:24 -0700 Subject: [PATCH 1/3] Bug#27836 "sql_plugin.cc, dynamic_array is not dynamic" When the DYNAMIC_ARRAYs were resized, pointers became invalid. Solved by only storing pointers within the DYNAMIC_ARRAYs. sql/sql_plugin.cc: Bug27836 Store pointers to data structures in dynamic arrays: plugin_dl_array, plugin_array Allocate data structures in plugin_mem_root --- sql/sql_plugin.cc | 56 +++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 5f8513a4a9e..5008019fb30 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -278,7 +278,7 @@ static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl) DBUG_ENTER("plugin_dl_find"); for (i= 0; i < plugin_dl_array.elements; i++) { - tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); + tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **); if (tmp->ref_count && ! my_strnncoll(files_charset_info, (const uchar *)dl->str, dl->length, @@ -296,17 +296,20 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) DBUG_ENTER("plugin_dl_insert_or_reuse"); for (i= 0; i < plugin_dl_array.elements; i++) { - tmp= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); + tmp= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **); if (! tmp->ref_count) { memcpy(tmp, plugin_dl, sizeof(struct st_plugin_dl)); DBUG_RETURN(tmp); } } - if (insert_dynamic(&plugin_dl_array, (gptr)plugin_dl)) + if (insert_dynamic(&plugin_dl_array, (gptr)&plugin_dl)) DBUG_RETURN(0); - DBUG_RETURN(dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1, - struct st_plugin_dl *)); + tmp= *dynamic_element(&plugin_dl_array, plugin_dl_array.elements - 1, + struct st_plugin_dl **)= + (struct st_plugin_dl *) memdup_root(&plugin_mem_root, (gptr)plugin_dl, + sizeof(struct st_plugin_dl)); + DBUG_RETURN(tmp); } #endif /* HAVE_DLOPEN */ @@ -516,8 +519,8 @@ static void plugin_dl_del(const LEX_STRING *dl) for (i= 0; i < plugin_dl_array.elements; i++) { - struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i, - struct st_plugin_dl *); + struct st_plugin_dl *tmp= *dynamic_element(&plugin_dl_array, i, + struct st_plugin_dl **); if (tmp->ref_count && ! my_strnncoll(files_charset_info, (const uchar *)dl->str, dl->length, @@ -665,21 +668,24 @@ plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) { uint i; + struct st_plugin_int *tmp; DBUG_ENTER("plugin_insert_or_reuse"); for (i= 0; i < plugin_array.elements; i++) { - struct st_plugin_int *tmp= dynamic_element(&plugin_array, i, - struct st_plugin_int *); + tmp= *dynamic_element(&plugin_array, i, struct st_plugin_int **); if (tmp->state == PLUGIN_IS_FREED) { memcpy(tmp, plugin, sizeof(struct st_plugin_int)); DBUG_RETURN(tmp); } } - if (insert_dynamic(&plugin_array, (gptr)plugin)) + if (insert_dynamic(&plugin_array, (gptr)&plugin)) DBUG_RETURN(0); - DBUG_RETURN(dynamic_element(&plugin_array, plugin_array.elements - 1, - struct st_plugin_int *)); + tmp= *dynamic_element(&plugin_array, plugin_array.elements - 1, + struct st_plugin_int **)= + (struct st_plugin_int *) memdup_root(&plugin_mem_root, (gptr)plugin, + sizeof(struct st_plugin_int)); + DBUG_RETURN(tmp); } @@ -874,7 +880,7 @@ static void reap_plugins(void) for (idx= 0; idx < count; idx++) { - plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count) { /* change the status flag to prevent reaping by another thread */ @@ -1097,9 +1103,9 @@ int plugin_init(int *argc, char **argv, int flags) pthread_mutex_init(&LOCK_plugin, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&plugin_dl_array, - sizeof(struct st_plugin_dl),16,16) || + sizeof(struct st_plugin_dl *),16,16) || my_init_dynamic_array(&plugin_array, - sizeof(struct st_plugin_int),16,16)) + sizeof(struct st_plugin_int *),16,16)) goto err; for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++) @@ -1185,7 +1191,7 @@ int plugin_init(int *argc, char **argv, int flags) for (i= 0; i < plugin_array.elements; i++) { - plugin_ptr= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugin_ptr= *dynamic_element(&plugin_array, i, struct st_plugin_int **); if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED) { if (plugin_initialize(plugin_ptr)) @@ -1232,11 +1238,13 @@ static bool register_builtin(struct st_mysql_plugin *plugin, tmp->ref_count= 0; tmp->plugin_dl= 0; - if (insert_dynamic(&plugin_array, (gptr)tmp)) + if (insert_dynamic(&plugin_array, (gptr)&tmp)) DBUG_RETURN(1); - *ptr= dynamic_element(&plugin_array, plugin_array.elements - 1, - struct st_plugin_int *); + *ptr= *dynamic_element(&plugin_array, plugin_array.elements - 1, + struct st_plugin_int **)= + (struct st_plugin_int *) memdup_root(&plugin_mem_root, (gptr)tmp, + sizeof(struct st_plugin_int)); if (my_hash_insert(&plugin_hash[plugin->type],(byte*) *ptr)) DBUG_RETURN(1); @@ -1458,7 +1466,7 @@ void plugin_shutdown(void) reap_plugins(); for (i= free_slots= 0; i < count; i++) { - plugin= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, i, struct st_plugin_int **); switch (plugin->state) { case PLUGIN_IS_READY: plugin->state= PLUGIN_IS_DELETED; @@ -1490,7 +1498,7 @@ void plugin_shutdown(void) */ for (i= 0; i < count; i++) { - plugins[i]= dynamic_element(&plugin_array, i, struct st_plugin_int *); + plugins[i]= *dynamic_element(&plugin_array, i, struct st_plugin_int **); /* change the state to ensure no reaping races */ if (plugins[i]->state == PLUGIN_IS_DELETED) plugins[i]->state= PLUGIN_IS_DYING; @@ -1555,7 +1563,7 @@ void plugin_shutdown(void) count= plugin_dl_array.elements; dl= (struct st_plugin_dl **)my_alloca(sizeof(void*) * count); for (i= 0; i < count; i++) - dl[i]= dynamic_element(&plugin_dl_array, i, struct st_plugin_dl *); + dl[i]= *dynamic_element(&plugin_dl_array, i, struct st_plugin_dl **); for (i= 0; i < plugin_dl_array.elements; i++) free_plugin_mem(dl[i]); my_afree(dl); @@ -1714,7 +1722,7 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, { for (idx= 0; idx < total; idx++) { - plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; } } @@ -3139,7 +3147,7 @@ void my_print_help_inc_plugins(my_option *main_options, uint size) if (initialized) for (uint idx= 0; idx < plugin_array.elements; idx++) { - p= dynamic_element(&plugin_array, idx, struct st_plugin_int *); + p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); if (!p->plugin->system_vars || !(opt= construct_help_options(&mem_root, p))) From a40ec74750f512d4fcd1c38b19cdf76ad208f513 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 May 2007 16:40:24 -0700 Subject: [PATCH 2/3] Missing functionality in WL#2936: String variables not readable by using @@name. Required for WL1722. sql/set_var.cc: Missing functionality in WL2936: String variables not readable by using @@name. --- sql/set_var.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sql/set_var.cc b/sql/set_var.cc index 3dc8cddcb26..bd9b31468f7 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1489,6 +1489,25 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) pthread_mutex_unlock(&LOCK_global_system_variables); return new Item_int(value,1); } + case SHOW_CHAR_PTR: + { + Item *tmp; + pthread_mutex_lock(&LOCK_global_system_variables); + char *str= *(char**) value_ptr(thd, var_type, base); + if (str) + { + uint length= strlen(str); + tmp= new Item_string(thd->strmake(str, length), length, + system_charset_info, DERIVATION_SYSCONST); + } + else + { + tmp= new Item_null(); + tmp->collation.set(system_charset_info, DERIVATION_SYSCONST); + } + pthread_mutex_unlock(&LOCK_global_system_variables); + return tmp; + } case SHOW_CHAR: { Item *tmp; From 787e0a39479ddd0b43a351e990d8ae23ebfb8307 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 May 2007 13:27:26 +0500 Subject: [PATCH 3/3] BUG#18839 - return value of parser->parse() is ignored Check value returned by parser->parse(). Better handle situations when it fails. storage/myisam/ft_boolean_search.c: Check value returned by parser->parse(). storage/myisam/ft_nlq_search.c: Check value returned by parser->parse(). --- storage/myisam/ft_boolean_search.c | 51 ++++++++++++++++++------------ storage/myisam/ft_nlq_search.c | 8 +++-- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 68076d7e401..f5866011f04 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -286,8 +286,8 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, } -static void _ftb_parse_query(FTB *ftb, byte *query, uint len, - struct st_mysql_ftparser *parser) +static int _ftb_parse_query(FTB *ftb, byte *query, uint len, + struct st_mysql_ftparser *parser) { MYSQL_FTPARSER_PARAM *param; MY_FTB_PARAM ftb_param; @@ -295,9 +295,9 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, DBUG_ASSERT(parser); if (ftb->state != UNINITIALIZED) - DBUG_VOID_RETURN; + DBUG_RETURN(0); if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 0))) - DBUG_VOID_RETURN; + DBUG_RETURN(1); ftb_param.ftb= ftb; ftb_param.depth= 0; @@ -312,8 +312,7 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len, param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO; - parser->parse(param); - DBUG_VOID_RETURN; + DBUG_RETURN(parser->parse(param)); } @@ -538,9 +537,10 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ftbe->phrase= NULL; ftbe->document= 0; ftb->root=ftbe; - _ftb_parse_query(ftb, query, query_len, keynr == NO_SUCH_KEY ? - &ft_default_parser : - info->s->keyinfo[keynr].parser); + if (unlikely(_ftb_parse_query(ftb, query, query_len, + keynr == NO_SUCH_KEY ? &ft_default_parser : + info->s->keyinfo[keynr].parser))) + goto err; /* Hack: instead of init_queue, we'll use reinit queue to be able to alloc queue with alloc_root() @@ -621,7 +621,7 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, { param->mysql_add_word(param, word.pos, word.len, 0); if (phrase_param->match) - return 1; + break; } return 0; } @@ -639,6 +639,7 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, RETURN VALUE 1 is returned if phrase found, 0 else. + -1 is returned if error occurs. */ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, @@ -667,12 +668,13 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len, param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_WITH_STOPWORDS; - parser->parse(param); + if (unlikely(parser->parse(param))) + return -1; DBUG_RETURN(ftb_param.match ? 1 : 0); } -static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_orig) +static int _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_orig) { FT_SEG_ITERATOR ftsi; FTB_EXPR *ftbe; @@ -704,17 +706,19 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ weight=ftbe->cur_weight*ftbe->weight; if (mode && ftbe->phrase) { - int not_found=1; + int found= 0; memcpy(&ftsi, ftsi_orig, sizeof(ftsi)); - while (_mi_ft_segiterator(&ftsi) && not_found) + while (_mi_ft_segiterator(&ftsi) && !found) { if (!ftsi.pos) continue; - not_found = ! _ftb_check_phrase(ftb, ftsi.pos, ftsi.len, - ftbe, parser); + found= _ftb_check_phrase(ftb, ftsi.pos, ftsi.len, ftbe, parser); + if (unlikely(found < 0)) + return 1; } - if (not_found) break; + if (!found) + break; } /* ftbe->quot */ } else @@ -746,6 +750,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_ weight*= ftbe->weight; } } + return 0; } @@ -778,7 +783,11 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record) { while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0]) { - _ftb_climb_the_tree(ftb, ftbw, 0); + if (unlikely(_ftb_climb_the_tree(ftb, ftbw, 0))) + { + my_errno= HA_ERR_OUT_OF_MEM; + goto err; + } /* update queue */ _ft2_search(ftb, ftbw, 0); @@ -854,7 +863,8 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, if (ftbw->docid[1] == ftb->info->lastpos) continue; ftbw->docid[1]= ftb->info->lastpos; - _ftb_climb_the_tree(ftb, ftbw, ftb_param->ftsi); + if (unlikely(_ftb_climb_the_tree(ftb, ftbw, ftb_param->ftsi))) + return 1; } return(0); } @@ -926,7 +936,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) continue; param->doc= (byte *)ftsi.pos; param->length= ftsi.len; - parser->parse(param); + if (unlikely(parser->parse(param))) + return 0; } ftbe=ftb->root; if (ftbe->docid[1]==docid && ftbe->cur_weight>0 && diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 5c6f66897ee..2bef5238501 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -257,8 +257,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query, { info->update|= HA_STATE_AKTIV; ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY; - _mi_ft_parse(&wtree, info, keynr, record, ftparser_param, - &wtree.mem_root); + if (unlikely(_mi_ft_parse(&wtree, info, keynr, record, ftparser_param, + &wtree.mem_root))) + { + delete_queue(&best); + goto err; + } } } delete_queue(&best);