Fix memory leaks in maxinfo (modified for 2.0 and develop-branch)

MXS-1009. This commit adds a gwbuf_free after maxinfo_execute() to
free a buffer with an sql-query after it has been processed. Also,
the parse tree in maxinfo_execute_query() is now freed. The tree_free-
function was renamed to maxinfo_tree_free, since it is now globally
available.

This commit has additional changes (in relation to the 1.4.4 branch)
to remove errors caused by differences in the html and sql-sides of
MaxInfo.
This commit is contained in:
ekorh475
2016-11-25 12:53:15 +02:00
parent 0bc68742a6
commit cc54d80a8b
4 changed files with 186 additions and 156 deletions

View File

@ -132,6 +132,7 @@ typedef enum
extern MAXINFO_TREE *maxinfo_parse(char *, PARSE_ERROR *);
extern void maxinfo_free_tree(MAXINFO_TREE *);
extern void maxinfo_execute(DCB *, MAXINFO_TREE *);
extern void maxinfo_send_error(DCB *, int, char *);
extern void maxinfo_send_parse_error(DCB *, char *, PARSE_ERROR);

View File

@ -335,11 +335,11 @@ static void handleError(
static int
execute(ROUTER *rinstance, void *router_session, GWBUF *queue)
{
INFO_INSTANCE *instance = (INFO_INSTANCE *)rinstance;
INFO_SESSION *session = (INFO_SESSION *)router_session;
uint8_t *data;
int length, len, residual;
char *sql;
INFO_INSTANCE *instance = (INFO_INSTANCE *)rinstance;
INFO_SESSION *session = (INFO_SESSION *)router_session;
uint8_t *data;
int length, len, residual;
char *sql;
if (GWBUF_TYPE(queue) == GWBUF_TYPE_HTTP)
{
@ -360,29 +360,35 @@ char *sql;
return 1;
}
// We have a complete request in a signle buffer
int rc = 1;
// We have a complete request in a single buffer
if (modutil_MySQL_Query(queue, &sql, &len, &residual))
{
sql = strndup(sql, len);
int rc = maxinfo_execute_query(instance, session, sql);
rc = maxinfo_execute_query(instance, session, sql);
free(sql);
return rc;
}
else
{
switch (MYSQL_COMMAND(queue))
{
case COM_PING:
return maxinfo_ping(instance, session, queue);
rc = maxinfo_ping(instance, session, queue);
break;
case COM_STATISTICS:
return maxinfo_statistics(instance, session, queue);
rc = maxinfo_statistics(instance, session, queue);
break;
case COM_QUIT:
break;
default:
MXS_ERROR("maxinfo: Unexpected MySQL command 0x%x",
MYSQL_COMMAND(queue));
break;
}
}
return 1;
// MaxInfo doesn't route the data forward so it should be freed.
gwbuf_free(queue);
return rc;
}
/**
@ -601,8 +607,8 @@ uint8_t *ptr;
static int
maxinfo_execute_query(INFO_INSTANCE *instance, INFO_SESSION *session, char *sql)
{
MAXINFO_TREE *tree;
PARSE_ERROR err;
MAXINFO_TREE *tree;
PARSE_ERROR err;
MXS_INFO("maxinfo: SQL statement: '%s' for 0x%p.",
sql, session->dcb);
@ -644,7 +650,10 @@ PARSE_ERROR err;
MXS_NOTICE("Failed to parse SQL statement: '%s'.", sql);
}
else
{
maxinfo_execute(session->dcb, tree);
maxinfo_free_tree(tree);
}
return 1;
}

View File

@ -882,21 +882,27 @@ static void
exec_show_variables(DCB *dcb, MAXINFO_TREE *filter)
{
RESULTSET *result;
VARCONTEXT context;
VARCONTEXT *context;
if ((context = malloc(sizeof(VARCONTEXT))) == NULL)
{
return;
}
if (filter)
{
context.like = filter->value;
context->like = filter->value;
}
else
{
context.like = NULL;
context->like = NULL;
}
context.index = 0;
context->index = 0;
if ((result = resultset_create(variable_row, &context)) == NULL)
if ((result = resultset_create(variable_row, context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
free(context);
return;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
@ -1168,21 +1174,27 @@ static void
exec_show_status(DCB *dcb, MAXINFO_TREE *filter)
{
RESULTSET *result;
VARCONTEXT context;
VARCONTEXT *context;
if ((context = malloc(sizeof(VARCONTEXT))) == NULL)
{
return;
}
if (filter)
{
context.like = filter->value;
context->like = filter->value;
}
else
{
context.like = NULL;
context->like = NULL;
}
context.index = 0;
context->index = 0;
if ((result = resultset_create(status_row, &context)) == NULL)
if ((result = resultset_create(status_row, context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
free(context);
return;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);

View File

@ -41,7 +41,7 @@
#include <log_manager.h>
static MAXINFO_TREE *make_tree_node(MAXINFO_OPERATOR, char *, MAXINFO_TREE *, MAXINFO_TREE *);
static void free_tree(MAXINFO_TREE *);
void maxinfo_free_tree(MAXINFO_TREE *); // This function is needed by maxinfo.c
static char *fetch_token(char *, int *, char **);
static MAXINFO_TREE *parse_column_list(char **sql);
static MAXINFO_TREE *parse_table_name(char **sql);
@ -78,7 +78,9 @@ MAXINFO_TREE *col, *table;
}
tree = make_tree_node(MAXOP_SHOW, text, NULL, NULL);
if ((ptr = fetch_token(ptr, &token, &text)) == NULL)
{
return tree;
}
else if (token == LT_LIKE)
{
if ((ptr = fetch_token(ptr, &token, &text)) != NULL)
@ -91,13 +93,13 @@ MAXINFO_TREE *col, *table;
{
// Expected expression
*parse_error = PARSE_EXPECTED_LIKE;
free_tree(tree);
maxinfo_free_tree(tree);
return NULL;
}
}
// Malformed show
free(text);
free_tree(tree);
maxinfo_free_tree(tree);
*parse_error = PARSE_MALFORMED_SHOW;
return NULL;
#if 0
@ -128,7 +130,7 @@ MAXINFO_TREE *col, *table;
{
/** Unknown token after SHUTDOWN MONITOR|SERVICE */
*parse_error = PARSE_SYNTAX_ERROR;
free_tree(tree);
maxinfo_free_tree(tree);
return NULL;
}
return tree;
@ -142,7 +144,7 @@ MAXINFO_TREE *col, *table;
{
/** Missing token for RESTART MONITOR|SERVICE */
*parse_error = PARSE_SYNTAX_ERROR;
free_tree(tree);
maxinfo_free_tree(tree);
return NULL;
}
tree->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL);
@ -152,7 +154,7 @@ MAXINFO_TREE *col, *table;
/** Unknown token after RESTART MONITOR|SERVICE */
*parse_error = PARSE_SYNTAX_ERROR;
free(text);
free_tree(tree);
maxinfo_free_tree(tree);
return NULL;
}
return tree;
@ -270,19 +272,25 @@ MAXINFO_TREE *node;
}
/**
* Recusrsively free the storage associated with a parse tree
* Recursively free the storage associated with a parse tree
*
* @param tree The parse tree to free
*/
static void
free_tree(MAXINFO_TREE *tree)
void
maxinfo_free_tree(MAXINFO_TREE *tree)
{
if (tree->left)
free_tree(tree->left);
{
maxinfo_free_tree(tree->left);
}
if (tree->right)
free_tree(tree->right);
{
maxinfo_free_tree(tree->right);
}
if (tree->value)
{
free(tree->value);
}
free(tree);
}
@ -410,8 +418,8 @@ MAXINFO_TREE* maxinfo_parse_literals(MAXINFO_TREE *tree, int min_args, char *ptr
(node->right = make_tree_node(MAXOP_LITERAL, text, NULL, NULL)) == NULL)
{
*parse_error = PARSE_SYNTAX_ERROR;
free_tree(tree);
if(ptr)
maxinfo_free_tree(tree);
if (ptr)
{
free(text);
}