diff options
author | Annamalai Gurusami <annamalai.gurusami@oracle.com> | 2013-02-25 10:28:25 +0530 |
---|---|---|
committer | Annamalai Gurusami <annamalai.gurusami@oracle.com> | 2013-02-25 10:28:25 +0530 |
commit | 436d8402a15d7b84de620ab68f73abfc565018b4 (patch) | |
tree | 826e64adde291328bd8925d68b94b1d2dcbfdf1d /sql/set_var.cc | |
parent | b8957f542f988da889c617b57a354741867eca6d (diff) | |
download | mariadb-git-436d8402a15d7b84de620ab68f73abfc565018b4.tar.gz |
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.
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r-- | sql/set_var.cc | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc index 231fbb47d35..75387b974f1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1,4 +1,4 @@ -/* 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 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) 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}; - set_var var(type, 0, &empty, 0); - - if (type == OPT_GLOBAL || scope() == GLOBAL) - global_save_default(thd, &var); + if (var->type == OPT_GLOBAL || scope() == GLOBAL) + global_save_default(thd, var); 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) @@ -668,7 +665,7 @@ int set_var::light_check(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); } |