Commit c4fa6a38 authored by Tatiana A. Nurnberg's avatar Tatiana A. Nurnberg

Bug#43233: Some server variables are clipped during "update," not "check" stage

Bug#55794: ulonglong options of mysqld show wrong values.

Port the few remaining system variables to the correct mechanism --
range-check in check-stage (and throw error or warning at that point
as needed and depending on STRICTness), update in update stage.
Fix some signedness errors when retrieving sysvar values for display.

mysql-test/r/variables.result:
  Show that we throw warnings or errors depending on strictness
  even for "special" variables now.
mysql-test/t/variables.test:
  Show that we throw warnings or errors depending on strictness
  even for "special" variables now.
sql/item_func.cc:
  show sys_var_ulonglong_ptr and SHOW_LONGLONG type variables as unsigned.
sql/set_var.cc:
  move range-checking from update stage to check stage for the remaining
  few sys-vars that broke the pattern
sql/set_var.h:
  add check functions.
parent 58dfba28
...@@ -1511,4 +1511,38 @@ SELECT @@skip_name_resolve; ...@@ -1511,4 +1511,38 @@ SELECT @@skip_name_resolve;
SHOW VARIABLES LIKE 'skip_name_resolve'; SHOW VARIABLES LIKE 'skip_name_resolve';
Variable_name Value Variable_name Value
skip_name_resolve OFF skip_name_resolve OFF
#
# Bug #43233 : Some server variables are clipped during "update,"
# not "check" stage
#
SET @kbs=@@global.key_buffer_size;
SET @kcbs=@@global.key_cache_block_size;
throw errors in STRICT mode
SET SQL_MODE=STRICT_ALL_TABLES;
SET @@global.max_binlog_cache_size=-1;
ERROR 42000: Variable 'max_binlog_cache_size' can't be set to the value of '-1'
SET @@global.max_join_size=0;
ERROR 42000: Variable 'max_join_size' can't be set to the value of '0'
SET @@global.key_buffer_size=0;
ERROR 42000: Variable 'key_buffer_size' can't be set to the value of '0'
SET @@global.key_cache_block_size=0;
ERROR 42000: Variable 'key_cache_block_size' can't be set to the value of '0'
throw warnings in default mode
SET SQL_MODE=DEFAULT;
SET @@global.max_binlog_cache_size=-1;
Warnings:
Warning 1292 Truncated incorrect max_binlog_cache_size value: '-1'
SET @@global.max_join_size=0;
Warnings:
Warning 1292 Truncated incorrect max_join_size value: '0'
SET @@global.key_buffer_size=0;
Warnings:
Warning 1292 Truncated incorrect key_buffer_size value: '0'
SET @@global.key_cache_block_size=0;
Warnings:
Warning 1292 Truncated incorrect key_cache_block_size value: '0'
SET @@global.max_binlog_cache_size=DEFAULT;
SET @@global.max_join_size=DEFAULT;
SET @@global.key_buffer_size=@kbs;
SET @@global.key_cache_block_size=@kcbs;
End of 5.1 tests End of 5.1 tests
...@@ -1255,4 +1255,45 @@ SET GLOBAL max_binlog_cache_size = @old_max_binlog_cache_size; ...@@ -1255,4 +1255,45 @@ SET GLOBAL max_binlog_cache_size = @old_max_binlog_cache_size;
SELECT @@skip_name_resolve; SELECT @@skip_name_resolve;
SHOW VARIABLES LIKE 'skip_name_resolve'; SHOW VARIABLES LIKE 'skip_name_resolve';
--echo #
--echo # Bug #43233 : Some server variables are clipped during "update,"
--echo # not "check" stage
--echo #
SET @kbs=@@global.key_buffer_size;
SET @kcbs=@@global.key_cache_block_size;
--echo throw errors in STRICT mode
SET SQL_MODE=STRICT_ALL_TABLES;
# sys_var_ulonglong_ptr: sys_max_binlog_cache_size
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.max_binlog_cache_size=-1;
# sys_var_thd_ha_rows: "max_join_size" et al.
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.max_join_size=0;
# sys_var_key_buffer_size: "key_buffer_size"
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.key_buffer_size=0;
# sys_var_key_cache_long: "key_cache_block_size" et al.
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.key_cache_block_size=0;
--echo throw warnings in default mode
SET SQL_MODE=DEFAULT;
SET @@global.max_binlog_cache_size=-1;
SET @@global.max_join_size=0;
SET @@global.key_buffer_size=0;
SET @@global.key_cache_block_size=0;
# cleanup
SET @@global.max_binlog_cache_size=DEFAULT;
SET @@global.max_join_size=DEFAULT;
SET @@global.key_buffer_size=@kbs;
SET @@global.key_cache_block_size=@kcbs;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -4843,7 +4843,7 @@ void Item_func_get_system_var::fix_length_and_dec() ...@@ -4843,7 +4843,7 @@ void Item_func_get_system_var::fix_length_and_dec()
decimals=0; decimals=0;
break; break;
case SHOW_LONGLONG: case SHOW_LONGLONG:
unsigned_flag= FALSE; unsigned_flag= TRUE;
max_length= MY_INT64_NUM_DECIMAL_DIGITS; max_length= MY_INT64_NUM_DECIMAL_DIGITS;
decimals=0; decimals=0;
break; break;
...@@ -4984,7 +4984,7 @@ longlong Item_func_get_system_var::val_int() ...@@ -4984,7 +4984,7 @@ longlong Item_func_get_system_var::val_int()
{ {
case SHOW_INT: get_sys_var_safe (uint); case SHOW_INT: get_sys_var_safe (uint);
case SHOW_LONG: get_sys_var_safe (ulong); case SHOW_LONG: get_sys_var_safe (ulong);
case SHOW_LONGLONG: get_sys_var_safe (longlong); case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
case SHOW_HA_ROWS: get_sys_var_safe (ha_rows); case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
case SHOW_BOOL: get_sys_var_safe (bool); case SHOW_BOOL: get_sys_var_safe (bool);
case SHOW_MY_BOOL: get_sys_var_safe (my_bool); case SHOW_MY_BOOL: get_sys_var_safe (my_bool);
......
...@@ -1579,11 +1579,16 @@ void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type) ...@@ -1579,11 +1579,16 @@ void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type)
} }
bool sys_var_ulonglong_ptr::check(THD *thd, set_var *var)
{
return get_unsigned(thd, var, 0, GET_ULL);
}
bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->save_result.ulonglong_value; ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
bound_unsigned(thd, &tmp, option_limits);
*value= (ulonglong) tmp; *value= (ulonglong) tmp;
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
return 0; return 0;
...@@ -1675,25 +1680,30 @@ uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, ...@@ -1675,25 +1680,30 @@ uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
} }
bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) bool sys_var_thd_ha_rows::check(THD *thd, set_var *var)
{ {
ulonglong tmp= var->save_result.ulonglong_value; return get_unsigned(thd, var, max_system_variables.*offset,
#ifdef BIG_TABLES
/* Don't use bigger value than given with --maximum-variable-name=.. */ GET_ULL
if ((ha_rows) tmp > max_system_variables.*offset) #else
tmp= max_system_variables.*offset; GET_ULONG
#endif
);
}
bound_unsigned(thd, &tmp, option_limits);
bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL) if (var->type == OPT_GLOBAL)
{ {
/* Lock is needed to make things safe on 32 bit systems */ /* Lock is needed to make things safe on 32 bit systems */
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= (ha_rows) tmp; global_system_variables.*offset= (ha_rows)
var->save_result.ulonglong_value;
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
} }
else else
thd->variables.*offset= (ha_rows) tmp; thd->variables.*offset= (ha_rows) var->save_result.ulonglong_value;
return 0; return 0;
} }
...@@ -2305,6 +2315,12 @@ uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, ...@@ -2305,6 +2315,12 @@ uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
} }
bool sys_var_key_buffer_size::check(THD *thd, set_var *var)
{
return get_unsigned(thd, var, 0, GET_ULL);
}
bool sys_var_key_buffer_size::update(THD *thd, set_var *var) bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->save_result.ulonglong_value; ulonglong tmp= var->save_result.ulonglong_value;
...@@ -2318,10 +2334,10 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) ...@@ -2318,10 +2334,10 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
key_cache= get_key_cache(base_name); key_cache= get_key_cache(base_name);
if (!key_cache) if (!key_cache)
{ {
/* Key cache didn't exists */ /* Key cache didn't exist */
if (!tmp) // Tried to delete cache if (!tmp) // Tried to delete cache
goto end; // Ok, nothing to do goto end; // Ok, nothing to do
if (!(key_cache= create_key_cache(base_name->str, base_name->length))) if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
...@@ -2371,7 +2387,6 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) ...@@ -2371,7 +2387,6 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
goto end; goto end;
} }
bound_unsigned(thd, &tmp, option_limits);
key_cache->param_buff_size= (ulonglong) tmp; key_cache->param_buff_size= (ulonglong) tmp;
/* If key cache didn't exist initialize it, else resize it */ /* If key cache didn't exist initialize it, else resize it */
...@@ -2388,10 +2403,19 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) ...@@ -2388,10 +2403,19 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
end: end:
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
var->save_result.ulonglong_value = SIZE_T_MAX;
return error; return error;
} }
bool sys_var_key_cache_long::check(THD *thd, set_var *var)
{
return get_unsigned(thd, var, 0, GET_ULONG);
}
/** /**
@todo @todo
Abort if some other thread is changing the key cache. Abort if some other thread is changing the key cache.
...@@ -2400,7 +2424,6 @@ end: ...@@ -2400,7 +2424,6 @@ end:
*/ */
bool sys_var_key_cache_long::update(THD *thd, set_var *var) bool sys_var_key_cache_long::update(THD *thd, set_var *var)
{ {
ulonglong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base; LEX_STRING *base_name= &var->base;
bool error= 0; bool error= 0;
...@@ -2425,8 +2448,8 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) ...@@ -2425,8 +2448,8 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
if (key_cache->in_init) if (key_cache->in_init)
goto end; goto end;
bound_unsigned(thd, &tmp, option_limits); *((ulong*) (((char*) key_cache) + offset))= (ulong)
*((ulong*) (((char*) key_cache) + offset))= (ulong) tmp; var->save_result.ulonglong_value;
/* /*
Don't create a new key cache if it didn't exist Don't create a new key cache if it didn't exist
......
...@@ -196,6 +196,7 @@ public: ...@@ -196,6 +196,7 @@ public:
sys_after_update_func func) sys_after_update_func func)
:sys_var(name_arg,func), value(value_ptr_arg) :sys_var(name_arg,func), value(value_ptr_arg)
{ chain_sys_var(chain); } { chain_sys_var(chain); }
bool check(THD *thd, set_var *var);
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
SHOW_TYPE show_type() { return SHOW_LONGLONG; } SHOW_TYPE show_type() { return SHOW_LONGLONG; }
...@@ -442,6 +443,7 @@ public: ...@@ -442,6 +443,7 @@ public:
sys_after_update_func func) sys_after_update_func func)
:sys_var_thd(name_arg,func), offset(offset_arg) :sys_var_thd(name_arg,func), offset(offset_arg)
{ chain_sys_var(chain); } { chain_sys_var(chain); }
bool check(THD *thd, set_var *var);
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type); void set_default(THD *thd, enum_var_type type);
SHOW_TYPE show_type() { return SHOW_HA_ROWS; } SHOW_TYPE show_type() { return SHOW_HA_ROWS; }
...@@ -854,6 +856,7 @@ public: ...@@ -854,6 +856,7 @@ public:
:sys_var_key_cache_param(chain, name_arg, :sys_var_key_cache_param(chain, name_arg,
offsetof(KEY_CACHE, param_buff_size)) offsetof(KEY_CACHE, param_buff_size))
{} {}
bool check(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_LONGLONG; } SHOW_TYPE show_type() { return SHOW_LONGLONG; }
}; };
...@@ -865,6 +868,7 @@ public: ...@@ -865,6 +868,7 @@ public:
sys_var_key_cache_long(sys_var_chain *chain, const char *name_arg, size_t offset_arg) sys_var_key_cache_long(sys_var_chain *chain, const char *name_arg, size_t offset_arg)
:sys_var_key_cache_param(chain, name_arg, offset_arg) :sys_var_key_cache_param(chain, name_arg, offset_arg)
{} {}
bool check(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_LONG; } SHOW_TYPE show_type() { return SHOW_LONG; }
}; };
......
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