Description:
I have NOT tested with next-mr.
If a session variable accepts multiple flags, like @@optimizer_switch does
(set optimizer_switch=index_merge=off,loosescan=on,etc), and one of the possible flags starts with "on", then
set the_variable=on;
will crash.
The crash doesn't occur in a stock version, but it will, the day we add a new flag to @@optimizer_switch and it starts with "on".
This bug was found while developing WL#4800 "optimizer trace", where a multi-flag session variable @@optimizer_trace is added and has one flag named "one_line" (so, starting with "on").
Stack trace:
#4 0x00007f91b8a5cef4 in strcpy () from /lib/libc.so.6
#5 0x0000000000ac898a in find_type (x=0xbb4c23 "ON", typelib=0x12802b8, full_name=8) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/mysys/typelib.c:120
#6 0x0000000000ac8e46 in parse_name (lib=0x12802b8, strpos=0x7f91ba0db410, end=0xbb4c25 "") at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/mysys/typelib.c:279
#7 0x0000000000ac8f14 in find_set_from_flags (lib=0x12802b8, default_name=13, cur_set=3071, default_set=3071, str=0xbb4c23 "ON", length=2, err_pos=0x7f91ba0db4c8, err_len=0x7f91ba0db4ec)
at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/mysys/typelib.c:338
#8 0x0000000000735647 in Sys_var_flagset::do_check (this=0x12801e0, thd=0x181d520, var=0x1775dd8) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/sql/sys_vars.h:892
#9 0x0000000000595e97 in sys_var::check (this=0x12801e0, thd=0x181d520, var=0x1775dd8) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/sql/set_var.cc:216
#10 0x0000000000596d64 in set_var::check (this=0x1775dd8, thd=0x181d520) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/sql/set_var.cc:616
#11 0x0000000000596a63 in sql_set_variables (thd=0x181d520, var_list=0x181fc10) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/sql/set_var.cc:560
#12 0x000000000061a533 in mysql_execute_command (thd=0x181d520) at /m/bzrrepos/mysql-6.0-codebase-bugfixing2/sql/sql_parse.cc:3728
How to repeat:
take 6.0-codebase-bugfixing (haven't tested with next-mr), modify sys_vars.cc like this:
static const char *optimizer_switch_names[]=
{
"ondex_merge", (keep the rest unchanged)
recompile and do
set optimizer_switch=on;
Suggested fix:
Note that I can work around it in the WL#4800 feature tree (using another name than "one_line" for the new flag).
The problem's analysis:
when the parser parses the =ON clause (sql_yacc.yy):
set_expr_or_default:
expr { $$=$1; }
| DEFAULT { $$=0; }
| ON
{
$$= new (YYTHD->mem_root) Item_string("ON", 2,
system_charset_info);
this constructor calls:
Item_string(const char *str,uint length,
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE,
uint repertoire= MY_REPERTOIRE_UNICODE30)
: m_cs_specified(FALSE)
{
str_value.set_or_copy_aligned(str, length, cs);
which does a "set" (not copy): it makes str_value.Ptr be == the address of the
static char array "ON".
This str_value is "res" in sys_var_flagset::do_check():
var->save_result.ulonglong_value=
find_set_from_flags(&typelib,
typelib.count,
current_value,
default_value,
res->ptr(), res->length(),
&error, &error_len);
this function calls parse_name(), which calls find_type(), and because
"ON" is a prefix of one allowed flag ("one_line") we come to this in
find_type() (we found a partial match and we expand it in-line in the input string):
if (!(full_name & 2))
(void) strmov(x,typelib->type_names[findpos]);
which is incorrect as x is a static char array (segfault).
Note this guilty cast of "strpos" removing "const":
static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end)
{
const char *pos= *strpos;
uint find= find_type((char*)pos, lib, 8);
^^^^^^
If we didn't have this, the guilty strmov() would not compile...
This bug was probably introduced between
alik@sun.com-20100322131724-a0hybweujmt4ejx1 and
alfranio.correia@sun.com-20100426092226-bnkzpjs8uqkl7l16 .
The fix which I'm using in my tree is to replace 8 above by 2|8. It instructs find_type() to not change the content of "pos" (don't expand a partial match). Changing the content of "pos" looks quite wrong anyway because it may change
var=on=on,other=off
to
var=onlineother=off .