summaryrefslogtreecommitdiff
path: root/sql/set_var.cc
diff options
context:
space:
mode:
authorAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-02-25 10:28:25 +0530
committerAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-02-25 10:28:25 +0530
commit436d8402a15d7b84de620ab68f73abfc565018b4 (patch)
tree826e64adde291328bd8925d68b94b1d2dcbfdf1d /sql/set_var.cc
parentb8957f542f988da889c617b57a354741867eca6d (diff)
downloadmariadb-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.cc17
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);
}