summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorArun Kuruvila <arun.kuruvila@oracle.com>2015-06-04 11:53:17 +0530
committerArun Kuruvila <arun.kuruvila@oracle.com>2015-06-04 11:53:17 +0530
commit044e3b1d07c0854c39178d3054ab0cd0a3188436 (patch)
tree7e560ccc8b4fb80ade6d611cb9df47bd9c24739d /client
parentc0055f0d41af73f0d8a59ccb66fc7a3a43acdeaa (diff)
downloadmariadb-git-044e3b1d07c0854c39178d3054ab0cd0a3188436.tar.gz
Bug #20605441 : BUFFER OVERFLOW IN MYSQLSLAP
Description:- mysqlslap is a diagnostic utility designed to emulate client load for a MySQL server and to report the timing of each stage. This utility crashes when invalid values are passed to the options 'num_int_cols_opt' or 'num_chars_cols_opt' or 'engine'. Analysis:- mysqlslap uses "parse_option()" to parse the values specified to the options 'num_int_cols_opt', 'num_chars_cols_opt' and 'engine'. These options takes values separated by commas. In "parse_option()", the comma separated values are separated and copied into a buffer without checking the length of the string to be copied. The size of the buffer is defined by a macro HUGE_STRING_LENGTH whose value is 8196. So if the length of the any of the comma separated value exceeds HUGE_STRING_LENGTH, will result in a buffer overflow. Fix:- A check is introduced in "parse_option()" to check whether the size of the string to be copied is more than HUGE_STRING_LENGTH. If it is more, an error, "Invalid value specified for the option 'xxx'" is thrown. Option length was incorrectly calculated for the last comma separated value. So fixed that as well.
Diffstat (limited to 'client')
-rw-r--r--client/mysqlslap.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 4c4dbafc24d..65c5945e603 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2015, 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
@@ -245,7 +245,7 @@ void print_conclusions_csv(conclusions *con);
void generate_stats(conclusions *con, option_string *eng, stats *sptr);
uint parse_comma(const char *string, uint **range);
uint parse_delimiter(const char *script, statement **stmt, char delm);
-uint parse_option(const char *origin, option_string **stmt, char delm);
+int parse_option(const char *origin, option_string **stmt, char delm);
static int drop_schema(MYSQL *mysql, const char *db);
uint get_random_string(char *buf);
static statement *build_table_string(void);
@@ -1227,7 +1227,13 @@ get_options(int *argc,char ***argv)
if (num_int_cols_opt)
{
option_string *str;
- parse_option(num_int_cols_opt, &str, ',');
+ if(parse_option(num_int_cols_opt, &str, ',') == -1)
+ {
+ fprintf(stderr, "Invalid value specified for the option "
+ "'number-int-cols'\n");
+ option_cleanup(str);
+ return 1;
+ }
num_int_cols= atoi(str->string);
if (str->option)
num_int_cols_index= atoi(str->option);
@@ -1237,7 +1243,13 @@ get_options(int *argc,char ***argv)
if (num_char_cols_opt)
{
option_string *str;
- parse_option(num_char_cols_opt, &str, ',');
+ if(parse_option(num_char_cols_opt, &str, ',') == -1)
+ {
+ fprintf(stderr, "Invalid value specified for the option "
+ "'number-char-cols'\n");
+ option_cleanup(str);
+ return 1;
+ }
num_char_cols= atoi(str->string);
if (str->option)
num_char_cols_index= atoi(str->option);
@@ -1473,7 +1485,13 @@ get_options(int *argc,char ***argv)
printf("Parsing engines to use.\n");
if (default_engine)
- parse_option(default_engine, &engine_options, ',');
+ {
+ if(parse_option(default_engine, &engine_options, ',') == -1)
+ {
+ fprintf(stderr, "Invalid value specified for the option 'engine'\n");
+ return 1;
+ }
+ }
if (tty_password)
opt_password= get_tty_password(NullS);
@@ -1946,7 +1964,7 @@ end:
DBUG_RETURN(0);
}
-uint
+int
parse_option(const char *origin, option_string **stmt, char delm)
{
char *retstr;
@@ -1966,6 +1984,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
char buffer[HUGE_STRING_LENGTH];
char *buffer_ptr;
+ /*
+ Return an error if the length of the any of the comma seprated value
+ exceeds HUGE_STRING_LENGTH.
+ */
+ if ((size_t)(retstr - ptr) > HUGE_STRING_LENGTH)
+ return -1;
+
count++;
strncpy(buffer, ptr, (size_t)(retstr - ptr));
if ((buffer_ptr= strchr(buffer, ':')))
@@ -1998,6 +2023,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
{
char *origin_ptr;
+ /*
+ Return an error if the length of the any of the comma seprated value
+ exceeds HUGE_STRING_LENGTH.
+ */
+ if (strlen(ptr) > HUGE_STRING_LENGTH)
+ return -1;
+
if ((origin_ptr= strchr(ptr, ':')))
{
char *option_ptr;
@@ -2008,13 +2040,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
option_ptr= (char *)ptr + 1 + tmp->length;
/* Move past the : and the first string */
- tmp->option_length= (size_t)((ptr + length) - option_ptr);
+ tmp->option_length= strlen(option_ptr);
tmp->option= my_strndup(option_ptr, tmp->option_length,
MYF(MY_FAE));
}
else
{
- tmp->length= (size_t)((ptr + length) - ptr);
+ tmp->length= strlen(ptr);
tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
}