diff options
author | Arun Kuruvila <arun.kuruvila@oracle.com> | 2015-06-04 11:53:17 +0530 |
---|---|---|
committer | Arun Kuruvila <arun.kuruvila@oracle.com> | 2015-06-04 11:53:17 +0530 |
commit | 044e3b1d07c0854c39178d3054ab0cd0a3188436 (patch) | |
tree | 7e560ccc8b4fb80ade6d611cb9df47bd9c24739d /client/mysqlslap.c | |
parent | c0055f0d41af73f0d8a59ccb66fc7a3a43acdeaa (diff) | |
download | mariadb-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/mysqlslap.c')
-rw-r--r-- | client/mysqlslap.c | 48 |
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)); } |