From f1042103e619330f5b1fdd11faed7d07c79df49f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Jan 2008 16:05:15 -0800 Subject: Bug#33358 "Plugin enum variables can't be set from command line" fix crash of LOCK_plugins mutex when loading plug-ins from command line. fix off-by-one bug when loading multiple plug-ins from the command line. initialize command line handling for ENUM and SET plugin variable types. sql/sql_plugin.cc: Bug33358 fix crash of LOCK_plugins mutex when loading plug-ins from command line. fix off-by-one bug when loading multiple plug-ins from the command line. initialize command line handling for ENUM and SET plugin variable types. mysql-test/r/plugin_load.result: New BitKeeper file ``mysql-test/r/plugin_load.result'' mysql-test/t/plugin_load-master.opt: New BitKeeper file ``mysql-test/t/plugin_load-master.opt'' mysql-test/t/plugin_load.test: New BitKeeper file ``mysql-test/t/plugin_load.test'' --- sql/sql_plugin.cc | 66 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 18 deletions(-) (limited to 'sql/sql_plugin.cc') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2a86844c8c6..8e204eb3d51 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1412,7 +1412,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, while (list) { if (p == buffer + sizeof(buffer) - 1) - break; + { + sql_print_error("plugin-load parameter too long"); + DBUG_RETURN(TRUE); + } + switch ((*(p++)= *(list++))) { case '\0': list= NULL; /* terminate the loop */ @@ -1421,10 +1425,17 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, case ':': /* can't use this as delimiter as it may be drive letter */ #endif case ';': - name.str[name.length]= '\0'; - if (str != &dl) // load all plugins in named module + str->str[str->length]= '\0'; + if (str == &name) // load all plugins in named module { + if (!name.length) + { + p--; /* reset pointer */ + continue; + } + dl= name; + pthread_mutex_lock(&LOCK_plugin); if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG))) { for (plugin= plugin_dl->plugins; plugin->info; plugin++) @@ -1434,7 +1445,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + { + pthread_mutex_unlock(&LOCK_plugin); goto error; + } } plugin_dl_del(&dl); // reduce ref count } @@ -1442,9 +1456,14 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, else { free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + pthread_mutex_lock(&LOCK_plugin); if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + { + pthread_mutex_unlock(&LOCK_plugin); goto error; + } } + pthread_mutex_unlock(&LOCK_plugin); name.length= dl.length= 0; dl.str= NULL; name.str= p= buffer; str= &name; @@ -1453,6 +1472,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, case '#': if (str == &name) { + name.str[name.length]= '\0'; str= &dl; str->str= p; continue; @@ -2999,7 +3019,8 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_RETURN(-1); } - if (opt->flags & PLUGIN_VAR_NOCMDOPT) + if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL)) + == PLUGIN_VAR_NOCMDOPT) continue; if (!opt->name) @@ -3009,7 +3030,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_RETURN(-1); } - if (!(v= find_bookmark(name, opt->name, opt->flags))) + if (!(opt->flags & PLUGIN_VAR_THDLOCAL)) { optnamelen= strlen(opt->name); optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2); @@ -3017,7 +3038,23 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, optnamelen= namelen + optnamelen + 1; } else - optname= (char*) memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1); + { + /* this should not fail because register_var should create entry */ + if (!(v= find_bookmark(name, opt->name, opt->flags))) + { + sql_print_error("Thread local variable '%s' not allocated " + "in plugin '%s'.", opt->name, plugin_name); + DBUG_RETURN(-1); + } + + *(int*)(opt + 1)= offset= v->offset; + + if (opt->flags & PLUGIN_VAR_NOCMDOPT) + continue; + + optname= (char*) memdup_root(mem_root, v->key + 1, + (optnamelen= v->name_len) + 1); + } /* convert '_' to '-' */ for (p= optname; *p; p++) @@ -3029,20 +3066,13 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, options->app_type= opt; options->id= (options-1)->id + 1; - if (opt->flags & PLUGIN_VAR_THDLOCAL) - *(int*)(opt + 1)= offset= v->offset; - plugin_opt_set_limits(options, opt); - if ((opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM && - (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET) - { - if (opt->flags & PLUGIN_VAR_THDLOCAL) - options->value= options->u_max_value= (uchar**) - (global_system_variables.dynamic_variables_ptr + offset); - else - options->value= options->u_max_value= *(uchar***) (opt + 1); - } + if (opt->flags & PLUGIN_VAR_THDLOCAL) + options->value= options->u_max_value= (uchar**) + (global_system_variables.dynamic_variables_ptr + offset); + else + options->value= options->u_max_value= *(uchar***) (opt + 1); options[1]= options[0]; options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8); -- cgit v1.2.1 From 70884e09b8d10088da4598aaf0b8ebe04e6a97b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Jan 2008 02:13:35 -0800 Subject: fixes to make pushbuild tests green mysql-test/t/plugin_load-master.opt: add '--loose' modifier to allow test to be skipped if plugin is not available. sql/sql_plugin.cc: Failure to load a plugin from command line option made non-fatal as plugin load failures from plugin table is already non-fatal. --- sql/sql_plugin.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sql/sql_plugin.cc') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 8e204eb3d51..bae4a85fd8a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1181,9 +1181,8 @@ int plugin_init(int *argc, char **argv, int flags) /* Register all dynamic plugins */ if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING)) { - if (opt_plugin_load && - plugin_load_list(&tmp_root, argc, argv, opt_plugin_load)) - goto err; + if (opt_plugin_load) + plugin_load_list(&tmp_root, argc, argv, opt_plugin_load); if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE)) plugin_load(&tmp_root, argc, argv); } -- cgit v1.2.1 From a1915039e8e202c705b6cde961fd2fb95fa84901 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Feb 2008 12:55:13 -0800 Subject: Bug#34598 "crash on hpita: Invalid address alignment" Replace dangerous pointer arithmetic - it may occurr where sizeof(int) is less than size of machine alignment requirement. include/mysql/plugin.h: bug34598 change of update func prototype sql/sql_plugin.cc: bug34598 Avoid dangerous pointer arithmetic which can cause unaligned word access. Change of update function prototype --- sql/sql_plugin.cc | 56 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 15 deletions(-) (limited to 'sql/sql_plugin.cc') diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2a86844c8c6..ede326457f5 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2069,35 +2069,35 @@ err: static void update_func_bool(THD *thd, struct st_mysql_sys_var *var, - void *tgt, void *save) + void *tgt, const void *save) { *(my_bool *) tgt= *(int *) save ? 1 : 0; } static void update_func_int(THD *thd, struct st_mysql_sys_var *var, - void *tgt, void *save) + void *tgt, const void *save) { *(int *)tgt= *(int *) save; } static void update_func_long(THD *thd, struct st_mysql_sys_var *var, - void *tgt, void *save) + void *tgt, const void *save) { *(long *)tgt= *(long *) save; } static void update_func_longlong(THD *thd, struct st_mysql_sys_var *var, - void *tgt, void *save) + void *tgt, const void *save) { *(longlong *)tgt= *(ulonglong *) save; } static void update_func_str(THD *thd, struct st_mysql_sys_var *var, - void *tgt, void *save) + void *tgt, const void *save) { char *old= *(char **) tgt; *(char **)tgt= *(char **) save; @@ -2654,7 +2654,8 @@ bool sys_var_pluginvar::check(THD *thd, set_var *var) void sys_var_pluginvar::set_default(THD *thd, enum_var_type type) { - void *tgt, *src; + const void *src; + void *tgt; DBUG_ASSERT(is_readonly() || plugin_var->update); @@ -2667,9 +2668,34 @@ void sys_var_pluginvar::set_default(THD *thd, enum_var_type type) if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) { - src= ((int*) (plugin_var + 1) + 1); if (type != OPT_GLOBAL) src= real_value_ptr(thd, OPT_GLOBAL); + else + switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_INT: + src= &((thdvar_uint_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONG: + src= &((thdvar_ulong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONGLONG: + src= &((thdvar_ulonglong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_ENUM: + src= &((thdvar_enum_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_SET: + src= &((thdvar_set_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_BOOL: + src= &((thdvar_bool_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_STR: + src= &((thdvar_str_t*) plugin_var)->def_val; + break; + default: + DBUG_ASSERT(0); + } } /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */ @@ -2757,25 +2783,25 @@ static void plugin_opt_set_limits(struct my_option *options, case PLUGIN_VAR_ENUM: options->var_type= GET_ENUM; options->typelib= ((sysvar_enum_t*) opt)->typelib; - options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->def_value= ((sysvar_enum_t*) opt)->def_val; options->min_value= options->block_size= 0; options->max_value= options->typelib->count - 1; break; case PLUGIN_VAR_SET: options->var_type= GET_SET; options->typelib= ((sysvar_set_t*) opt)->typelib; - options->def_value= *(ulonglong*) ((int*) (opt + 1) + 1); + options->def_value= ((sysvar_set_t*) opt)->def_val; options->min_value= options->block_size= 0; options->max_value= (ULL(1) << options->typelib->count) - 1; break; case PLUGIN_VAR_BOOL: options->var_type= GET_BOOL; - options->def_value= *(my_bool*) ((void**)(opt + 1) + 1); + options->def_value= ((sysvar_bool_t*) opt)->def_val; break; case PLUGIN_VAR_STR: options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ? GET_STR_ALLOC : GET_STR); - options->def_value= (ulonglong)(intptr) *((char**) ((void**) (opt + 1) + 1)); + options->def_value= (intptr) ((sysvar_str_t*) opt)->def_val; break; /* threadlocal variables */ case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL: @@ -2799,25 +2825,25 @@ static void plugin_opt_set_limits(struct my_option *options, case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL: options->var_type= GET_ENUM; options->typelib= ((thdvar_enum_t*) opt)->typelib; - options->def_value= *(ulong*) ((int*) (opt + 1) + 1); + options->def_value= ((thdvar_enum_t*) opt)->def_val; options->min_value= options->block_size= 0; options->max_value= options->typelib->count - 1; break; case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL: options->var_type= GET_SET; options->typelib= ((thdvar_set_t*) opt)->typelib; - options->def_value= *(ulonglong*) ((int*) (opt + 1) + 1); + options->def_value= ((thdvar_set_t*) opt)->def_val; options->min_value= options->block_size= 0; options->max_value= (ULL(1) << options->typelib->count) - 1; break; case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL: options->var_type= GET_BOOL; - options->def_value= *(my_bool*) ((int*) (opt + 1) + 1); + options->def_value= ((thdvar_bool_t*) opt)->def_val; break; case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL: options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ? GET_STR_ALLOC : GET_STR); - options->def_value= (intptr) *((char**) ((void**) (opt + 1) + 1)); + options->def_value= (intptr) ((thdvar_str_t*) opt)->def_val; break; default: DBUG_ASSERT(0); -- cgit v1.2.1