Commit c163b8c6 authored by Yuchen Pei's avatar Yuchen Pei

MDEV-31117 clean up spider connection info parsing

Spider connection string is a comma-separated parameter definitions,
where each definition is of the form "<param_title> <param_value>",
where <param_value> is quote delimited on both ends, with backslashes
acting as an escaping prefix.

The code however treated param title the same way as param value when
assigning, and have nonsensical fields like delim_title_len and
delim_title. We remove these.

We also clean up the spider comment connection string parsing,
including:

- Factoring out some code from the parsing function
- Rewriting the struct `st_spider_param_string_parse`, including
  replacing its messy methods with cleaner ones
- And any necessary changes caused by the above changes
parent 239a9304
#
# MDEV-31117 Spider UBSAN runtime error: applying non-zero offset x to null pointer in st_spider_param_string_parse::restore_delims
#
for master_1
for child2
for child3
CREATE TABLE t (c INT) ENGINE=Spider COMMENT='abc';
ERROR HY000: The connect info 'abc' is invalid
ALTER TABLE mysql.help_topic ENGINE=Spider;
ERROR HY000: The connect info 'help topics' is invalid
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", "srv" "srv",TABLE "t2"';
ERROR HY000: The connect info '"srv" "srv",TABLE "t2"' is invalid
create table t1 (c int) ENGINE=Spider CONNECTION='WRAPPER "mysql", srv \'srv\',TABLE "t2", password "say \\"hello\\ world!\\""';
drop table t1, t2;
for master_1
for child2
for child3
--echo #
--echo # MDEV-31117 Spider UBSAN runtime error: applying non-zero offset x to null pointer in st_spider_param_string_parse::restore_delims
--echo #
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
--error 12501
CREATE TABLE t (c INT) ENGINE=Spider COMMENT='abc';
--error 12501
ALTER TABLE mysql.help_topic ENGINE=Spider;
evalp CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t2 (c int);
# param title should not have delimiter
--error 12501
create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", "srv" "srv",TABLE "t2"';
# test escaping
create table t1 (c int) ENGINE=Spider CONNECTION='WRAPPER "mysql", srv \'srv\',TABLE "t2", password "say \\"hello\\ world!\\""';
drop table t1, t2;
--disable_query_log
--disable_result_log
--source ../t/test_deinit.inc
--enable_query_log
--enable_result_log
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -30,281 +30,21 @@
typedef struct st_spider_param_string_parse
{
char *start_ptr; /* Pointer to the start of the parameter string */
char *end_ptr; /* Pointer to the end of the parameter string */
char *start_title_ptr; /* Pointer to the start of the current parameter
title */
char *end_title_ptr; /* Pointer to the end of the current parameter
title */
char *start_value_ptr; /* Pointer to the start of the current parameter
value */
char *end_value_ptr; /* Pointer to the end of the current parameter
value */
int error_num; /* Error code of the error message to print when
an error is detected */
uint delim_title_len; /* Length of the paramater title's delimiter */
uint delim_value_len; /* Length of the paramater value's delimiter */
char delim_title; /* Current parameter title's delimiter character */
char delim_value; /* Current parameter value's delimiter character */
/**
Initialize the parameter string parse information.
@param param_string Pointer to the parameter string being parsed.
@param error_code Error code of the error message to print when
an error is detected.
*/
inline void init(char *param_string, int error_code)
{
start_ptr = param_string;
end_ptr = start_ptr + strlen(start_ptr);
init_param_title();
init_param_value();
error_num = error_code;
}
/**
Initialize the current parameter title.
*/
inline void init_param_title()
{
start_title_ptr = end_title_ptr = NULL;
delim_title_len = 0;
delim_title = '\0';
}
/**
Save pointers to the start and end positions of the current parameter
title in the parameter string. Also save the parameter title's
delimiter character.
@param start_value Pointer to the start position of the current
parameter title.
@param end_value Pointer to the end position of the current
parameter title.
*/
inline void set_param_title(char *start_title, char *end_title)
{
start_title_ptr = start_title;
end_title_ptr = end_title;
if (*start_title == '"' ||
*start_title == '\'')
{
delim_title = *start_title;
if (start_title >= start_ptr && *--start_title == '\\')
delim_title_len = 2;
else
delim_title_len = 1;
}
}
/**
Initialize the current parameter value.
*/
inline void init_param_value()
{
start_value_ptr = end_value_ptr = NULL;
delim_value_len = 0;
delim_value = '\0';
}
/**
Save pointers to the start and end positions of the current parameter
value in the parameter string. Also save the parameter value's
delimiter character.
@param start_value Pointer to the start position of the current
parameter value.
@param end_value Pointer to the end position of the current
parameter value.
*/
inline void set_param_value(char *start_value, char *end_value)
{
start_value_ptr = start_value--;
end_value_ptr = end_value;
if (*start_value == '"' ||
*start_value == '\'')
{
delim_value = *start_value;
if (*--start_value == '\\')
delim_value_len = 2;
else
delim_value_len = 1;
}
}
/**
Determine whether the current parameter in the parameter string has
extra parameter values.
@return 0 Current parameter value in the parameter string
does not have extra parameter values.
<> 0 Error code indicating that the current parameter
value in the parameter string has extra
parameter values.
*/
inline int has_extra_parameter_values()
{
int error_num = 0;
DBUG_ENTER("has_extra_parameter_values");
if (end_value_ptr)
{
/* There is a current parameter value */
char *end_param_ptr = end_value_ptr;
while (end_param_ptr < end_ptr &&
(*end_param_ptr == ' ' || *end_param_ptr == '\r' ||
*end_param_ptr == '\n' || *end_param_ptr == '\t'))
end_param_ptr++;
if (end_param_ptr < end_ptr && *end_param_ptr != '\0')
{
/* Extra values in parameter definition */
error_num = print_param_error();
}
}
DBUG_RETURN(error_num);
}
inline int get_next_parameter_head(char *st, char **nx)
{
DBUG_ENTER("get_next_parameter_head");
char *sq = strchr(st, '\'');
char *dq = strchr(st, '"');
if (!sq && !dq)
{
DBUG_RETURN(print_param_error());
}
if (dq && (!sq || sq > dq))
{
while (1)
{
++dq;
if (*dq == '\\')
{
++dq;
}
else if (*dq == '"')
{
break;
}
else if (*dq == '\0')
{
DBUG_RETURN(print_param_error());
}
}
while (1)
{
++dq;
if (*dq == '\0')
{
*nx = dq;
break;
}
else if (*dq == ',')
{
*dq = '\0';
*nx = dq + 1;
break;
}
else if (*dq != ' ' && *dq != '\r' && *dq != '\n' && *dq != '\t')
{
DBUG_RETURN(print_param_error());
}
}
}
else /* sq && (!dq || sq <= dq) */
{
while (1)
{
++sq;
if (*sq == '\\')
{
++sq;
}
else if (*sq == '\'')
{
break;
}
else if (*sq == '\0')
{
DBUG_RETURN(print_param_error());
}
}
while (1)
{
++sq;
if (*sq == '\0')
{
*nx = sq;
break;
}
else if (*sq == ',')
{
*sq = '\0';
*nx = sq + 1;
break;
}
else if (*sq != ' ' && *sq != '\r' && *sq != '\n' && *sq != '\t')
{
DBUG_RETURN(print_param_error());
}
}
}
DBUG_RETURN(0);
}
/**
Restore the current parameter's input delimiter characters in the
parameter string. They were NULLed during parameter parsing.
*/
inline void restore_delims()
{
char *end = end_title_ptr - 1;
switch (delim_title_len)
{
case 2:
*end++ = '\\';
/* Fall through */
case 1:
*end = delim_title;
}
end = end_value_ptr - 1;
switch (delim_value_len)
{
case 2:
*end++ = '\\';
/* Fall through */
case 1:
*end = delim_value;
}
}
/**
Print a parameter string error message.
@return Error code.
*/
int print_param_error();
char *start_title; /* Pointer to the start of the current parameter
title */
char *end_title; /* Pointer to the end of the current
parameter value */
char *start_value; /* Pointer to the start of the current parameter
value */
char *end_value; /* Pointer to the end of the current parameter
value */
char delim_value; /* Current parameter value's delimiter
character, either a single or a double quote */
int error_num; /* Error code of the error message to print when
an error is detected */
int fail(bool restore_delim);
bool locate_param_def(char*& start_param);
} SPIDER_PARAM_STRING_PARSE;
uchar *spider_tbl_get_key(
......@@ -344,19 +84,12 @@ void spider_free_tmp_share_alloc(
SPIDER_SHARE *share
);
char *spider_get_string_between_quote(
char *ptr,
bool alloc,
SPIDER_PARAM_STRING_PARSE *param_string_parse = NULL
);
int spider_create_string_list(
char ***string_list,
uint **string_length_list,
uint *list_length,
char *str,
uint length,
SPIDER_PARAM_STRING_PARSE *param_string_parse
uint length
);
int spider_create_long_list(
......@@ -365,8 +98,7 @@ int spider_create_long_list(
char *str,
uint length,
long min_val,
long max_val,
SPIDER_PARAM_STRING_PARSE *param_string_parse
long max_val
);
int spider_create_longlong_list(
......@@ -375,8 +107,7 @@ int spider_create_longlong_list(
char *str,
uint length,
longlong min_val,
longlong max_val,
SPIDER_PARAM_STRING_PARSE *param_string_parse
longlong max_val
);
int spider_increase_string_list(
......
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