Commit 436d8402 authored by Annamalai Gurusami's avatar Annamalai Gurusami

Bug #16044655 CRASH: SETTING DEFAULT VALUE FOR SOME VARIABLES

Problem:

When a system variable is being set to the DEFAULT value, the server
segfaults if there is no 'default' defined for that system variable.
For example, for the following statements server segfaults.

set session rand_seed1=DEFAULT;
set session rand_seed2=DEFAULT;

Analysis:

The class sys_var represents one system variable.  The class set_var represents
one system variable that is to be updated.   The class set_var contains two 
pieces of information, the system variable to object (set_var::var) member
and the value to be updated (set_var::value).

When the given value is 'default', the set_var::value will be NULL.

To update a system variable the member set_var::update() will be called, 
which in turn will call sys_var::update() or sys_var::set_default() depending
on whether a value has been provided or not.  

If the sys_var::set_default() is called, then the default value is obtained
either from the session scope or the global scope.  This default value is
stored in a local temporary set_var object and then passed on to the 
sys_var::update() call.  A local temporary set_var object is needed because
sys_var::set_default() does not take set_var as an argument.

In the given scenario, the set_var::update() called sys_var::set_default().
And this sys_var::set_default() obtains the default value and then calls
sys_var::update().  To pass this value to sys_var::update() a local set_var
object is being created.   While creating this local set_var object, its member
set_var::var was incorrectly left as 0.  

Solution:

Instead of creating a local set_var object, the sys_var::set_default() can take
the set_var object as an argument just like sys_var::update().

rb://1996 approved by Nirbhay and Ramil.
parent b8957f54
/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. /* Copyright (c) 2002, 2013 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -256,17 +256,14 @@ uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) ...@@ -256,17 +256,14 @@ uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
return session_value_ptr(thd, base); return session_value_ptr(thd, base);
} }
bool sys_var::set_default(THD *thd, enum_var_type type) bool sys_var::set_default(THD *thd, set_var* var)
{ {
LEX_STRING empty={0,0}; if (var->type == OPT_GLOBAL || scope() == GLOBAL)
set_var var(type, 0, &empty, 0); global_save_default(thd, var);
if (type == OPT_GLOBAL || scope() == GLOBAL)
global_save_default(thd, &var);
else else
session_save_default(thd, &var); session_save_default(thd, var);
return check(thd, &var) || update(thd, &var); return check(thd, var) || update(thd, var);
} }
void sys_var::do_deprecated_warning(THD *thd) void sys_var::do_deprecated_warning(THD *thd)
...@@ -668,7 +665,7 @@ int set_var::light_check(THD *thd) ...@@ -668,7 +665,7 @@ int set_var::light_check(THD *thd)
*/ */
int set_var::update(THD *thd) int set_var::update(THD *thd)
{ {
return value ? var->update(thd, this) : var->set_default(thd, type); return value ? var->update(thd, this) : var->set_default(thd, this);
} }
......
#ifndef SET_VAR_INCLUDED #ifndef SET_VAR_INCLUDED
#define SET_VAR_INCLUDED #define SET_VAR_INCLUDED
/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. /* Copyright (c) 2002, 2013 Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -107,7 +107,13 @@ public: ...@@ -107,7 +107,13 @@ public:
bool check(THD *thd, set_var *var); bool check(THD *thd, set_var *var);
uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
bool set_default(THD *thd, enum_var_type type);
/**
Update the system variable with the default value from either
session or global scope. The default value is stored in the
'var' argument. Return false when successful.
*/
bool set_default(THD *thd, set_var *var);
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
SHOW_TYPE show_type() { return show_val_type; } SHOW_TYPE show_type() { return show_val_type; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment