From 77b8a94d7a767291f90d57f0e667b421c5f41037 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Jan 2005 22:35:53 +0100 Subject: [PATCH 1/7] make the code to look safe, not only be safe --- ndb/src/common/util/strdup.c | 4 ++-- sql/log.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ndb/src/common/util/strdup.c b/ndb/src/common/util/strdup.c index afe2306427e..d8f4d99bd28 100644 --- a/ndb/src/common/util/strdup.c +++ b/ndb/src/common/util/strdup.c @@ -21,8 +21,8 @@ char * strdup(const char *s){ void *p2; - p2 = malloc(strlen(s)+1); - strcpy(p2, s); + if ((p2 = malloc(strlen(s)+1))) + strcpy(p2, s); return p2; } #endif diff --git a/sql/log.cc b/sql/log.cc index 4504b286506..38844877f1b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2247,9 +2247,9 @@ void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, DBUG_ENTER("print_buffer_to_nt_eventlog"); buffptr= buff; - if (length > (uint)(buffLen-4)) + if (length > (uint)(buffLen-5)) { - char *newBuff= new char[length + 4]; + char *newBuff= new char[length + 5]; strcpy(newBuff, buff); buffptr= newBuff; } From f003895df9f562018ba47e5f7af2eae03d937368 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Jan 2005 11:27:38 +0100 Subject: [PATCH 2/7] myisam/ft_boolean_search.c -trunc* bug - don't increase yweaks in this case myisam/ft_boolean_search.c: -trunc* bug - don't increase yweaks in this case mysql-test/r/fulltext.result: -trunc* bug - don't increase yweaks in this case mysql-test/t/fulltext.test: -trunc* bug - don't increase yweaks in this case --- myisam/ft_boolean_search.c | 11 ++++++----- mysql-test/r/fulltext.result | 3 +++ mysql-test/t/fulltext.test | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index ffc7e1bf104..aab3854dd34 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -345,11 +345,12 @@ static void _ftb_init_index_search(FT_INFO *ftb) if (ftbe->flags & FTB_FLAG_NO || /* 2 */ ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */ { - FTB_EXPR *top_ftbe=ftbe->up->up; + FTB_EXPR *top_ftbe=ftbe->up; ftbw->docid[0]=HA_OFFSET_ERROR; - for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up) - if (!(ftbe->flags & FTB_FLAG_NO)) - ftbe->yweaks++; + for (ftbe=(FTB_EXPR *)ftbw; + ftbe != top_ftbe && !(ftbe->flags & FTB_FLAG_NO); + ftbe=ftbe->up) + ftbe->up->yweaks++; ftbe=0; break; } @@ -363,7 +364,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) else reset_tree(& ftb->no_dupes); } - + if (_ft2_search(ftb, ftbw, 1)) return; } diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 7acc8a2d23f..a042248ba34 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -148,6 +148,9 @@ select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN B a b select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE); a b +select * from t1 where MATCH a,b AGAINST ('+collections -supp* -foobar*' IN BOOLEAN MODE); +a b +Full-text indexes are called collections select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); a b select * from t1 where MATCH a,b AGAINST('"space model' IN BOOLEAN MODE); diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 008e965297f..62dcecaff68 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -67,6 +67,7 @@ select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('+(support collections) +foobar*' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('+(+(support collections)) +foobar*' IN BOOLEAN MODE); +select * from t1 where MATCH a,b AGAINST ('+collections -supp* -foobar*' IN BOOLEAN MODE); select * from t1 where MATCH a,b AGAINST ('"xt indexes"' IN BOOLEAN MODE); # bug#2708, bug#3870 crash From faff1cda2bd0c45daf32768f3c2daef9eb0b48a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Jan 2005 12:23:24 -0800 Subject: [PATCH 3/7] Warn when mysqld starts up with lower_case_table_names=2 but datadir is on a case-sensitive filesystem. (Bug #7887) sql/mysqld.cc: Add warning when running with lower_case_table_names=2 and datadir is on a case-sensitive filesystem. --- sql/mysqld.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d1fef3519bf..b21b84a34e7 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2913,6 +2913,17 @@ You should consider changing lower_case_table_names to 1 or 2", lower_case_table_names= 2; } } + else if (lower_case_table_names == 2 && + (test_if_case_insensitive(mysql_real_data_home) == 0)) + { + if (global_system_variables.log_warnings) + sql_print_warning("\ +You have forced lower_case_table_names to 2 through a command-line \ +option, even though your file system '%s' is case sensitive. This means \ +that you can create a table that you can then no longer access. \ +You should consider changing lower_case_table_names to 0.", + mysql_real_data_home); + } select_thread=pthread_self(); select_thread_in_use=1; From 8bdb500105f97e3007e652f73d99c373d38f2aad Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 15:48:25 +0100 Subject: [PATCH 4/7] fixes/cleanups according to Coverity report --- client/mysql.cc | 13 +++------- client/mysqlbinlog.cc | 6 +---- client/mysqldump.c | 5 ++-- client/mysqltest.c | 5 ++-- isam/sort.c | 3 +++ myisam/mi_packrec.c | 7 ----- myisam/rt_index.c | 7 +++-- myisam/sort.c | 3 +++ mysys/mf_keycache.c | 1 + mysys/thr_alarm.c | 2 +- sql/item.cc | 24 +++++------------- sql/item_create.cc | 13 ++++------ sql/item_strfunc.cc | 3 +++ sql/item_timefunc.cc | 23 ++++++++++------- sql/set_var.cc | 4 +-- sql/slave.cc | 11 ++++---- sql/sql_acl.cc | 14 ++++++---- sql/sql_acl.h | 2 +- sql/sql_analyse.cc | 59 +++++++++++++++++++++++-------------------- sql/sql_base.cc | 18 ++++++------- sql/sql_cache.cc | 10 ++++---- sql/sql_db.cc | 22 ++++++++-------- sql/sql_lex.cc | 3 --- sql/sql_parse.cc | 29 ++++++++++----------- sql/sql_table.cc | 4 +-- sql/sql_update.cc | 9 +++---- sql/table.cc | 10 +++++--- sql/tztime.cc | 2 +- tests/client_test.c | 6 +++++ 29 files changed, 156 insertions(+), 162 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 480a0deb347..635973e946c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1430,12 +1430,6 @@ static void build_completion_hash(bool rehash, bool write_info) if (status.batch || quick || !current_db) DBUG_VOID_RETURN; // We don't need completion in batches - if (tables) - { - mysql_free_result(tables); - tables=0; - } - /* hash SQL commands */ while (cmd->name) { add_word(&ht,(char*) cmd->name); @@ -1681,8 +1675,8 @@ static int com_server_help(String *buffer __attribute__((unused)), else if (num_fields >= 2 && num_rows) { init_pager(); - char last_char; - + char last_char= 0; + int num_name= 0, num_cat= 0; LINT_INIT(num_name); LINT_INIT(num_cat); @@ -1693,7 +1687,6 @@ static int com_server_help(String *buffer __attribute__((unused)), put_info("To make a more specific request, please type 'help ',\nwhere is one of the following", INFO_INFO); num_name= 0; num_cat= 1; - last_char= '_'; } else if ((cur= mysql_fetch_row(result))) { @@ -1703,7 +1696,7 @@ static int com_server_help(String *buffer __attribute__((unused)), num_cat= 2; print_help_item(&cur,1,2,&last_char); } - + while ((cur= mysql_fetch_row(result))) print_help_item(&cur,num_name,num_cat,&last_char); tee_fprintf(PAGER, "\n"); diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index de53831c43d..7ddb01d9ec8 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -717,11 +717,7 @@ static int check_master_version(MYSQL* mysql) if (mysql_query(mysql, "SELECT VERSION()") || !(res = mysql_store_result(mysql))) - { - mysql_close(mysql); - die("Error checking master version: %s", - mysql_error(mysql)); - } + die("Error checking master version: %s", mysql_error(mysql)); if (!(row = mysql_fetch_row(res))) { mysql_free_result(res); diff --git a/client/mysqldump.c b/client/mysqldump.c index 7280bea43f3..00f5272e3d7 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2328,14 +2328,13 @@ static const char *check_if_ignore_table(const char *table_name) fprintf(stderr, "Error: Couldn't read status information for table %s (%s)\n", table_name, mysql_error(sock)); - if (res) - mysql_free_result(res); + mysql_free_result(res); return 0; /* assume table is ok */ } if (strcmp(row[1], (result= "MRG_MyISAM")) && strcmp(row[1], (result= "MRG_ISAM"))) result= 0; - mysql_free_result(res); + mysql_free_result(res); return result; } diff --git a/client/mysqltest.c b/client/mysqltest.c index abacd73d878..d81e199ab1f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -715,9 +715,10 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw, die("Empty variable"); } length= (uint) (var_name - save_var_name); + if (length >= MAX_VAR_NAME) + die("Too long variable name: %s", save_var_name); - if (!(v = (VAR*) hash_search(&var_hash, save_var_name, length)) && - length < MAX_VAR_NAME) + if (!(v = (VAR*) hash_search(&var_hash, save_var_name, length))) { char buff[MAX_VAR_NAME+1]; strmake(buff, save_var_name, length); diff --git a/isam/sort.c b/isam/sort.c index d22b0e648a0..5d13f8085d2 100644 --- a/isam/sort.c +++ b/isam/sort.c @@ -122,7 +122,10 @@ uint sortbuff_size; MYF(0)))) break; else + { my_free((gptr) sort_keys,MYF(0)); + sort_keys= 0; + } } old_memavl=memavl; if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index a277c2ca9d1..1a71d43a7f1 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -182,21 +182,14 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) my_malloc((length+OFFSET_TABLE_SIZE)*sizeof(uint16)+ (uint) (share->pack.header_length+7), MYF(MY_WME | MY_ZEROFILL)))) - { - my_free((gptr) share->decode_trees,MYF(0)); goto err1; - } tmp_buff=share->decode_tables+length; disk_cache=(byte*) (tmp_buff+OFFSET_TABLE_SIZE); if (my_read(file,disk_cache, (uint) (share->pack.header_length-sizeof(header)), MYF(MY_NABP))) - { - my_free((gptr) share->decode_trees,MYF(0)); - my_free((gptr) share->decode_tables,MYF(0)); goto err2; - } huff_tree_bits=max_bit(trees ? trees-1 : 0); init_bit_buffer(&bit_buff, (uchar*) disk_cache, diff --git a/myisam/rt_index.c b/myisam/rt_index.c index bdf5ee9c60f..97554dca4e6 100644 --- a/myisam/rt_index.c +++ b/myisam/rt_index.c @@ -948,15 +948,14 @@ int rtree_delete(MI_INFO *info, uint keynr, uchar *key, uint key_length) /* check for redundant root (not leaf, 1 child) and eliminate */ if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR) goto err1; - if (!_mi_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, + if (!_mi_fetch_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff, 0)) goto err1; nod_flag = mi_test_if_nod(info->buff); page_size = mi_getint(info->buff); - if (nod_flag && (page_size == 2 + key_length + - (nod_flag ? nod_flag : info->s->base.rec_reflength))) + if (nod_flag && (page_size == 2 + key_length + nod_flag)) { - my_off_t new_root = _mi_kpos(nod_flag, + my_off_t new_root = _mi_kpos(nod_flag, rt_PAGE_FIRST_KEY(info->buff, nod_flag)); if (_mi_dispose(info, keyinfo, old_root, DFLT_INIT_HITS)) goto err1; diff --git a/myisam/sort.c b/myisam/sort.c index 39bde41e4c9..7c6efa9a05b 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -162,7 +162,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, { if (my_init_dynamic_array(&buffpek, sizeof(BUFFPEK), maxbuffer, maxbuffer/2)) + { my_free((gptr) sort_keys,MYF(0)); + sort_keys= 0; + } else break; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 052d6c79ab9..c246e9b320c 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -352,6 +352,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, MYF(0)))) break; my_free_lock(keycache->block_mem, MYF(0)); + keycache->block_mem= 0; } if (blocks < 8) { diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index caef1caaf3d..19611a6027a 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -248,7 +248,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) if (alarm_data->malloced) my_free((gptr) alarm_data,MYF(0)); found++; -#ifndef DBUG_OFF +#ifdef DBUG_OFF break; #endif } diff --git a/sql/item.cc b/sql/item.cc index 92a15694e89..eda569378be 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1444,7 +1444,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ¬_used)) != (Item **) not_found_item) { - if (*refer && (*refer)->fixed) // Avoid crash in case of error + if (refer && (*refer)->fixed) // Avoid crash in case of error { prev_subselect_item->used_tables_cache|= (*refer)->used_tables(); prev_subselect_item->const_item_cache&= (*refer)->const_item(); @@ -2057,7 +2057,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) if (!ref) { TABLE_LIST *where= 0, *table_list; - bool upward_lookup= 0; SELECT_LEX_UNIT *prev_unit= thd->lex->current_select->master_unit(); SELECT_LEX *sl= prev_unit->outer_select(); /* @@ -2078,7 +2077,6 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { Field *tmp= (Field*) not_found_field; SELECT_LEX *last= 0; - upward_lookup= 1; /* We can't find table field in select list of current select, consequently we have to find it in outer subselect(s). @@ -2098,7 +2096,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ¬_used)) != (Item **)not_found_item) { - if (*ref && (*ref)->fixed) // Avoid crash in case of error + if (ref && (*ref)->fixed) // Avoid crash in case of error { prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); prev_subselect_item->const_item_cache&= (*ref)->const_item(); @@ -2142,20 +2140,10 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) return -1; if (ref == (Item **)not_found_item && tmp == not_found_field) { - if (upward_lookup) - { - // We can't say exactly what absend (table or field) - my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), - full_name(), thd->where); - } - else - { - // Call to report error - find_item_in_list(this, - *(thd->lex->current_select->get_item_list()), - &counter, REPORT_ALL_ERRORS, ¬_used); - } - ref= 0; // Safety + // We can't say exactly what absend (table or field) + my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0), + full_name(), thd->where); + ref= 0; // Safety return 1; } if (tmp != not_found_field) diff --git a/sql/item_create.cc b/sql/item_create.cc index 800489a6a72..99db184e71f 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -365,22 +365,19 @@ Item *create_func_sin(Item* a) Item *create_func_sha(Item* a) { - return new Item_func_sha(a); + return new Item_func_sha(a); } - + Item *create_func_space(Item *a) { CHARSET_INFO *cs= current_thd->variables.collation_connection; Item *sp; - + if (cs->mbminlen > 1) { + uint dummy_errors; sp= new Item_string("",0,cs); - if (sp) - { - uint dummy_errors; - sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); - } + sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); } else { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f131d849d62..cd98fb62818 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2489,6 +2489,9 @@ String* Item_func_export_set::val_str(String* str) case 3: sep_buf.set(",", 1, default_charset()); sep = &sep_buf; + break; + default: + DBUG_ASSERT(0); // cannot happen } null_value=0; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index f9c9d1f013d..39c88c8b0a3 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2112,20 +2112,25 @@ void Item_char_typecast::print(String *str) String *Item_char_typecast::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res, *res1; + String *res; uint32 length; - if (!charset_conversion && !(res= args[0]->val_str(str))) +#if 0 + if (!charset_conversion) { - null_value= 1; - return 0; + if (!(res= args[0]->val_str(str))) + { + null_value= 1; + return 0; + } } else +#endif { // Convert character set if differ uint dummy_errors; - if (!(res1= args[0]->val_str(&tmp_value)) || - str->copy(res1->ptr(), res1->length(), res1->charset(), + if (!(res= args[0]->val_str(&tmp_value)) || + str->copy(res->ptr(), res->length(), res->charset(), cast_cs, &dummy_errors)) { null_value= 1; @@ -2135,13 +2140,13 @@ String *Item_char_typecast::val_str(String *str) } res->set_charset(cast_cs); - + /* Cut the tail if cast with length and the result is longer than cast length, e.g. CAST('string' AS CHAR(1)) */ - if (cast_length >= 0 && + if (cast_length >= 0 && (res->length() > (length= (uint32) res->charpos(cast_length)))) { // Safe even if const arg if (!res->alloced_length()) @@ -2150,7 +2155,7 @@ String *Item_char_typecast::val_str(String *str) res= &str_value; } res->length((uint) length); - } + } null_value= 0; return res; } diff --git a/sql/set_var.cc b/sql/set_var.cc index e44ac742abe..3d21e6db069 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2912,8 +2912,8 @@ int set_var_password::check(THD *thd) if (!user->host.str) user->host.str= (char*) thd->host_or_ip; /* Returns 1 as the function sends error to client */ - return check_change_password(thd, user->host.str, user->user.str, password) ? - 1 : 0; + return check_change_password(thd, user->host.str, user->user.str, + password, strlen(password)) ? 1 : 0; #else return 0; #endif diff --git a/sql/slave.cc b/sql/slave.cc index ef9caa5f5b5..75f51437d0c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2422,18 +2422,19 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, init_abort_pos_wait= abort_pos_wait; /* - We'll need to + We'll need to handle all possible log names comparisons (e.g. 999 vs 1000). - We use ulong for string->number conversion ; this is no + We use ulong for string->number conversion ; this is no stronger limitation than in find_uniq_filename in sql/log.cc */ ulong log_name_extension; char log_name_tmp[FN_REFLEN]; //make a char[] from String - char *end= strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), - FN_REFLEN-1)); + + strmake(log_name_tmp, log_name->ptr(), min(log_name->length(), FN_REFLEN-1)); + char *p= fn_ext(log_name_tmp); char *p_end; - if (!*p || log_pos<0) + if (!*p || log_pos<0) { error= -2; //means improper arguments goto err; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2c11d1c87ad..7c17a4ef275 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -438,7 +438,7 @@ void acl_free(bool end) SYNOPSIS acl_reload() - thd Thread handle + thd Thread handle (can be NULL) */ void acl_reload(THD *thd) @@ -1128,6 +1128,10 @@ bool acl_check_host(const char *host, const char *ip) thd THD host hostname for the user user user name + new_password new password + + NOTE: + new_password cannot be NULL RETURN VALUE 0 OK @@ -1135,7 +1139,7 @@ bool acl_check_host(const char *host, const char *ip) */ bool check_change_password(THD *thd, const char *host, const char *user, - char *new_password) + char *new_password, uint new_password_len) { if (!initialized) { @@ -1186,12 +1190,13 @@ bool check_change_password(THD *thd, const char *host, const char *user, bool change_password(THD *thd, const char *host, const char *user, char *new_password) { + uint new_password_len= strlen(new_password); DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); DBUG_ASSERT(host != 0); // Ensured by parent - if (check_change_password(thd, host, user, new_password)) + if (check_change_password(thd, host, user, new_password, new_password_len)) DBUG_RETURN(1); VOID(pthread_mutex_lock(&acl_cache->lock)); @@ -1203,7 +1208,6 @@ bool change_password(THD *thd, const char *host, const char *user, DBUG_RETURN(1); } /* update loaded acl entry: */ - uint new_password_len= new_password ? strlen(new_password) : 0; set_user_salt(acl_user, new_password, new_password_len); if (update_user_table(thd, @@ -2697,7 +2701,7 @@ end: SYNOPSIS grant_reload() - thd Thread handler + thd Thread handler (can be NULL) NOTES Locked tables are checked by acl_init and doesn't have to be checked here diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 68cb1476eb5..dc1b04c063a 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -143,7 +143,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd, uint passwd_len); bool acl_check_host(const char *host, const char *ip); bool check_change_password(THD *thd, const char *host, const char *user, - char *password); + char *password, uint password_len); bool change_password(THD *thd, const char *host, const char *user, char *password); int mysql_grant(THD *thd, const char *db, List &user_list, diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 33ce62bc5cf..7ac9a0866df 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -70,6 +70,9 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, field_info **f_info; DBUG_ENTER("proc_analyse_init"); + if (!pc) + DBUG_RETURN(0); + if (!(param = param->next)) { pc->max_tree_elements = MAX_TREE_ELEMENTS; @@ -81,33 +84,30 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - delete pc; my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); - DBUG_RETURN(0); + goto err; } pc->max_tree_elements = (uint) (*param->item)->val_int(); param = param->next; if (param->next) // no third parameter possible { my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE, MYF(0), proc_name); - DBUG_RETURN(0); + goto err; } // second parameter if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - delete pc; my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); - DBUG_RETURN(0); + goto err; } pc->max_treemem = (uint) (*param->item)->val_int(); } else if ((*param->item)->type() != Item::INT_ITEM || (*param->item)->val() < 0) { - delete pc; my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); - DBUG_RETURN(0); + goto err; } // if only one parameter was given, it will be the value of max_tree_elements else @@ -116,34 +116,39 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, pc->max_treemem = MAX_TREEMEM; } - if (!pc || !(pc->f_info = (field_info**) - sql_alloc(sizeof(field_info*)*field_list.elements))) - DBUG_RETURN(0); + if (!(pc->f_info= + (field_info**)sql_alloc(sizeof(field_info*)*field_list.elements))) + goto err; pc->f_end = pc->f_info + field_list.elements; pc->fields = field_list; - List_iterator_fast it(pc->fields); - f_info = pc->f_info; - - Item *item; - while ((item = it++)) { - if (item->result_type() == INT_RESULT) + List_iterator_fast it(pc->fields); + f_info = pc->f_info; + + Item *item; + while ((item = it++)) { - // Check if fieldtype is ulonglong - if (item->type() == Item::FIELD_ITEM && - ((Item_field*) item)->field->type() == FIELD_TYPE_LONGLONG && - ((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag) - *f_info++ = new field_ulonglong(item, pc); - else - *f_info++ = new field_longlong(item, pc); + if (item->result_type() == INT_RESULT) + { + // Check if fieldtype is ulonglong + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field->type() == FIELD_TYPE_LONGLONG && + ((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag) + *f_info++ = new field_ulonglong(item, pc); + else + *f_info++ = new field_longlong(item, pc); + } + if (item->result_type() == REAL_RESULT) + *f_info++ = new field_real(item, pc); + if (item->result_type() == STRING_RESULT) + *f_info++ = new field_str(item, pc); } - if (item->result_type() == REAL_RESULT) - *f_info++ = new field_real(item, pc); - if (item->result_type() == STRING_RESULT) - *f_info++ = new field_str(item, pc); } DBUG_RETURN(pc); +err: + delete pc; + DBUG_RETURN(0); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 263c68a82b7..7d26996856d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -251,13 +251,19 @@ void free_io_cache(TABLE *table) DBUG_VOID_RETURN; } - /* Close all tables which aren't in use by any thread */ +/* + Close all tables which aren't in use by any thread + + THD can be NULL, but then if_wait_for_refresh must be FALSE + and tables must be NULL. +*/ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, TABLE_LIST *tables) { bool result=0; DBUG_ENTER("close_cached_tables"); + DBUG_ASSERT(thd || (!if_wait_for_refresh && !tables)); VOID(pthread_mutex_lock(&LOCK_open)); if (!tables) @@ -333,7 +339,6 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, VOID(pthread_mutex_unlock(&LOCK_open)); if (if_wait_for_refresh) { - THD *thd=current_thd; pthread_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; @@ -2068,13 +2073,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); table_name=buff; } - if (report_error) - { - my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), - table_name, thd->where); - } - else - return (Field*) not_found_field; + my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0), + table_name, thd->where); } else if (report_error) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index bd42a2c1720..55e96ec0c6d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1157,12 +1157,12 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, DBUG_ASSERT(!using_transactions || tables_used->table!=0); if (tables_used->derived) continue; - if (using_transactions && - (tables_used->table->file->table_cache_type() == + if (using_transactions && + (tables_used->table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT)) - /* + /* Tables_used->table can't be 0 in transaction. - Only 'drop' invalidate not opened table, but 'drop' + Only 'drop' invalidate not opened table, but 'drop' force transaction finish. */ thd->add_changed_table(tables_used->table); @@ -1210,7 +1210,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) */ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used) { - DBUG_ENTER("Query_cache::invalidate (changed table list)"); + DBUG_ENTER("Query_cache::invalidate_locked_for_write"); if (query_cache_size > 0 && tables_used) { STRUCT_LOCK(&structure_guard_mutex); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 39c3f8586ed..407e2b23e38 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -225,7 +225,7 @@ void del_dbopt(const char *path) } -/* +/* Create database options file: DESCRIPTION @@ -244,10 +244,10 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) if (!create->default_table_charset) create->default_table_charset= thd->variables.collation_server; - + if (put_dbopt(path, create)) return 1; - + if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) { ulong length; @@ -523,14 +523,14 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if ((error=write_db_opt(thd, path, create_info))) goto exit; - /* + /* Change options if current database is being altered TODO: Delete this code */ if (thd->db && !strcmp(thd->db,db)) { - thd->db_charset= (create_info && create_info->default_table_charset) ? - create_info->default_table_charset : + thd->db_charset= create_info->default_table_charset ? + create_info->default_table_charset : thd->variables.collation_server; thd->variables.collation_database= thd->db_charset; } @@ -538,7 +538,7 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) mysql_update_log.write(thd,thd->query, thd->query_length); if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, + Query_log_event qinfo(thd, thd->query, thd->query_length, 0, /* suppress_use */ TRUE); /* @@ -620,12 +620,12 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) pthread_mutex_lock(&LOCK_open); remove_db_from_cache(db); pthread_mutex_unlock(&LOCK_open); - + error= -1; if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0)) >= 0) { ha_drop_database(path); - query_cache_invalidate1(db); + query_cache_invalidate1(db); error = 0; } } @@ -636,7 +636,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) my_casedn_str(files_charset_info, tmp_db); db= tmp_db; } - if (!silent && deleted>=0 && thd) + if (!silent && deleted>=0) { const char *query; ulong query_length; @@ -686,7 +686,7 @@ exit: have 'if (data_buf) free(data_buf)' data_buf is !=0 so this makes a DOUBLE free(). Side effects of this double free() are, randomly (depends on the machine), - when the slave is replicating a DROP DATABASE: + when the slave is replicating a DROP DATABASE: - garbage characters in the error message: "Error 'Can't drop database 'test2'; database doesn't exist' on query 'h4zI©'" diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2783406e16a..e0cb43e093e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1685,9 +1685,6 @@ void st_select_lex::print_order(String *str, ORDER *order) void st_select_lex::print_limit(THD *thd, String *str) { - if (!thd) - thd= current_thd; - if (explicit_limit) { str->append(" limit ", 7); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c81aefc9cea..ca626539eb4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -866,14 +866,16 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; char *db= passwd; - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 - /* + uint dummy_errors; + + /* Old clients send null-terminated string as password; new clients send the size (1 byte) + string (not null-terminated). Hence in case of empty password both send '\0'. */ - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; @@ -881,7 +883,6 @@ static int check_connection(THD *thd) /* Since 4.1 all database names are stored in utf8 */ if (db) { - uint dummy_errors; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, db, strlen(db), @@ -889,14 +890,10 @@ static int check_connection(THD *thd) db= db_buff; } - if (user) - { - uint dummy_errors; - user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1, - system_charset_info, user, strlen(user), - thd->charset(), &dummy_errors)]= '\0'; - user= user_buff; - } + user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1, + system_charset_info, user, strlen(user), + thd->charset(), &dummy_errors)]= '\0'; + user= user_buff; if (thd->user) x_free(thd->user); @@ -3217,12 +3214,12 @@ purposes internal to the MySQL server", MYF(0)); /* If in a slave thread : ALTER DATABASE DB may not be preceded by USE DB. - For that reason, maybe db_ok() in sql/slave.cc did not check the + For that reason, maybe db_ok() in sql/slave.cc did not check the do_db/ignore_db. And as this query involves no tables, tables_ok() above was not called. So we have to check rules again here. */ #ifdef HAVE_REPLICATION - if (thd->slave_thread && + if (thd->slave_thread && (!db_ok(db, replicate_do_db, replicate_ignore_db) || !db_ok_with_wild_table(db))) { @@ -3309,9 +3306,9 @@ purposes internal to the MySQL server", MYF(0)); case SQLCOM_GRANT: { if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, - tables && tables->db ? tables->db : select_lex->db, + tables ? tables->db : select_lex->db, tables ? &tables->grant.privilege : 0, - tables ? 0 : 1,0)) + tables ? 0 : 1, 0)) goto error; /* diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c3bfbe086f1..5d756653cdd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1897,9 +1897,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, for (table = tables; table; table = table->next) { char table_name[NAME_LEN*2+2]; - char* db = (table->db) ? table->db : thd->db; + char* db = table->db; bool fatal_error=0; - strxmov(table_name,db ? db : "",".",table->real_name,NullS); + strxmov(table_name, db, ".", table->real_name, NullS); thd->open_options|= extra_open_options; table->table = open_ltable(thd, table, lock_type); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 761e8d6de8b..c2894a0c86b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -61,7 +61,7 @@ int mysql_update(THD *thd, bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table, log_delayed; int error=0; - uint used_index; + uint used_index= MAX_KEY; #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif @@ -75,7 +75,6 @@ int mysql_update(THD *thd, thd->lex->select_lex.table_list.first); DBUG_ENTER("mysql_update"); - LINT_INIT(used_index); LINT_INIT(timestamp_query_id); if ((open_and_lock_tables(thd, table_list))) @@ -175,7 +174,7 @@ int mysql_update(THD *thd, matching rows before updating the table! */ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); - if (old_used_keys.is_set(used_index)) + if (used_index < MAX_KEY && old_used_keys.is_set(used_index)) { table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); @@ -542,8 +541,8 @@ int mysql_multi_update(THD *thd, /* Unlock the tables in preparation for relocking */ if (!using_lock_tables) - { - mysql_unlock_tables(thd, thd->lock); + { + mysql_unlock_tables(thd, thd->lock); thd->lock= 0; } diff --git a/sql/table.cc b/sql/table.cc index 5ede9c1e43d..0d3f2545b20 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -99,11 +99,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, *root_ptr= &outparam->mem_root; outparam->real_name=strdup_root(&outparam->mem_root, - name+dirname_length(name)); - *fn_ext(outparam->real_name)='\0'; // Remove extension + name+dirname_length(name)); outparam->table_name=my_strdup(alias,MYF(MY_WME)); if (!outparam->real_name || !outparam->table_name) goto err_end; + *fn_ext(outparam->real_name)='\0'; // Remove extension if ((file=my_open(fn_format(index_file,name,"",reg_ext,MY_UNPACK_FILENAME), O_RDONLY | O_SHARE, @@ -305,12 +305,14 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open; +#ifdef HAVE_CRYPTED_FRM if (crypted) { crypted->decode((char*) head+256,288-256); if (sint2korr(head+284) != 0) // Should be 0 goto err_not_open; // Wrong password } +#endif outparam->fields= uint2korr(head+258); pos=uint2korr(head+260); /* Length of all screens */ @@ -339,12 +341,14 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, pos+ (uint) (n_length+int_length+com_length)); if (read_string(file,(gptr*) &disk_buff,read_length)) goto err_not_open; /* purecov: inspected */ +#ifdef HAVE_CRYPTED_FRM if (crypted) { crypted->decode((char*) disk_buff,read_length); delete crypted; crypted=0; } +#endif strpos= disk_buff+pos; outparam->intervals= (TYPELIB*) (field_ptr+outparam->fields+1); @@ -1453,7 +1457,7 @@ bool check_column_name(const char *name) { const char *start= name; bool last_char_is_space= TRUE; - + while (*name) { #if defined(USE_MB) && defined(USE_MB_IDENT) diff --git a/sql/tztime.cc b/sql/tztime.cc index c2143b0d5dd..597389220f7 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1825,7 +1825,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) { ttid= (uint)table->field[1]->val_int(); - if (ttid > TZ_MAX_TYPES) + if (ttid >= TZ_MAX_TYPES) { sql_print_error("Error while loading time zone description from " "mysql.time_zone_transition_type table: too big " diff --git a/tests/client_test.c b/tests/client_test.c index beaff795d0e..83f8f6ab143 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -10778,6 +10778,12 @@ static void test_bug5194() if (bind == 0 || query == 0 || param_str == 0) { fprintf(stderr, "Can't allocate enough memory for query structs\n"); + if (bind) + free(bind); + if (query) + free(query); + if (param_str) + free(param_str); return; } From 7109999b92ec8541a61ca5babc5b06f4315478a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 18:38:46 +0100 Subject: [PATCH 5/7] remove the entry from the list, before freeing --- mysys/mf_keycaches.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c index fee3096de52..38fef31fdd4 100644 --- a/mysys/mf_keycaches.c +++ b/mysys/mf_keycaches.c @@ -275,7 +275,11 @@ static void safe_hash_change(SAFE_HASH *hash, byte *old_data, byte *new_data) if (entry->data == old_data) { if (new_data == hash->default_value) + { + if ((*entry->prev= entry->next)) + entry->next->prev= entry->prev; hash_delete(&hash->hash, (byte*) entry); + } else entry->data= new_data; } From 15f37ac2b43592063b27d9f02876d35bda05aa06 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 24 Jan 2005 12:31:14 -0800 Subject: [PATCH 6/7] Set lower_case_file_system when it is being tested to check if lower_case_tables_names=2 is sensible. Related to Bug #7887. sql/mysqld.cc: Set lower_case_file_system when it is being tested to check if lower_case_tables_names=2 is sensible. --- sql/mysqld.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b21b84a34e7..425911570ef 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2914,7 +2914,8 @@ You should consider changing lower_case_table_names to 1 or 2", } } else if (lower_case_table_names == 2 && - (test_if_case_insensitive(mysql_real_data_home) == 0)) + !(lower_case_file_system= + (test_if_case_insensitive(mysql_real_data_home) == 1))) { if (global_system_variables.log_warnings) sql_print_warning("\ From dc43c6ea4b2bd3c466049674b4c760cad9ad2979 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Jan 2005 02:31:51 +0300 Subject: [PATCH 7/7] A fix for Bug#5787 "mysql_stmt_prepare is upto 8 times slower": it's crucial to disable Nagle algorithm on client for no-reply commands (like mysql_stmt_free) to always work fast. Nagle algorithm instructs the sender to buffer (store) data if any unacknowledged data is outstanding and the size of to-send data is less than the network segment. It was exactly the case with COM_STMT_CLOSE after COM_STMT_PREPARE, so the client was waiting for Nagle timer to expire or for ACK from the server, while the server was holding up ACK because of delayed acknowledgement algorithm. The tricky part is that we have been already disabling Nagle algorithm (by setting TCP_NODELAY) almost everywhere except Windows (and maybe Netware). It is the reason why the bug was repeatable only with Windows client. vio/viosocket.c: A fix for Bug#5787 "mysql_stmt_prepare is upto 8 times slower": if we disable Nagle algorithm, do it everywhere. --- vio/viosocket.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/vio/viosocket.c b/vio/viosocket.c index bcba05beef1..202d70b6c26 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -142,23 +142,29 @@ int vio_fastsend(Vio * vio __attribute__((unused))) int r=0; DBUG_ENTER("vio_fastsend"); -#ifdef IPTOS_THROUGHPUT +#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) { -#ifndef __EMX__ int tos = IPTOS_THROUGHPUT; - if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos))) -#endif /* !__EMX__ */ - { - int nodelay = 1; - if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay, - sizeof(nodelay))) { - DBUG_PRINT("warning", - ("Couldn't set socket option for fast send")); - r= -1; - } - } + r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); + } +#endif /* IPTOS_THROUGHPUT && !__EMX__ */ + if (!r) + { +#ifdef __WIN__ + BOOL nodelay= 1; + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (const char*) &nodelay, + sizeof(nodelay)); +#else + int nodelay = 1; + r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay, + sizeof(nodelay)); +#endif /* __WIN__ */ + } + if (r) + { + DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); + r= -1; } -#endif /* IPTOS_THROUGHPUT */ DBUG_PRINT("exit", ("%d", r)); DBUG_RETURN(r); }