From cf3487acf374cf4495c50a96f431f9c14695ed1e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 05:45:50 +0300 Subject: [PATCH 1/7] BUG#20100 fix: mysql_upgrade modified to also accept all the communication parameters from the command line and pass 'em correctly to both mysqlcheck and mysql client/mysql_upgrade.c: Now mysql_upgrade passes all the parameters specified on the command line to both mysqlcheck and mysql through the upgrade_defaults file --- client/mysql_upgrade.c | 702 +++++++++++++++++++++++++++-------------- 1 file changed, 460 insertions(+), 242 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 6ec361392c8..e5855aee605 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -16,21 +16,42 @@ #include "client_priv.h" #include +#include +#include + +#define UPGRADE_DEFAULTS_NAME "mysql_upgrade_defaults" +#define MYSQL_UPGRADE_INFO_NAME "mysql_upgrade_info" +#define MYSQL_FIX_PRIV_TABLES_NAME "mysql_fix_privilege_tables.sql" + +#define MY_PARENT (1 << 0) +#define MY_ISDIR (1 << 1) +#define MY_SEARCH_SELF (1 << 2) #ifdef __WIN__ const char *mysqlcheck_name= "mysqlcheck.exe"; const char *mysql_name= "mysql.exe"; +const char *mysqld_name= "mysqld.exe"; #else const char *mysqlcheck_name= "mysqlcheck"; const char *mysql_name= "mysql"; +const char *mysqld_name= "mysqld"; #endif /*__WIN__*/ -static my_bool opt_force= 0, opt_verbose= 0, tty_password= 0; +extern TYPELIB sql_protocol_typelib; + +static my_bool opt_force= 0, opt_verbose= 0, opt_compress= 0; static char *user= (char*) "root", *basedir= 0, *datadir= 0, *opt_password= 0; -static my_bool upgrade_defaults_created= 0; -static my_string opt_mysql_port, opt_mysql_unix_port= 0; -static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace"; -static my_bool info_flag= 0; +static char *current_host= 0; +static char *opt_default_charset= 0, *opt_charsets_dir= 0; +#ifdef HAVE_SMEM +static char *shared_memory_base_name= 0; +#endif +static char *opt_protocol= 0; +static my_string opt_mysql_port= 0, opt_mysql_unix_port= 0; +#ifndef DBUG_OFF +static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace"; +#endif +static my_bool info_flag= 0, tty_password= 0; static struct my_option my_long_options[]= { @@ -50,27 +71,51 @@ static struct my_option my_long_options[]= #endif {"debug-info", 'T', "Print some debug info at exit.", (gptr *) & info_flag, (gptr *) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"force", 'f', "Continue even if we get an sql-error.", + {"default-character-set", OPT_DEFAULT_CHARSET, + "Set the default character set.", (gptr*) &opt_default_charset, + (gptr*) &opt_default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " + "has already been executed for the current version of MySQL.", (gptr*) &opt_force, (gptr*) &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are.", (gptr*) &opt_charsets_dir, + (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"compress", OPT_COMPRESS, "Use compression in server/client protocol.", + (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + 0, 0, 0}, + {"host",'h', "Connect to host.", (gptr*) ¤t_host, + (gptr*) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', - "Password to use when connecting to server. If password is not given it's solicited on the tty.", - 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Password to use when connecting to server. If password is not given" + " it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef __WIN__ + {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, - 0}, + (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_SMEM + {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, + "Base name of shared memory.", (gptr*) &shared_memory_base_name, + (gptr*) &shared_memory_base_name, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"socket", 'S', "Socket file to use for connection.", - (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "User for login if not current user.", (gptr*) &user, (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Display more output about the process", (gptr*) &opt_verbose, - (gptr *) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#include + {"verbose", 'v', "Display more output about the process", + (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; + static const char *load_default_groups[]= { "mysql_upgrade", 0 @@ -78,6 +123,81 @@ static const char *load_default_groups[]= #include +static LIST *extra_defaults= NULL; + +typedef struct _extra_default +{ + int id; + const char *name; + int n_len; + const char *value; + int v_len; +} extra_default_t; + +static inline +void set_extra_default(int id, const struct my_option *opt) +{ + switch (id) { + case 'b': case 'd': /* these are ours */ + case 'f': /* --force is ours */ + case 'u': /* --user passed on cmdline */ + case 'T': /* --debug-info is not accepted by mysqlcheck */ + /* so, do nothing */ + break; + default: + { + LIST *l; + extra_default_t *d; + + /* + Remove any earlier duplicates: they can + refer to invalid memory addresses (stale pointers) + */ + l= extra_defaults; + while (l) + { + LIST *n= l->next; + + d= l->data; + if (d->id == id) + { + extra_defaults= list_delete(extra_defaults, l); + my_free((gptr)l, MYF(0)); + my_free((gptr)d, MYF(0)); + } + l= n; + } + + d= (extra_default_t *)my_malloc(sizeof(extra_default_t), + MYF(MY_FAE|MY_ZEROFILL)); + d->id= id; + d->name= opt->name; + d->n_len= strlen(opt->name); + if (opt->arg_type != NO_ARG) + switch (opt->var_type & GET_TYPE_MASK) { + case GET_BOOL: + if (*((int *)opt->value)) + { + d->value= "true"; + d->v_len= 4; + } + break; + case GET_STR: + case GET_STR_ALLOC: + d->value= *opt->value; + d->v_len= strlen(d->value); + break; + default: + my_printf_error(0, "Error: internal error at %s:%d", MYF(0), + __FILE__, __LINE__); + exit(1); + } + list_push(extra_defaults, d); + } + } +} + + static my_bool get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), char *argument) @@ -85,16 +205,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), switch (optid) { case '?': puts - ("MySQL utility script to upgrade database to the current server version"); + ("MySQL utility to upgrade database to the current server version"); puts(""); my_print_help(my_long_options); exit(0); case '#': DBUG_PUSH(argument ? argument : default_dbug_option); break; - case 'f': - opt_force= TRUE; - break; case 'p': tty_password= 1; if (argument) @@ -109,315 +226,416 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)), tty_password= 0; } break; +#ifdef __WIN__ + case 'W': + my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); + opt_protocol= my_strdup("pipe", MYF(MY_FAE)); + break; +#endif + case OPT_MYSQL_PROTOCOL: + if (find_type(argument, &sql_protocol_typelib, 0) > 0) + { + my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR)); + opt_protocol= my_strdup(argument, MYF(MY_FAE)); + } + else + { + fprintf(stderr, "Unknown option to protocol: %s\n", argument); + exit(1); + } + break; +#include default:; - }; + } + set_extra_default(opt->id, opt); return 0; } -/* buffer should be not smaller than FN_REFLEN */ -static my_bool test_file_exists_res(const char *dir, const char *fname, - char *buffer, char **buf_end) -{ - MY_STAT stat_info; - - *buf_end= strxnmov(buffer, FN_REFLEN-1, dir, "/", fname, NullS); - unpack_filename(buffer, buffer); - return my_stat(buffer, &stat_info, MYF(0)) != 0; -} - - -static my_bool test_file_exists(const char *dir, const char *fname) -{ - char path[FN_REFLEN]; - char *path_end; - return test_file_exists_res(dir, fname, path, &path_end); -} - - static int create_check_file(const char *path) { - File check_file= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME)); - int error; - - if (check_file < 0) - return 1; - - error= my_write(check_file, - MYSQL_SERVER_VERSION, strlen(MYSQL_SERVER_VERSION), + int ret; + File fd; + + fd= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME)); + if (fd < 0) { + ret= 1; + goto error; + } + ret= my_write(fd, MYSQL_SERVER_VERSION, + sizeof(MYSQL_SERVER_VERSION) - 1, MYF(MY_WME | MY_FNABP)); - error= my_close(check_file, MYF(MY_FAE | MY_WME)) || error; - return error; + ret|= my_close(fd, MYF(MY_FAE | MY_WME)); +error: + return ret; } -static int create_defaults_file(const char *path, const char *our_defaults_path) +static int create_defaults_file(const char *path, const char *forced_path) { - uint b_read; - File our_defaults_file, defaults_file; - char buffer[512]; - char *buffer_end; - int failed_to_open_count= 0; - int error; + int ret; + uint cnt; + File forced_file, defaults_file; + + DYNAMIC_STRING buf; + extra_default_t *d; - /* check if the defaults file is needed at all */ - if (!opt_password) - return 0; - -retry_open: + my_delete(path, MYF(0)); + defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL, MYF(MY_FAE | MY_WME)); - if (defaults_file < 0) { - if (failed_to_open_count == 0) - { - remove(path); - failed_to_open_count+= 1; - goto retry_open; - } - else - return 1; + ret= 1; + goto out; } - upgrade_defaults_created= 1; - if (our_defaults_path) + if (init_dynamic_string(&buf, NULL, my_getpagesize(), FN_REFLEN)) { - our_defaults_file= my_open(our_defaults_path, O_RDONLY, - MYF(MY_FAE | MY_WME)); - if (our_defaults_file < 0) - return 1; + ret= 1; + goto error; + } + + if (forced_path) + { + forced_file= my_open(forced_path, O_RDONLY, MYF(MY_FAE | MY_WME)); + if (forced_file < 0) + { + ret= 1; + goto error; + } do { - if (((b_read= my_read(our_defaults_file, buffer, - sizeof(buffer), MYF(MY_WME))) == MY_FILE_ERROR) || - my_write(defaults_file, buffer, b_read, MYF(MY_FNABP | MY_WME))) + cnt= my_read(forced_file, buf.str, buf.max_length, MYF(MY_WME)); + if ((cnt == MY_FILE_ERROR) + || my_write(defaults_file, buf.str, cnt, MYF(MY_FNABP | MY_WME))) { - error= 1; - goto close_return; + ret= 1; + my_close(forced_file, MYF(0)); + goto error; } - } while (b_read == sizeof(buffer)); + } while (cnt == buf.max_length); + my_close(forced_file, MYF(0)); } - buffer_end= strnmov(buffer, "\n[client]", sizeof(buffer)); - if (opt_password) - buffer_end= strxnmov(buffer_end, sizeof(buffer), - "\npassword=", opt_password, NullS); - error= my_write(defaults_file, buffer, (int) (buffer_end - buffer), - MYF(MY_WME | MY_FNABP)); -close_return: - return my_close(defaults_file, MYF(MY_WME)) || error; + + dynstr_set(&buf, "\n[client]"); + while (extra_defaults) + { + int len; + + d= extra_defaults->data; + len= d->n_len + d->v_len + 1; + if (buf.length + len >= buf.max_length) /* to avoid realloc() */ + { + if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) + { + ret= 1; + goto error; + } + dynstr_set(&buf, NULL); + } + if (dynstr_append_mem(&buf, "\n", 1) + || dynstr_append_mem(&buf, d->name, d->n_len) + || (d->v_len && (dynstr_append_mem(&buf, "=", 1) + || dynstr_append_mem(&buf, d->value, d->v_len)))) + { + ret= 1; + goto error; + } + my_delete((gptr)d, MYF(0)); + list_pop(extra_defaults); /* pop off the head */ + } + if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME))) + { + ret= 1; + goto error; + } + /* everything's all right */ + ret= 0; +error: + dynstr_free(&buf); + + if (defaults_file >= 0) + ret|= my_close(defaults_file, MYF(MY_WME)); + + if (ret) + my_delete(path, MYF(0)); + +out: + return ret; +} + + +/* Compare filenames */ +static int comp_names(struct fileinfo *a, struct fileinfo *b) +{ + return (strcmp(a->name,b->name)); +} + + +static int +find_file(const char *name, const char *root, uint flags, char *result, size_t len, ...) +{ + int ret; + va_list va; + FILEINFO key= { name }; + const char *subdir; + char *cp; + + DBUG_ASSERT(root != NULL); + + cp= strmake(result, root, len); + if (cp[-1] != FN_LIBCHAR) + *cp= FN_LIBCHAR; + + ret= 1; + va_start(va, len); + subdir= (!(flags & MY_SEARCH_SELF)) ? va_arg(va, char *) : ""; + while (ret && subdir) + { + MY_DIR *dir; + FILEINFO *match; + uint i; + char *cp1; + + cp1= strnmov(cp + 1, subdir, len - (cp - result) - 1); + + dir= my_dir(result, (flags & MY_ISDIR) ? MY_WANT_STAT : MYF(0)); + if (dir) + { + match= bsearch(&key, dir->dir_entry, dir->number_off_files, + sizeof(FILEINFO), (qsort_cmp)comp_names); + if (match) + { + if (!(flags & MY_PARENT)) + { + if (cp1[-1] != FN_LIBCHAR) + *cp1++= FN_LIBCHAR; + strnmov(cp1, name, len - (cp1 - result)); + } + else + { + if (cp1[-1] == FN_LIBCHAR) + --cp1; + while (*--cp1 == FN_LIBCHAR) + {} + *++cp1= FN_LIBCHAR; + *++cp1= '\0'; + } + if (flags & MY_ISDIR) + ret= !MY_S_ISDIR(match->mystat->st_mode); + else + ret= 0; + } + my_dirend(dir); + } + subdir= va_arg(va, char *); + } + va_end(va); + return ret; } int main(int argc, char **argv) { - char bindir[FN_REFLEN]; - char *bindir_end, *buf_end; - char datadir_buf[FN_REFLEN]; - char mysqlcheck_line[FN_REFLEN], *mysqlcheck_end; - char check_file_name[FN_REFLEN]; - int check_file; - char fix_priv_tables_cmd[FN_REFLEN], *fix_cmd_end; - char script_line[FN_REFLEN]; - int error; + int ret; + char *forced_defaults_file; char *forced_extra_defaults; char *defaults_group_suffix; - char upgrade_defaults_path[FN_REFLEN], *defaults_to_use= 0; - char port_socket[100], *port_socket_end; + const char *script_line; + char *upgrade_defaults_path; + char *defaults_to_use= NULL; + int upgrade_defaults_created= 0; + + char path[FN_REFLEN]; + DYNAMIC_STRING cmdline; MY_INIT(argv[0]); #ifdef __NETWARE__ setscreenmode(SCR_AUTOCLOSE_ON_EXIT); #endif - load_defaults("my", load_default_groups, &argc, &argv); - - if ((error= handle_options(&argc, &argv, my_long_options, get_one_option))) - exit(error); - - if (tty_password) - opt_password= get_tty_password(NullS); - - /* Check if we want to force the use a specific default file */ + /* Check if we are forced to use specific defaults */ get_defaults_options(argc, argv, &forced_defaults_file, &forced_extra_defaults, &defaults_group_suffix); + + load_defaults("my", load_default_groups, &argc, &argv); - port_socket_end= port_socket; - if (opt_mysql_port) - port_socket_end= strxnmov(port_socket, sizeof(port_socket) - 1, " --port=", - opt_mysql_port, NullS); - if (opt_mysql_unix_port) - port_socket_end= strxnmov(port_socket_end, - sizeof(port_socket) - - (int)(port_socket_end - port_socket) - 1, - " --socket=", opt_mysql_unix_port, NullS); - *port_socket_end= 0; - - if (basedir) + if (handle_options(&argc, &argv, my_long_options, get_one_option)) { - bindir_end= strmake(bindir, basedir, sizeof(bindir)-1); + ret= 1; + goto error; } - else + if (tty_password) + opt_password= get_tty_password(NullS); + + if (init_dynamic_string(&cmdline, NULL, 2 * FN_REFLEN + 128, FN_REFLEN)) { - if (test_file_exists("./share/mysql/english", "errmsg.sys") - && (test_file_exists("./bin", "mysqld") || - test_file_exists("./libexec", "mysqld"))) + ret= 1; + goto error; + } + if (!basedir) + { + my_getwd(path, sizeof(path), MYF(0)); + basedir= my_strdup(path, MYF(0)); + if (find_file("errmsg.sys", basedir, MYF(0), path, sizeof(path), + "share/mysql/english", NullS) + || find_file(mysqld_name, basedir, MYF(0), path, sizeof(path), + "bin", "libexec", NullS)) { - my_getwd(bindir, sizeof(bindir), MYF(0)); - bindir_end= bindir + strlen(bindir); - } - else - { - bindir_end= strmake(bindir, DEFAULT_MYSQL_HOME, sizeof(bindir)-1); + my_strdup((gptr)basedir, MYF(0)); + basedir= (char *)DEFAULT_MYSQL_HOME; } } if (!datadir) { - datadir= datadir_buf; - if (test_file_exists(bindir, "data/mysql")) - { - *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/data", NullS)= 0; - } - else if (test_file_exists(bindir, "var/mysql")) - { - *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/var", NullS)= 0; - } + if (!find_file("mysql", basedir, MYF(MY_ISDIR|MY_PARENT), + path, sizeof(path), + "data", "var", NullS)) + datadir= my_strdup(path, MYF(0)); else - datadir= (char*) DATADIR; + datadir= (char *)DATADIR; + } + if (find_file("user.frm", datadir, MYF(0), path, sizeof(path), + "mysql", NullS)) + { + ret= 1; + puts("Can't find data directory. Please restart with" + " --datadir=path-to-writable-data-dir"); + goto error; } - strmake(bindir_end, "/bin", sizeof(bindir) - (int) (bindir_end - bindir)-1); - - if (!test_file_exists_res - (bindir, mysqlcheck_name, mysqlcheck_line, &mysqlcheck_end)) + /* + Create the modified defaults file to be used by mysqlcheck + and mysql tools + */ + fn_format(path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0)); + upgrade_defaults_path= my_strdup(path, MYF(0)); + + if (extra_defaults) { - printf("Can't find program '%s'\n", mysqlcheck_line); - puts("Please restart with --basedir=mysql-install-directory"); - exit(1); - } + ret= create_defaults_file(upgrade_defaults_path, forced_extra_defaults); + if (ret) + goto error; + + defaults_to_use= upgrade_defaults_path; + upgrade_defaults_created= 1; + } + else + defaults_to_use= forced_extra_defaults; - if (!test_file_exists(datadir, "mysql/user.frm")) + if (!find_file(MYSQL_UPGRADE_INFO_NAME, datadir, MY_SEARCH_SELF, + path, sizeof(path), NULL, NullS) + && !opt_force) { - puts - ("Can't find data directory. Please restart with --datadir=path-to-data-dir"); - exit(1); - } - - /* create the modified defaults file to be used by mysqlcheck */ - /* and mysql tools */ - *strxnmov(upgrade_defaults_path, sizeof(upgrade_defaults_path)-1, - datadir, "/upgrade_defaults", NullS)= 0; - unpack_filename(upgrade_defaults_path, upgrade_defaults_path); - if ((error= - create_defaults_file(upgrade_defaults_path, forced_extra_defaults))) - goto err_exit; - - defaults_to_use= upgrade_defaults_created ? - upgrade_defaults_path : forced_extra_defaults; - - if (test_file_exists_res(datadir, "mysql_upgrade_info", check_file_name, - &buf_end) && !opt_force) - { - char chf_buffer[50]; - int b_read; - check_file= my_open(check_file_name, O_RDONLY, MYF(0)); - b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0)); - chf_buffer[b_read]= 0; - my_close(check_file, MYF(0)); - if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION)) + char buf[sizeof(MYSQL_SERVER_VERSION)]; + int fd, cnt; + + fd= my_open(path, O_RDONLY, MYF(0)); + cnt= my_read(fd, buf, sizeof(buf) - 1, MYF(0)); + my_close(fd, MYF(0)); + buf[cnt]= 0; + if (!strcmp(buf, MYSQL_SERVER_VERSION)) { if (opt_verbose) - puts("mysql_upgrade already done for this version"); + puts("mysql_upgrade has already been done for this version"); goto fix_priv_tables; } } + + if (find_file(mysqlcheck_name, basedir, MYF(0), path, sizeof(path), + "bin", NullS)) + { + ret= 1; + printf("Can't find program '%s'\n", mysqlcheck_name); + puts("Please restart with --basedir=mysql-install-directory"); + goto error; + } + else + dynstr_set(&cmdline, path); if (defaults_to_use) { - mysqlcheck_end= strxnmov(mysqlcheck_end, - sizeof(mysqlcheck_line) - (int) (mysqlcheck_end - - mysqlcheck_line), - " --defaults-extra-file=", defaults_to_use,NullS); + dynstr_append(&cmdline, " --defaults-extra-file="); + dynstr_append(&cmdline, defaults_to_use); } - - mysqlcheck_end= strxnmov(mysqlcheck_end, - sizeof(mysqlcheck_line) - - (int) (mysqlcheck_end - mysqlcheck_line - 1), - " --check-upgrade --all-databases --auto-repair --user=", - user, port_socket, NullS); - *mysqlcheck_end= 0; + + dynstr_append(&cmdline, " --check-upgrade --all-databases" + " --auto-repair --user="); + dynstr_append(&cmdline, user); if (opt_verbose) - printf("Running %s\n", mysqlcheck_line); - if ((error= system(mysqlcheck_line))) + printf("Running %s\n", cmdline.str); + + ret= system(cmdline.str); + if (ret) { - printf("Error executing '%s'\n", mysqlcheck_line); - goto err_exit; + printf("Error executing '%s'\n", cmdline.str); + goto error; } - if ((error= create_check_file(check_file_name))) - goto err_exit; + fn_format(path, MYSQL_UPGRADE_INFO_NAME, datadir, "", MYF(0)); + ret= create_check_file(path); + if (ret) + goto error; fix_priv_tables: - if (!test_file_exists_res(bindir, mysql_name, - fix_priv_tables_cmd, &fix_cmd_end)) + if (find_file(mysql_name, basedir, MYF(0), path, sizeof(path), + "bin", NullS)) { - puts("Could not find MySQL command-line client (mysql)."); - puts - ("Please use --basedir to specify the directory where MySQL is installed."); - error= 1; - goto err_exit; + ret= 1; + puts("Could not find MySQL command-line client (mysql).\n" + "Please use --basedir to specify the directory" + " where MySQL is installed."); + goto error; } + else + dynstr_set(&cmdline, path); - if (!test_file_exists_res(basedir, - "support_files/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, "share/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, - "share/mysql/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res(basedir, - "scripts/mysql_fix_privilege_tables.sql", - script_line, &buf_end) - && !test_file_exists_res("/usr/local/mysql/share/mysql", - "mysql_fix_privilege_tables.sql", script_line, - &buf_end)) + if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0), + path, sizeof(path), + "support_files", "share/mysql", "scripts", + NullS) + && find_file(MYSQL_FIX_PRIV_TABLES_NAME, "/usr/local/mysql", MYF(0), + path, sizeof(path), + "share/mysql", NullS)) { - puts("Could not find file mysql_fix_privilege_tables.sql"); - puts - ("Please use --basedir to specify the directory where MySQL is installed"); - error= 1; - goto err_exit; + ret= 1; + puts("Could not find file " MYSQL_FIX_PRIV_TABLES_NAME "\n" + "Please use --basedir to specify the directory" + " where MySQL is installed"); + goto error; } + else + script_line= my_strdup(path, MYF(0)); if (defaults_to_use) { - fix_cmd_end= strxnmov(fix_cmd_end, - sizeof(fix_priv_tables_cmd) - - (int) (fix_cmd_end - fix_priv_tables_cmd - 1), - " --defaults-extra-file=", defaults_to_use, NullS); + dynstr_append(&cmdline, " --defaults-extra-file="); + dynstr_append(&cmdline, defaults_to_use); } - fix_cmd_end= strxnmov(fix_cmd_end, - sizeof(fix_priv_tables_cmd) - (int) (fix_cmd_end - - fix_priv_tables_cmd), - " --user=", user, port_socket, " mysql < ", script_line, NullS); - *fix_cmd_end= 0; + dynstr_append(&cmdline, " --force --no-auto-rehash --batch --user="); + dynstr_append(&cmdline, user); + dynstr_append(&cmdline, " mysql < "); + dynstr_append(&cmdline, script_line); - if ((error= system(fix_priv_tables_cmd))) - { - /* Problem is that the 'Duplicate column' error */ - /* which is not a bug for the script makes 'mysql' return */ - /* an error */ - /* printf("Error executing '%s'\n", fix_priv_tables_cmd); */ - } + if (opt_verbose) + printf("Running %s\n", cmdline.str); + + ret= system(cmdline.str); + if (ret) + printf("Error executing '%s'\n", cmdline.str); + +error: + dynstr_free(&cmdline); -err_exit: if (upgrade_defaults_created) my_delete(upgrade_defaults_path, MYF(0)); + my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); - return error; -} /* main */ + return ret; +} + From 3a86738289ea6d587d17aebab4f5d9967c9bba99 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 10:11:02 -0500 Subject: [PATCH 2/7] Bug#10963: LEFT/RIGHT/SUBSTR/.. string functions returns wrong result \ on large length Problem: Most (all) of the numeric inputs were being coerced into int (32 bit) sized variables. Works OK for sane inputs; any input larger than 2^32 (or 2^31 for signed vars) exihibited predictable wrapping behavior (up to about 10^18) and then started having really strange behaviour past that point (since the conversion to 64 bit int from the DECIMAL type can do weird things on out of range numbers). Solution: 1) Add many tests. 2) Convert input from (u)long type to (u)longlong. 3) Do (sometimes multiple) sanity checks on input, keeping in mind that sometimes a negative longlong is not a negative longlong (if the unsigned_flag is set). 4) Emulate existing behavior w/rt negative and "small" out-of-bounds values. mysql-test/r/func_str.result: Additional test results for #10963 mysql-test/t/func_str.test: Additional test results for #10963 sql/item_func.cc: Used larger type for counting, to avoid truncation. sql/item_strfunc.cc: Fix for #10963, including comments and cleaned up logic --- mysql-test/r/func_str.result | 755 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 189 +++++++++ sql/item_func.cc | 20 +- sql/item_strfunc.cc | 187 ++++++--- 4 files changed, 1096 insertions(+), 55 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c2c12f8d291..e5342eec54f 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1148,4 +1148,759 @@ id select_type table type possible_keys key key_len ref rows Extra Warnings: Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5)) DROP TABLE t1,t2; +select locate('he','hello',-2); +locate('he','hello',-2) +0 +select locate('lo','hello',-4294967295); +locate('lo','hello',-4294967295) +0 +select locate('lo','hello',4294967295); +locate('lo','hello',4294967295) +0 +select locate('lo','hello',-4294967296); +locate('lo','hello',-4294967296) +0 +select locate('lo','hello',4294967296); +locate('lo','hello',4294967296) +0 +select locate('lo','hello',-4294967297); +locate('lo','hello',-4294967297) +0 +select locate('lo','hello',4294967297); +locate('lo','hello',4294967297) +0 +select locate('lo','hello',-18446744073709551615); +locate('lo','hello',-18446744073709551615) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551615); +locate('lo','hello',18446744073709551615) +0 +select locate('lo','hello',-18446744073709551616); +locate('lo','hello',-18446744073709551616) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551616); +locate('lo','hello',18446744073709551616) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',-18446744073709551617); +locate('lo','hello',-18446744073709551617) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select locate('lo','hello',18446744073709551617); +locate('lo','hello',18446744073709551617) +0 +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 10); +left('hello', 10) +hello +select left('hello', 0); +left('hello', 0) + +select left('hello', -1); +left('hello', -1) + +select left('hello', -4294967295); +left('hello', -4294967295) + +select left('hello', 4294967295); +left('hello', 4294967295) +hello +select left('hello', -4294967296); +left('hello', -4294967296) + +select left('hello', 4294967296); +left('hello', 4294967296) +hello +select left('hello', -4294967297); +left('hello', -4294967297) + +select left('hello', 4294967297); +left('hello', 4294967297) +hello +select left('hello', -18446744073709551615); +left('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551615); +left('hello', 18446744073709551615) +hello +select left('hello', -18446744073709551616); +left('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551616); +left('hello', 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', -18446744073709551617); +left('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select left('hello', 18446744073709551617); +left('hello', 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 10); +right('hello', 10) +hello +select right('hello', 0); +right('hello', 0) + +select right('hello', -1); +right('hello', -1) + +select right('hello', -4294967295); +right('hello', -4294967295) + +select right('hello', 4294967295); +right('hello', 4294967295) +hello +select right('hello', -4294967296); +right('hello', -4294967296) + +select right('hello', 4294967296); +right('hello', 4294967296) +hello +select right('hello', -4294967297); +right('hello', -4294967297) + +select right('hello', 4294967297); +right('hello', 4294967297) +hello +select right('hello', -18446744073709551615); +right('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551615); +right('hello', 18446744073709551615) +hello +select right('hello', -18446744073709551616); +right('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551616); +right('hello', 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', -18446744073709551617); +right('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select right('hello', 18446744073709551617); +right('hello', 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 2, -1); +substring('hello', 2, -1) + +select substring('hello', -1, 1); +substring('hello', -1, 1) +o +select substring('hello', -2, 1); +substring('hello', -2, 1) +l +select substring('hello', -4294967295, 1); +substring('hello', -4294967295, 1) + +select substring('hello', 4294967295, 1); +substring('hello', 4294967295, 1) + +select substring('hello', -4294967296, 1); +substring('hello', -4294967296, 1) + +select substring('hello', 4294967296, 1); +substring('hello', 4294967296, 1) + +select substring('hello', -4294967297, 1); +substring('hello', -4294967297, 1) + +select substring('hello', 4294967297, 1); +substring('hello', 4294967297, 1) + +select substring('hello', -18446744073709551615, 1); +substring('hello', -18446744073709551615, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551615, 1); +substring('hello', 18446744073709551615, 1) + +select substring('hello', -18446744073709551616, 1); +substring('hello', -18446744073709551616, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551616, 1); +substring('hello', 18446744073709551616, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -18446744073709551617, 1); +substring('hello', -18446744073709551617, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551617, 1); +substring('hello', 18446744073709551617, 1) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, -1); +substring('hello', 1, -1) + +select substring('hello', 1, -4294967295); +substring('hello', 1, -4294967295) + +select substring('hello', 1, 4294967295); +substring('hello', 1, 4294967295) +hello +select substring('hello', 1, -4294967296); +substring('hello', 1, -4294967296) + +select substring('hello', 1, 4294967296); +substring('hello', 1, 4294967296) +hello +select substring('hello', 1, -4294967297); +substring('hello', 1, -4294967297) + +select substring('hello', 1, 4294967297); +substring('hello', 1, 4294967297) +hello +select substring('hello', 1, -18446744073709551615); +substring('hello', 1, -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551615); +substring('hello', 1, 18446744073709551615) +hello +select substring('hello', 1, -18446744073709551616); +substring('hello', 1, -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551616); +substring('hello', 1, 18446744073709551616) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, -18446744073709551617); +substring('hello', 1, -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 1, 18446744073709551617); +substring('hello', 1, 18446744073709551617) +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -1, -1); +substring('hello', -1, -1) + +select substring('hello', -4294967295, -4294967295); +substring('hello', -4294967295, -4294967295) + +select substring('hello', 4294967295, 4294967295); +substring('hello', 4294967295, 4294967295) + +select substring('hello', -4294967296, -4294967296); +substring('hello', -4294967296, -4294967296) + +select substring('hello', 4294967296, 4294967296); +substring('hello', 4294967296, 4294967296) + +select substring('hello', -4294967297, -4294967297); +substring('hello', -4294967297, -4294967297) + +select substring('hello', 4294967297, 4294967297); +substring('hello', 4294967297, 4294967297) + +select substring('hello', -18446744073709551615, -18446744073709551615); +substring('hello', -18446744073709551615, -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551615, 18446744073709551615); +substring('hello', 18446744073709551615, 18446744073709551615) + +select substring('hello', -18446744073709551616, -18446744073709551616); +substring('hello', -18446744073709551616, -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551616, 18446744073709551616); +substring('hello', 18446744073709551616, 18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', -18446744073709551617, -18446744073709551617); +substring('hello', -18446744073709551617, -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select substring('hello', 18446744073709551617, 18446744073709551617); +substring('hello', 18446744073709551617, 18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -1, 1, 'hi'); +insert('hello', -1, 1, 'hi') +hello +select insert('hello', -4294967295, 1, 'hi'); +insert('hello', -4294967295, 1, 'hi') +hello +select insert('hello', 4294967295, 1, 'hi'); +insert('hello', 4294967295, 1, 'hi') +hello +select insert('hello', -4294967296, 1, 'hi'); +insert('hello', -4294967296, 1, 'hi') +hello +select insert('hello', 4294967296, 1, 'hi'); +insert('hello', 4294967296, 1, 'hi') +hello +select insert('hello', -4294967297, 1, 'hi'); +insert('hello', -4294967297, 1, 'hi') +hello +select insert('hello', 4294967297, 1, 'hi'); +insert('hello', 4294967297, 1, 'hi') +hello +select insert('hello', -18446744073709551615, 1, 'hi'); +insert('hello', -18446744073709551615, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551615, 1, 'hi'); +insert('hello', 18446744073709551615, 1, 'hi') +hello +select insert('hello', -18446744073709551616, 1, 'hi'); +insert('hello', -18446744073709551616, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551616, 1, 'hi'); +insert('hello', 18446744073709551616, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -18446744073709551617, 1, 'hi'); +insert('hello', -18446744073709551617, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551617, 1, 'hi'); +insert('hello', 18446744073709551617, 1, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, -1, 'hi'); +insert('hello', 1, -1, 'hi') +hi +select insert('hello', 1, -4294967295, 'hi'); +insert('hello', 1, -4294967295, 'hi') +hi +select insert('hello', 1, 4294967295, 'hi'); +insert('hello', 1, 4294967295, 'hi') +hi +select insert('hello', 1, -4294967296, 'hi'); +insert('hello', 1, -4294967296, 'hi') +hi +select insert('hello', 1, 4294967296, 'hi'); +insert('hello', 1, 4294967296, 'hi') +hi +select insert('hello', 1, -4294967297, 'hi'); +insert('hello', 1, -4294967297, 'hi') +hi +select insert('hello', 1, 4294967297, 'hi'); +insert('hello', 1, 4294967297, 'hi') +hi +select insert('hello', 1, -18446744073709551615, 'hi'); +insert('hello', 1, -18446744073709551615, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551615, 'hi'); +insert('hello', 1, 18446744073709551615, 'hi') +hi +select insert('hello', 1, -18446744073709551616, 'hi'); +insert('hello', 1, -18446744073709551616, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551616, 'hi'); +insert('hello', 1, 18446744073709551616, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, -18446744073709551617, 'hi'); +insert('hello', 1, -18446744073709551617, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 1, 18446744073709551617, 'hi'); +insert('hello', 1, 18446744073709551617, 'hi') +hi +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -1, -1, 'hi'); +insert('hello', -1, -1, 'hi') +hello +select insert('hello', -4294967295, -4294967295, 'hi'); +insert('hello', -4294967295, -4294967295, 'hi') +hello +select insert('hello', 4294967295, 4294967295, 'hi'); +insert('hello', 4294967295, 4294967295, 'hi') +hello +select insert('hello', -4294967296, -4294967296, 'hi'); +insert('hello', -4294967296, -4294967296, 'hi') +hello +select insert('hello', 4294967296, 4294967296, 'hi'); +insert('hello', 4294967296, 4294967296, 'hi') +hello +select insert('hello', -4294967297, -4294967297, 'hi'); +insert('hello', -4294967297, -4294967297, 'hi') +hello +select insert('hello', 4294967297, 4294967297, 'hi'); +insert('hello', 4294967297, 4294967297, 'hi') +hello +select insert('hello', -18446744073709551615, -18446744073709551615, 'hi'); +insert('hello', -18446744073709551615, -18446744073709551615, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551615, 18446744073709551615, 'hi'); +insert('hello', 18446744073709551615, 18446744073709551615, 'hi') +hello +select insert('hello', -18446744073709551616, -18446744073709551616, 'hi'); +insert('hello', -18446744073709551616, -18446744073709551616, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551616, 18446744073709551616, 'hi'); +insert('hello', 18446744073709551616, 18446744073709551616, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', -18446744073709551617, -18446744073709551617, 'hi'); +insert('hello', -18446744073709551617, -18446744073709551617, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select insert('hello', 18446744073709551617, 18446744073709551617, 'hi'); +insert('hello', 18446744073709551617, 18446744073709551617, 'hi') +hello +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', -1); +repeat('hello', -1) + +select repeat('hello', -4294967295); +repeat('hello', -4294967295) + +select repeat('hello', 4294967295); +repeat('hello', 4294967295) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -4294967296); +repeat('hello', -4294967296) + +select repeat('hello', 4294967296); +repeat('hello', 4294967296) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -4294967297); +repeat('hello', -4294967297) + +select repeat('hello', 4294967297); +repeat('hello', 4294967297) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551615); +repeat('hello', -18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551615); +repeat('hello', 18446744073709551615) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551616); +repeat('hello', -18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551616); +repeat('hello', 18446744073709551616) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select repeat('hello', -18446744073709551617); +repeat('hello', -18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select repeat('hello', 18446744073709551617); +repeat('hello', 18446744073709551617) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-1); +space(-1) + +select space(-4294967295); +space(-4294967295) + +select space(4294967295); +space(4294967295) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-4294967296); +space(-4294967296) + +select space(4294967296); +space(4294967296) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-4294967297); +space(-4294967297) + +select space(4294967297); +space(4294967297) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551615); +space(-18446744073709551615) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551615); +space(18446744073709551615) +NULL +Warnings: +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551616); +space(-18446744073709551616) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551616); +space(18446744073709551616) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select space(-18446744073709551617); +space(-18446744073709551617) + +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select space(18446744073709551617); +space(18446744073709551617) +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -1, '1'); +rpad('hello', -1, '1') +NULL +select rpad('hello', -4294967295, '1'); +rpad('hello', -4294967295, '1') +NULL +select rpad('hello', 4294967295, '1'); +rpad('hello', 4294967295, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -4294967296, '1'); +rpad('hello', -4294967296, '1') +NULL +select rpad('hello', 4294967296, '1'); +rpad('hello', 4294967296, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -4294967297, '1'); +rpad('hello', -4294967297, '1') +NULL +select rpad('hello', 4294967297, '1'); +rpad('hello', 4294967297, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551615, '1'); +rpad('hello', -18446744073709551615, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551615, '1'); +rpad('hello', 18446744073709551615, '1') +NULL +Warnings: +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551616, '1'); +rpad('hello', -18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551616, '1'); +rpad('hello', 18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select rpad('hello', -18446744073709551617, '1'); +rpad('hello', -18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select rpad('hello', 18446744073709551617, '1'); +rpad('hello', 18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -1, '1'); +lpad('hello', -1, '1') +NULL +select lpad('hello', -4294967295, '1'); +lpad('hello', -4294967295, '1') +NULL +select lpad('hello', 4294967295, '1'); +lpad('hello', 4294967295, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -4294967296, '1'); +lpad('hello', -4294967296, '1') +NULL +select lpad('hello', 4294967296, '1'); +lpad('hello', 4294967296, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -4294967297, '1'); +lpad('hello', -4294967297, '1') +NULL +select lpad('hello', 4294967297, '1'); +lpad('hello', 4294967297, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -18446744073709551615, '1'); +lpad('hello', -18446744073709551615, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551615, '1'); +lpad('hello', 18446744073709551615, '1') +NULL +Warnings: +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -18446744073709551616, '1'); +lpad('hello', -18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551616, '1'); +lpad('hello', 18446744073709551616, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated +select lpad('hello', -18446744073709551617, '1'); +lpad('hello', -18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +select lpad('hello', 18446744073709551617, '1'); +lpad('hello', 18446744073709551617, '1') +NULL +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +Error 1292 Truncated incorrect DECIMAL value: '' +Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 45415882ac7..9622de96143 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -780,4 +780,193 @@ SELECT * FROM t1 INNER JOIN t2 ON code=id DROP TABLE t1,t2; +# +# Bug #10963 +# 4294967296 18446744073709551616 + +select locate('he','hello',-2); +select locate('lo','hello',-4294967295); +select locate('lo','hello',4294967295); +select locate('lo','hello',-4294967296); +select locate('lo','hello',4294967296); +select locate('lo','hello',-4294967297); +select locate('lo','hello',4294967297); +select locate('lo','hello',-18446744073709551615); +select locate('lo','hello',18446744073709551615); +select locate('lo','hello',-18446744073709551616); +select locate('lo','hello',18446744073709551616); +select locate('lo','hello',-18446744073709551617); +select locate('lo','hello',18446744073709551617); + +select left('hello', 10); +select left('hello', 0); +select left('hello', -1); +select left('hello', -4294967295); +select left('hello', 4294967295); +select left('hello', -4294967296); +select left('hello', 4294967296); +select left('hello', -4294967297); +select left('hello', 4294967297); +select left('hello', -18446744073709551615); +select left('hello', 18446744073709551615); +select left('hello', -18446744073709551616); +select left('hello', 18446744073709551616); +select left('hello', -18446744073709551617); +select left('hello', 18446744073709551617); + +select right('hello', 10); +select right('hello', 0); +select right('hello', -1); +select right('hello', -4294967295); +select right('hello', 4294967295); +select right('hello', -4294967296); +select right('hello', 4294967296); +select right('hello', -4294967297); +select right('hello', 4294967297); +select right('hello', -18446744073709551615); +select right('hello', 18446744073709551615); +select right('hello', -18446744073709551616); +select right('hello', 18446744073709551616); +select right('hello', -18446744073709551617); +select right('hello', 18446744073709551617); + +select substring('hello', 2, -1); + +select substring('hello', -1, 1); +select substring('hello', -2, 1); +select substring('hello', -4294967295, 1); +select substring('hello', 4294967295, 1); +select substring('hello', -4294967296, 1); +select substring('hello', 4294967296, 1); +select substring('hello', -4294967297, 1); +select substring('hello', 4294967297, 1); +select substring('hello', -18446744073709551615, 1); +select substring('hello', 18446744073709551615, 1); +select substring('hello', -18446744073709551616, 1); +select substring('hello', 18446744073709551616, 1); +select substring('hello', -18446744073709551617, 1); +select substring('hello', 18446744073709551617, 1); +select substring('hello', 1, -1); +select substring('hello', 1, -4294967295); +select substring('hello', 1, 4294967295); +select substring('hello', 1, -4294967296); +select substring('hello', 1, 4294967296); +select substring('hello', 1, -4294967297); +select substring('hello', 1, 4294967297); +select substring('hello', 1, -18446744073709551615); +select substring('hello', 1, 18446744073709551615); +select substring('hello', 1, -18446744073709551616); +select substring('hello', 1, 18446744073709551616); +select substring('hello', 1, -18446744073709551617); +select substring('hello', 1, 18446744073709551617); +select substring('hello', -1, -1); +select substring('hello', -4294967295, -4294967295); +select substring('hello', 4294967295, 4294967295); +select substring('hello', -4294967296, -4294967296); +select substring('hello', 4294967296, 4294967296); +select substring('hello', -4294967297, -4294967297); +select substring('hello', 4294967297, 4294967297); +select substring('hello', -18446744073709551615, -18446744073709551615); +select substring('hello', 18446744073709551615, 18446744073709551615); +select substring('hello', -18446744073709551616, -18446744073709551616); +select substring('hello', 18446744073709551616, 18446744073709551616); +select substring('hello', -18446744073709551617, -18446744073709551617); +select substring('hello', 18446744073709551617, 18446744073709551617); + +select insert('hello', -1, 1, 'hi'); +select insert('hello', -4294967295, 1, 'hi'); +select insert('hello', 4294967295, 1, 'hi'); +select insert('hello', -4294967296, 1, 'hi'); +select insert('hello', 4294967296, 1, 'hi'); +select insert('hello', -4294967297, 1, 'hi'); +select insert('hello', 4294967297, 1, 'hi'); +select insert('hello', -18446744073709551615, 1, 'hi'); +select insert('hello', 18446744073709551615, 1, 'hi'); +select insert('hello', -18446744073709551616, 1, 'hi'); +select insert('hello', 18446744073709551616, 1, 'hi'); +select insert('hello', -18446744073709551617, 1, 'hi'); +select insert('hello', 18446744073709551617, 1, 'hi'); +select insert('hello', 1, -1, 'hi'); +select insert('hello', 1, -4294967295, 'hi'); +select insert('hello', 1, 4294967295, 'hi'); +select insert('hello', 1, -4294967296, 'hi'); +select insert('hello', 1, 4294967296, 'hi'); +select insert('hello', 1, -4294967297, 'hi'); +select insert('hello', 1, 4294967297, 'hi'); +select insert('hello', 1, -18446744073709551615, 'hi'); +select insert('hello', 1, 18446744073709551615, 'hi'); +select insert('hello', 1, -18446744073709551616, 'hi'); +select insert('hello', 1, 18446744073709551616, 'hi'); +select insert('hello', 1, -18446744073709551617, 'hi'); +select insert('hello', 1, 18446744073709551617, 'hi'); +select insert('hello', -1, -1, 'hi'); +select insert('hello', -4294967295, -4294967295, 'hi'); +select insert('hello', 4294967295, 4294967295, 'hi'); +select insert('hello', -4294967296, -4294967296, 'hi'); +select insert('hello', 4294967296, 4294967296, 'hi'); +select insert('hello', -4294967297, -4294967297, 'hi'); +select insert('hello', 4294967297, 4294967297, 'hi'); +select insert('hello', -18446744073709551615, -18446744073709551615, 'hi'); +select insert('hello', 18446744073709551615, 18446744073709551615, 'hi'); +select insert('hello', -18446744073709551616, -18446744073709551616, 'hi'); +select insert('hello', 18446744073709551616, 18446744073709551616, 'hi'); +select insert('hello', -18446744073709551617, -18446744073709551617, 'hi'); +select insert('hello', 18446744073709551617, 18446744073709551617, 'hi'); + +select repeat('hello', -1); +select repeat('hello', -4294967295); +select repeat('hello', 4294967295); +select repeat('hello', -4294967296); +select repeat('hello', 4294967296); +select repeat('hello', -4294967297); +select repeat('hello', 4294967297); +select repeat('hello', -18446744073709551615); +select repeat('hello', 18446744073709551615); +select repeat('hello', -18446744073709551616); +select repeat('hello', 18446744073709551616); +select repeat('hello', -18446744073709551617); +select repeat('hello', 18446744073709551617); + +select space(-1); +select space(-4294967295); +select space(4294967295); +select space(-4294967296); +select space(4294967296); +select space(-4294967297); +select space(4294967297); +select space(-18446744073709551615); +select space(18446744073709551615); +select space(-18446744073709551616); +select space(18446744073709551616); +select space(-18446744073709551617); +select space(18446744073709551617); + +select rpad('hello', -1, '1'); +select rpad('hello', -4294967295, '1'); +select rpad('hello', 4294967295, '1'); +select rpad('hello', -4294967296, '1'); +select rpad('hello', 4294967296, '1'); +select rpad('hello', -4294967297, '1'); +select rpad('hello', 4294967297, '1'); +select rpad('hello', -18446744073709551615, '1'); +select rpad('hello', 18446744073709551615, '1'); +select rpad('hello', -18446744073709551616, '1'); +select rpad('hello', 18446744073709551616, '1'); +select rpad('hello', -18446744073709551617, '1'); +select rpad('hello', 18446744073709551617, '1'); + +select lpad('hello', -1, '1'); +select lpad('hello', -4294967295, '1'); +select lpad('hello', 4294967295, '1'); +select lpad('hello', -4294967296, '1'); +select lpad('hello', 4294967296, '1'); +select lpad('hello', -4294967297, '1'); +select lpad('hello', 4294967297, '1'); +select lpad('hello', -18446744073709551615, '1'); +select lpad('hello', 18446744073709551615, '1'); +select lpad('hello', -18446744073709551616, '1'); +select lpad('hello', 18446744073709551616, '1'); +select lpad('hello', -18446744073709551617, '1'); +select lpad('hello', 18446744073709551617, '1'); + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index ca71701841b..fa953889619 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2313,21 +2313,27 @@ longlong Item_func_locate::val_int() return 0; /* purecov: inspected */ } null_value=0; - uint start=0; - uint start0=0; + /* must be longlong to avoid truncation */ + longlong start= 0; + longlong start0= 0; my_match_t match; if (arg_count == 3) { - start0= start =(uint) args[2]->val_int()-1; - start=a->charpos(start); - - if (start > a->length() || start+b->length() > a->length()) + start0= start= args[2]->val_int() - 1; + + if ((start < 0) || (start > a->length())) + return 0; + + /* start is now sufficiently valid to pass to charpos function */ + start= a->charpos(start); + + if (start + b->length() > a->length()) return 0; } if (!b->length()) // Found empty string at start - return (longlong) (start+1); + return start + 1; if (!cmp_collation.collation->coll->instr(cmp_collation.collation, a->ptr()+start, a->length()-start, diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4f3e280fc8a..c2f16ffac10 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -951,22 +951,33 @@ String *Item_func_insert::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res,*res2; - uint start,length; + longlong start, length; /* must be longlong to avoid truncation */ null_value=0; res=args[0]->val_str(str); res2=args[3]->val_str(&tmp_value); - start=(uint) args[1]->val_int()-1; - length=(uint) args[2]->val_int(); + start= args[1]->val_int() - 1; + length= args[2]->val_int(); + if (args[0]->null_value || args[1]->null_value || args[2]->null_value || args[3]->null_value) goto null; /* purecov: inspected */ - start=res->charpos(start); - length=res->charpos(length,start); - if (start > res->length()+1) - return res; // Wrong param; skip insert - if (length > res->length()-start) - length=res->length()-start; + + if ((start < 0) || (start > res->length() + 1)) + return res; // Wrong param; skip insert + if ((length < 0) || (length > res->length() + 1)) + length= res->length() + 1; + + /* start and length are now sufficiently valid to pass to charpos function */ + start= res->charpos(start); + length= res->charpos(length, start); + + /* Re-testing with corrected params */ + if (start > res->length() + 1) + return res; // Wrong param; skip insert + if (length > res->length() - start) + length= res->length() - start; + if (res->length() - length + res2->length() > current_thd->variables.max_allowed_packet) { @@ -1039,16 +1050,21 @@ String *Item_str_conv::val_str(String *str) String *Item_func_left::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); - long length =(long) args[1]->val_int(); + String *res= args[0]->val_str(str); + + /* must be longlong to avoid truncation */ + longlong length= args[1]->val_int(); uint char_pos; if ((null_value=(args[0]->null_value || args[1]->null_value))) return 0; - if (length <= 0) + + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + if ((length <= 0) && (!args[1]->unsigned_flag)) return &my_empty_string; - if (res->length() <= (uint) length || - res->length() <= (char_pos= res->charpos(length))) + + if ((res->length() <= (ulonglong) length) || + (res->length() <= (char_pos= res->charpos(length)))) return res; tmp_value.set(*res, 0, char_pos); @@ -1080,14 +1096,18 @@ void Item_func_left::fix_length_and_dec() String *Item_func_right::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); - long length =(long) args[1]->val_int(); + String *res= args[0]->val_str(str); + /* must be longlong to avoid truncation */ + longlong length= args[1]->val_int(); if ((null_value=(args[0]->null_value || args[1]->null_value))) return 0; /* purecov: inspected */ - if (length <= 0) + + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + if ((length <= 0) && (!args[1]->unsigned_flag)) return &my_empty_string; /* purecov: inspected */ - if (res->length() <= (uint) length) + + if (res->length() <= (ulonglong) length) return res; /* purecov: inspected */ uint start=res->numchars(); @@ -1110,25 +1130,43 @@ String *Item_func_substr::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); - int32 start = (int32) args[1]->val_int(); - int32 length = arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32; - int32 tmp_length; + /* must be longlong to avoid truncation */ + longlong start= args[1]->val_int(); + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Limit so that code sees out-of-bound value properly. */ + longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32; + longlong tmp_length; if ((null_value=(args[0]->null_value || args[1]->null_value || (arg_count == 3 && args[2]->null_value)))) return 0; /* purecov: inspected */ - start= (int32)((start < 0) ? res->numchars() + start : start -1); - start=res->charpos(start); - length=res->charpos(length,start); - if (start < 0 || (uint) start+1 > res->length() || length <= 0) + + /* Negative length, will return empty string. */ + if ((arg_count == 3) && (length <= 0) && !args[2]->unsigned_flag) return &my_empty_string; - tmp_length=(int32) res->length()-start; - length=min(length,tmp_length); + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((length <= 0) || (length > INT_MAX32)) + length= INT_MAX32; - if (!start && res->length() == (uint) length) + /* if "unsigned_flag" is set, we have a *huge* positive number. */ + /* Assumes that the maximum length of a String is < INT_MAX32. */ + if ((args[1]->unsigned_flag) || (start < INT_MIN32) || (start > INT_MAX32)) + return &my_empty_string; + + start= ((start < 0) ? res->numchars() + start : start - 1); + start= res->charpos(start); + if ((start < 0) || ((uint) start + 1 > res->length())) + return &my_empty_string; + + length= res->charpos(length, start); + tmp_length= res->length() - start; + length= min(length, tmp_length); + + if (!start && res->length() == (ulonglong) length) return res; - tmp_value.set(*res,(uint) start,(uint) length); + tmp_value.set(*res, (ulonglong) start, (ulonglong) length); return &tmp_value; } @@ -2141,8 +2179,15 @@ void Item_func_repeat::fix_length_and_dec() collation.set(args[0]->collation); if (args[1]->const_item()) { - ulonglong max_result_length= ((ulonglong) args[0]->max_length * - args[1]->val_int()); + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (count > INT_MAX32) + count= INT_MAX32; + + ulonglong max_result_length= (ulonglong) args[0]->max_length * count; if (max_result_length >= MAX_BLOB_WIDTH) { max_result_length= MAX_BLOB_WIDTH; @@ -2167,13 +2212,20 @@ String *Item_func_repeat::val_str(String *str) DBUG_ASSERT(fixed == 1); uint length,tot_length; char *to; - long count= (long) args[1]->val_int(); - String *res =args[0]->val_str(str); + /* must be longlong to avoid truncation */ + longlong tmp_count= args[1]->val_int(); + long count= tmp_count; + String *res= args[0]->val_str(str); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Bounds check on count: If this is triggered, we will error. */ + if ((tmp_count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; if (args[0]->null_value || args[1]->null_value) goto err; // string and/or delim are null - null_value=0; - if (count <= 0) // For nicer SQL code + null_value= 0; + if ((tmp_count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code return &my_empty_string; if (count == 1) // To avoid reallocs return res; @@ -2212,8 +2264,20 @@ void Item_func_rpad::fix_length_and_dec() return; if (args[1]->const_item()) { - ulonglong length= ((ulonglong) args[1]->val_int() * - collation.collation->mbmaxlen); + ulonglong length= 0; + + if (collation.collation->mbmaxlen > 0) + { + ulonglong temp= (ulonglong) args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (temp > INT_MAX32) + temp = INT_MAX32; + + length= temp * collation.collation->mbmaxlen; + } + if (length >= MAX_BLOB_WIDTH) { length= MAX_BLOB_WIDTH; @@ -2235,21 +2299,30 @@ String *Item_func_rpad::val_str(String *str) uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length; char *to; const char *ptr_pad; - int32 count= (int32) args[1]->val_int(); - int32 byte_count= count * collation.collation->mbmaxlen; - String *res =args[0]->val_str(str); - String *rpad = args[2]->val_str(&rpad_str); + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + longlong byte_count; + String *res= args[0]->val_str(str); + String *rpad= args[2]->val_str(&rpad_str); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; if (!res || args[1]->null_value || !rpad || count < 0) goto err; null_value=0; - if (count <= (int32) (res_char_length=res->numchars())) + + if (count <= (res_char_length= res->numchars())) { // String to pad is big enough res->length(res->charpos(count)); // Shorten result if longer return (res); } pad_char_length= rpad->numchars(); - if ((ulong) byte_count > current_thd->variables.max_allowed_packet) + + byte_count= count * collation.collation->mbmaxlen; + if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet) { push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, @@ -2295,8 +2368,20 @@ void Item_func_lpad::fix_length_and_dec() if (args[1]->const_item()) { - ulonglong length= ((ulonglong) args[1]->val_int() * - collation.collation->mbmaxlen); + ulonglong length= 0; + + if (collation.collation->mbmaxlen > 0) + { + ulonglong temp= (ulonglong) args[1]->val_int(); + + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if (temp > INT_MAX32) + temp= INT_MAX32; + + length= temp * collation.collation->mbmaxlen; + } + if (length >= MAX_BLOB_WIDTH) { length= MAX_BLOB_WIDTH; @@ -2316,13 +2401,19 @@ String *Item_func_lpad::val_str(String *str) { DBUG_ASSERT(fixed == 1); uint32 res_char_length,pad_char_length; - ulong count= (long) args[1]->val_int(), byte_count; + /* must be longlong to avoid truncation */ + longlong count= args[1]->val_int(); + longlong byte_count; String *res= args[0]->val_str(&tmp_value); String *pad= args[2]->val_str(&lpad_str); - if (!res || args[1]->null_value || !pad) - goto err; + /* Assumes that the maximum length of a String is < INT_MAX32. */ + /* Set here so that rest of code sees out-of-bound value as such. */ + if ((count > INT_MAX32) || args[1]->unsigned_flag) + count= INT_MAX32; + if (!res || args[1]->null_value || !pad || count < 0) + goto err; null_value=0; res_char_length= res->numchars(); From c98a6dc8af717444330dc18e14e029b189144861 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 22:45:52 +0100 Subject: [PATCH 3/7] Don't run mysqltest with both --silent and --verbose --- mysql-test/mysql-test-run.pl | 3 --- 1 file changed, 3 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 465d058f97a..3bcb735890c 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2974,7 +2974,6 @@ sub analyze_testcase_failure_sync_with_master($) mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); @@ -4160,7 +4159,6 @@ sub run_check_testcase ($$) { mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); @@ -4206,7 +4204,6 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--no-defaults"); mtr_add_arg($args, "--silent"); - mtr_add_arg($args, "-v"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); From 427f1acaaaeb8967462ae712dc6623f0310e34a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 22:53:40 +0100 Subject: [PATCH 4/7] Pass location of charsets dir to mysqltest to avoid using the charsetdir locally installed on machine. client/mysqltest.c: Add new option --character-sets-dir to mysqltest Set MYSQL_SET_CHRSET_DIR before connecting to mysqld if the above variable is set mysql-test/mysql-test-run.pl: Pass $path_charsetsdir to mysqltest --- client/mysqltest.c | 20 +++++++++++++++----- mysql-test/mysql-test-run.pl | 3 +++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 7c1ce19283f..9ad2f3df5de 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -80,13 +80,13 @@ enum { OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES, - OPT_MARK_PROGRESS + OPT_MARK_PROGRESS, OPT_CHARSETS_DIR }; static int record= 0, opt_sleep= -1; static char *db= 0, *pass= 0; const char *user= 0, *host= 0, *unix_sock= 0, *opt_basedir= "./"; -const char *opt_include= 0; +const char *opt_include= 0, *opt_charsets_dir; static int port= 0; static int opt_max_connect_retries; static my_bool opt_compress= 0, silent= 0, verbose= 0; @@ -145,7 +145,6 @@ static struct st_test_file* file_stack_end; static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */ -static const char *charset_name= "latin1"; /* Default character set name */ static const char *embedded_server_groups[]= { @@ -3093,7 +3092,11 @@ void do_connect(struct st_command *command) if (opt_compress || con_compress) mysql_options(&next_con->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); - mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); + mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, + charset_info->csname); + if (opt_charsets_dir) + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR, + opt_charsets_dir); #ifdef HAVE_OPENSSL if (opt_use_ssl || con_ssl) @@ -3779,6 +3782,9 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir, (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"character-sets-dir", OPT_CHARSETS_DIR, + "Directory where character sets are.", (gptr*) &opt_charsets_dir, + (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use the compressed server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5511,7 +5517,11 @@ int main(int argc, char **argv) if (opt_compress) mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS); mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); - mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, + charset_info->csname); + if (opt_charsets_dir) + mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR, + opt_charsets_dir); #ifdef HAVE_OPENSSL diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 3bcb735890c..f1c7897e975 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2976,6 +2976,7 @@ sub analyze_testcase_failure_sync_with_master($) mtr_add_arg($args, "--silent"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'}); mtr_add_arg($args, "--port=%d", $master->[0]->{'port'}); @@ -4161,6 +4162,7 @@ sub run_check_testcase ($$) { mtr_add_arg($args, "--silent"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'}); mtr_add_arg($args, "--port=%d", $mysqld->{'port'}); @@ -4206,6 +4208,7 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--silent"); mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir); + mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir); if ($tinfo->{'component_id'} eq 'im') { From 26e6d78845deae2392bd9b06fe8a1592c8f39669 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 22:56:06 +0100 Subject: [PATCH 5/7] No need to pass an additional arg to to mtr_add_arg when there is no % sign --- mysql-test/mysql-test-run.pl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f1c7897e975..e89fa21d610 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4293,13 +4293,11 @@ sub run_mysqltest ($) { if ( $opt_ssl ) { # Turn on SSL for _all_ test cases if option --ssl was used - mtr_add_arg($args, "--ssl", - $glob_mysql_test_dir); + mtr_add_arg($args, "--ssl"); } elsif ( $opt_ssl_supported ) { - mtr_add_arg($args, "--skip-ssl", - $glob_mysql_test_dir); + mtr_add_arg($args, "--skip-ssl"); } # ---------------------------------------------------------------------- From d3b049a6bf104c42b84d1bd9f462c3df9f7602f0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Nov 2006 23:16:44 +0100 Subject: [PATCH 6/7] Update of --mem flag after comments mysql-test/mysql-test-run.pl: Allow --mem to be specified as a flag or --mem= Add /tmp to locations to search Update comments and usage description --- mysql-test/mysql-test-run.pl | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e89fa21d610..9bf0f8df632 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -667,7 +667,7 @@ sub command_line_setup () { 'tmpdir=s' => \$opt_tmpdir, 'vardir=s' => \$opt_vardir, 'benchdir=s' => \$glob_mysql_bench_dir, - 'mem' => \$opt_mem, + 'mem:s' => \$opt_mem, # Misc 'comment=s' => \$opt_comment, @@ -747,17 +747,18 @@ sub command_line_setup () { # -------------------------------------------------------------------------- # Check if we should speed up tests by trying to run on tmpfs # -------------------------------------------------------------------------- - if ( $opt_mem ) + if ( defined $opt_mem ) { mtr_error("Can't use --mem and --vardir at the same time ") if $opt_vardir; mtr_error("Can't use --mem and --tmpdir at the same time ") if $opt_tmpdir; - # Use /dev/shm as the preferred location for vardir and - # thus implicitly also tmpdir. Add other locations to list - my @tmpfs_locations= ($opt_mem, "/dev/shm"); - # One could maybe use "mount" to find tmpfs location(s) + # Search through list of locations that are known + # to be "fast disks" to list to find a suitable location + # Use --mem= as first location to look. + my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp"); + foreach my $fs (@tmpfs_locations) { if ( -d $fs ) @@ -4630,9 +4631,12 @@ Options to control directories to use vardir=DIR The directory where files generated from the test run is stored (default: ./var). Specifying a ramdisk or tmpfs will speed up tests. - mem Run testsuite in "memory" using tmpfs if - available(default: /dev/shm) - reads path from MTR_MEM environment variable + mem[=DIR] Run testsuite in "memory" using tmpfs or ramdisk + Attempts to use DIR first if specified else + uses as builtin list of standard locations + for tmpfs (/dev/shm) + The option can also be set using environment + variable MTR_MEM=[DIR] Options to control what test suites or cases to run From 0100c53f9deeaab395b39d25f643489a44559920 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Nov 2006 00:17:22 +0100 Subject: [PATCH 7/7] Fix warnings and NetWare compile failure client/mysql_upgrade.c: Fix NetWare problem - illegal cast of "const char*" to "char*" Fix warning, init "mystat" in FILEINFO to NULL Fix warning, remove unused variable "i" --- client/mysql_upgrade.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index e5855aee605..b8344606448 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -378,7 +378,7 @@ find_file(const char *name, const char *root, uint flags, char *result, size_t l { int ret; va_list va; - FILEINFO key= { name }; + FILEINFO key= { (char*)name, NULL }; const char *subdir; char *cp; @@ -395,7 +395,6 @@ find_file(const char *name, const char *root, uint flags, char *result, size_t l { MY_DIR *dir; FILEINFO *match; - uint i; char *cp1; cp1= strnmov(cp + 1, subdir, len - (cp - result) - 1);