MDEV-23841: Memory leak in innodb_monitor_validate()
innodb_monitor_validate(): Let item_val_str() allocate the memory in THD, so that it will be available to innodb_monitor_update(). In this way, there is no need to allocate another buffer, and no problem if the call to innodb_monitor_update() is skipped due to an invalid value that is passed to another configuration parameter. There are some other callers to st_mysql_sys_var::val_str() that validate configuration parameters that are related to FULLTEXT INDEX, but they will allocate memory by invoking thd_strmake().
This commit is contained in:
parent
5299f0c45e
commit
65c99207e0
@ -637,6 +637,8 @@ LIKE 'buffer_page_written_index_leaf';
|
|||||||
NAME COUNT > 0
|
NAME COUNT > 0
|
||||||
buffer_page_written_index_leaf 0
|
buffer_page_written_index_leaf 0
|
||||||
SET GLOBAL innodb_monitor_enable='%';
|
SET GLOBAL innodb_monitor_enable='%';
|
||||||
|
SET GLOBAL innodb_monitor_reset_all= '%', innodb_compression_algorithm= foo;
|
||||||
|
ERROR 42000: Variable 'innodb_compression_algorithm' can't be set to the value of 'foo'
|
||||||
INSERT INTO t1 VALUES (5), (6), (7), (8);
|
INSERT INTO t1 VALUES (5), (6), (7), (8);
|
||||||
FLUSH TABLES t1 FOR EXPORT;
|
FLUSH TABLES t1 FOR EXPORT;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
@ -408,6 +408,8 @@ SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
|||||||
LIKE 'buffer_page_written_index_leaf';
|
LIKE 'buffer_page_written_index_leaf';
|
||||||
|
|
||||||
SET GLOBAL innodb_monitor_enable='%';
|
SET GLOBAL innodb_monitor_enable='%';
|
||||||
|
--error ER_WRONG_VALUE_FOR_VAR
|
||||||
|
SET GLOBAL innodb_monitor_reset_all= '%', innodb_compression_algorithm= foo;
|
||||||
INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT;
|
INSERT INTO t1 VALUES (5), (6), (7), (8); FLUSH TABLES t1 FOR EXPORT;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
|
@ -17808,13 +17808,7 @@ innodb_monitor_validate_wildcard_name(
|
|||||||
Validate the passed in monitor name, find and save the
|
Validate the passed in monitor name, find and save the
|
||||||
corresponding monitor name in the function parameter "save".
|
corresponding monitor name in the function parameter "save".
|
||||||
@return 0 if monitor name is valid */
|
@return 0 if monitor name is valid */
|
||||||
static
|
static int innodb_monitor_valid_byname(const char *name)
|
||||||
int
|
|
||||||
innodb_monitor_valid_byname(
|
|
||||||
/*========================*/
|
|
||||||
void* save, /*!< out: immediate result
|
|
||||||
for update function */
|
|
||||||
const char* name) /*!< in: incoming monitor name */
|
|
||||||
{
|
{
|
||||||
ulint use;
|
ulint use;
|
||||||
monitor_info_t* monitor_info;
|
monitor_info_t* monitor_info;
|
||||||
@ -17862,9 +17856,6 @@ innodb_monitor_valid_byname(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the configure name for innodb_monitor_update() */
|
|
||||||
*static_cast<const char**>(save) = name;
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
@ -17880,41 +17871,18 @@ innodb_monitor_validate(
|
|||||||
for update function */
|
for update function */
|
||||||
struct st_mysql_value* value) /*!< in: incoming string */
|
struct st_mysql_value* value) /*!< in: incoming string */
|
||||||
{
|
{
|
||||||
const char* name;
|
int ret= 0;
|
||||||
char* monitor_name;
|
|
||||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
|
||||||
int len = sizeof(buff);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ut_a(save != NULL);
|
if (const char *name= value->val_str(value, nullptr, &ret))
|
||||||
ut_a(value != NULL);
|
{
|
||||||
|
ret= innodb_monitor_valid_byname(name);
|
||||||
|
if (!ret)
|
||||||
|
*static_cast<const char**>(save)= name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret= 1;
|
||||||
|
|
||||||
name = value->val_str(value, buff, &len);
|
return ret;
|
||||||
|
|
||||||
/* monitor_name could point to memory from MySQL
|
|
||||||
or buff[]. Always dup the name to memory allocated
|
|
||||||
by InnoDB, so we can access it in another callback
|
|
||||||
function innodb_monitor_update() and free it appropriately */
|
|
||||||
if (name) {
|
|
||||||
monitor_name = my_strdup(//PSI_INSTRUMENT_ME,
|
|
||||||
name, MYF(0));
|
|
||||||
} else {
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = innodb_monitor_valid_byname(save, monitor_name);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
/* Validation failed */
|
|
||||||
my_free(monitor_name);
|
|
||||||
} else {
|
|
||||||
/* monitor_name will be freed in separate callback function
|
|
||||||
innodb_monitor_update(). Assert "save" point to
|
|
||||||
the "monitor_name" variable */
|
|
||||||
ut_ad(*static_cast<char**>(save) == monitor_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -17930,11 +17898,9 @@ innodb_monitor_update(
|
|||||||
formal string goes */
|
formal string goes */
|
||||||
const void* save, /*!< in: immediate result
|
const void* save, /*!< in: immediate result
|
||||||
from check function */
|
from check function */
|
||||||
mon_option_t set_option, /*!< in: the set option,
|
mon_option_t set_option) /*!< in: the set option,
|
||||||
whether to turn on/off or
|
whether to turn on/off or
|
||||||
reset the counter */
|
reset the counter */
|
||||||
ibool free_mem) /*!< in: whether we will
|
|
||||||
need to free the memory */
|
|
||||||
{
|
{
|
||||||
monitor_info_t* monitor_info;
|
monitor_info_t* monitor_info;
|
||||||
ulint monitor_id;
|
ulint monitor_id;
|
||||||
@ -18018,12 +17984,6 @@ exit:
|
|||||||
sql_print_warning("InnoDB: Monitor %s is already enabled.",
|
sql_print_warning("InnoDB: Monitor %s is already enabled.",
|
||||||
srv_mon_get_name((monitor_id_t) err_monitor));
|
srv_mon_get_name((monitor_id_t) err_monitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (free_mem && name) {
|
|
||||||
my_free((void*) name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
@ -18114,7 +18074,7 @@ innodb_enable_monitor_update(
|
|||||||
const void* save) /*!< in: immediate result
|
const void* save) /*!< in: immediate result
|
||||||
from check function */
|
from check function */
|
||||||
{
|
{
|
||||||
innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON, TRUE);
|
innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -18131,7 +18091,7 @@ innodb_disable_monitor_update(
|
|||||||
const void* save) /*!< in: immediate result
|
const void* save) /*!< in: immediate result
|
||||||
from check function */
|
from check function */
|
||||||
{
|
{
|
||||||
innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF, TRUE);
|
innodb_monitor_update(thd, var_ptr, save, MONITOR_TURN_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -18149,7 +18109,7 @@ innodb_reset_monitor_update(
|
|||||||
const void* save) /*!< in: immediate result
|
const void* save) /*!< in: immediate result
|
||||||
from check function */
|
from check function */
|
||||||
{
|
{
|
||||||
innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE, TRUE);
|
innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
@ -18167,8 +18127,7 @@ innodb_reset_all_monitor_update(
|
|||||||
const void* save) /*!< in: immediate result
|
const void* save) /*!< in: immediate result
|
||||||
from check function */
|
from check function */
|
||||||
{
|
{
|
||||||
innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE,
|
innodb_monitor_update(thd, var_ptr, save, MONITOR_RESET_ALL_VALUE);
|
||||||
TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -18213,10 +18172,9 @@ innodb_enable_monitor_at_startup(
|
|||||||
for (char* option = my_strtok_r(str, sep, &last);
|
for (char* option = my_strtok_r(str, sep, &last);
|
||||||
option;
|
option;
|
||||||
option = my_strtok_r(NULL, sep, &last)) {
|
option = my_strtok_r(NULL, sep, &last)) {
|
||||||
char* option_name;
|
if (!innodb_monitor_valid_byname(option)) {
|
||||||
if (!innodb_monitor_valid_byname(&option_name, option)) {
|
|
||||||
innodb_monitor_update(NULL, NULL, &option,
|
innodb_monitor_update(NULL, NULL, &option,
|
||||||
MONITOR_TURN_ON, FALSE);
|
MONITOR_TURN_ON);
|
||||||
} else {
|
} else {
|
||||||
sql_print_warning("Invalid monitor counter"
|
sql_print_warning("Invalid monitor counter"
|
||||||
" name: '%s'", option);
|
" name: '%s'", option);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user