Commit b90a9b32 authored by unknown's avatar unknown

Fixed memory reference errors found by valgrind


sql/ha_federated.cc:
  Change mode to -rw-rw-r--
myisam/mi_create.c:
  Ensure that all referenced memory is reset
mysql-test/r/type_timestamp.result:
  More tests
mysql-test/t/func_compress.test:
  Added comment
mysql-test/t/type_timestamp.test:
  More tests
sql/field.h:
  Count number of varchars in table
sql/item_cmpfunc.cc:
  Safety fix (to avoid warning from valgrind)
sql/opt_range.cc:
  Simple optimzation
sql/sql_acl.cc:
  Safety fix (to avoid warning from valgrind)
sql/sql_parse.cc:
  Safety fix for prepared statements
sql/sql_show.cc:
  Move variable declarations first in function
  Remove hidden variable (it)
  Remove accessing freed memory (table_list->table_name)
sql/sql_update.cc:
  Compare records with varchars correctly
sql/table.cc:
  Safety fix when running with purify/valgrind
  Fix wrong memory reference in case of errors
sql/table.h:
  Added counting of varchar fields
strings/ctype-mb.c:
  Fill max_str properly
parent fa82355c
...@@ -630,10 +630,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ...@@ -630,10 +630,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{ {
HA_KEYSEG sseg; HA_KEYSEG sseg;
sseg.type=SPTYPE; sseg.type=SPTYPE;
sseg.language= 7; sseg.language= 7; /* Binary */
sseg.null_bit=0; sseg.null_bit=0;
sseg.bit_start=0; sseg.bit_start=0;
sseg.bit_end=0; sseg.bit_end=0;
sseg.bit_length= 0;
sseg.bit_pos= 0;
sseg.length=SPLEN; sseg.length=SPLEN;
sseg.null_pos=0; sseg.null_pos=0;
sseg.start=j*SPLEN; sseg.start=j*SPLEN;
......
...@@ -35,6 +35,10 @@ UPDATE t1 SET value="my value" WHERE id="myKey"; ...@@ -35,6 +35,10 @@ UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey"; SELECT stamp FROM t1 WHERE id="myKey";
stamp stamp
1999-04-02 00:00:00 1999-04-02 00:00:00
UPDATE t1 SET id="myKey" WHERE value="my value";
SELECT stamp FROM t1 WHERE id="myKey";
stamp
1999-04-02 00:00:00
drop table t1; drop table t1;
create table t1 (a timestamp); create table t1 (a timestamp);
insert into t1 values (now()); insert into t1 values (now());
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# #
# Test for compress and uncompress functions: # Test for compress and uncompress functions:
# #
# Note that this test gives error in the gzip library when running under
# valgrind, but these warnings can be ignored
select @test_compress_string:='string for test compress function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa '; select @test_compress_string:='string for test compress function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ';
select length(@test_compress_string); select length(@test_compress_string);
......
...@@ -29,6 +29,8 @@ INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00"); ...@@ -29,6 +29,8 @@ INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
SELECT stamp FROM t1 WHERE id="myKey"; SELECT stamp FROM t1 WHERE id="myKey";
UPDATE t1 SET value="my value" WHERE id="myKey"; UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey"; SELECT stamp FROM t1 WHERE id="myKey";
UPDATE t1 SET id="myKey" WHERE value="my value";
SELECT stamp FROM t1 WHERE id="myKey";
drop table t1; drop table t1;
create table t1 (a timestamp); create table t1 (a timestamp);
......
...@@ -952,14 +952,20 @@ class Field_varstring :public Field_str { ...@@ -952,14 +952,20 @@ class Field_varstring :public Field_str {
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg, cs), unireg_check_arg, field_name_arg, table_arg, cs),
length_bytes(length_bytes_arg) length_bytes(length_bytes_arg)
{} {
if (table)
table->s->varchar_fields++;
}
Field_varstring(uint32 len_arg,bool maybe_null_arg, Field_varstring(uint32 len_arg,bool maybe_null_arg,
const char *field_name_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs) struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg, cs), NONE, field_name_arg, table_arg, cs),
length_bytes(len_arg < 256 ? 1 :2) length_bytes(len_arg < 256 ? 1 :2)
{} {
if (table)
table->s->varchar_fields++;
}
enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
enum ha_base_keytype key_type() const; enum ha_base_keytype key_type() const;
......
File mode changed from 100755 to 100644
...@@ -2519,7 +2519,7 @@ longlong Item_func_regex::val_int() ...@@ -2519,7 +2519,7 @@ longlong Item_func_regex::val_int()
regfree(&preg); regfree(&preg);
regex_compiled=0; regex_compiled=0;
} }
if (regcomp(&preg,res2->c_ptr(), if (regcomp(&preg,res2->c_ptr_safe(),
((cmp_collation.collation->state & ((cmp_collation.collation->state &
(MY_CS_BINSORT | MY_CS_CSSORT)) ? (MY_CS_BINSORT | MY_CS_CSSORT)) ?
REG_EXTENDED | REG_NOSUB : REG_EXTENDED | REG_NOSUB :
......
...@@ -3589,7 +3589,6 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -3589,7 +3589,6 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
Item_func::Functype type,Item *value) Item_func::Functype type,Item *value)
{ {
uint maybe_null=(uint) field->real_maybe_null(), copies; uint maybe_null=(uint) field->real_maybe_null(), copies;
uint field_length=field->pack_length()+maybe_null;
bool optimize_range; bool optimize_range;
SEL_ARG *tree; SEL_ARG *tree;
char *str, *str2; char *str, *str2;
...@@ -3639,6 +3638,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -3639,6 +3638,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
char buff1[MAX_FIELD_WIDTH],*min_str,*max_str; char buff1[MAX_FIELD_WIDTH],*min_str,*max_str;
String tmp(buff1,sizeof(buff1),value->collation.collation),*res; String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
uint length,offset,min_length,max_length; uint length,offset,min_length,max_length;
uint field_length= field->pack_length()+maybe_null;
if (!optimize_range) if (!optimize_range)
DBUG_RETURN(0); // Can't optimize this DBUG_RETURN(0); // Can't optimize this
...@@ -3683,21 +3683,23 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -3683,21 +3683,23 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
length+=offset; length+=offset;
if (!(min_str= (char*) alloc_root(param->mem_root, length*2))) if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
DBUG_RETURN(0); DBUG_RETURN(0);
max_str=min_str+length; max_str=min_str+length;
if (maybe_null) if (maybe_null)
max_str[0]= min_str[0]=0; max_str[0]= min_str[0]=0;
field_length-= maybe_null;
like_error= my_like_range(field->charset(), like_error= my_like_range(field->charset(),
res->ptr(), res->length(), res->ptr(), res->length(),
((Item_func_like*)(param->cond))->escape, ((Item_func_like*)(param->cond))->escape,
wild_one, wild_many, wild_one, wild_many,
field_length-maybe_null, field_length,
min_str+offset, max_str+offset, min_str+offset, max_str+offset,
&min_length, &max_length); &min_length, &max_length);
if (like_error) // Can't optimize with LIKE if (like_error) // Can't optimize with LIKE
DBUG_RETURN(0); DBUG_RETURN(0);
if (offset != maybe_null) // Blob if (offset != maybe_null) // BLOB or VARCHAR
{ {
int2store(min_str+maybe_null,min_length); int2store(min_str+maybe_null,min_length);
int2store(max_str+maybe_null,max_length); int2store(max_str+maybe_null,max_length);
......
...@@ -4800,7 +4800,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) ...@@ -4800,7 +4800,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
close_thread_tables(thd); close_thread_tables(thd);
if (result) if (result)
my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr()); my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe());
DBUG_RETURN(result); DBUG_RETURN(result);
} }
...@@ -4905,7 +4905,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) ...@@ -4905,7 +4905,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
close_thread_tables(thd); close_thread_tables(thd);
if (result) if (result)
my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr()); my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe());
DBUG_RETURN(result); DBUG_RETURN(result);
} }
......
...@@ -1911,7 +1911,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, ...@@ -1911,7 +1911,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
{ {
DBUG_ENTER("prepare_schema_table"); DBUG_ENTER("prepare_schema_table");
SELECT_LEX *sel= 0; SELECT_LEX *sel= 0;
switch(schema_table_idx) { switch (schema_table_idx) {
case SCH_SCHEMATA: case SCH_SCHEMATA:
#if defined(DONT_ALLOW_SHOW_COMMANDS) #if defined(DONT_ALLOW_SHOW_COMMANDS)
my_message(ER_NOT_ALLOWED_COMMAND, my_message(ER_NOT_ALLOWED_COMMAND,
...@@ -1953,7 +1953,11 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, ...@@ -1953,7 +1953,11 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
thd->priv_user, thd->priv_host, db); thd->priv_user, thd->priv_host, db);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
lex->select_lex.db= db; /*
We need to do a copy to make this prepared statement safe if this
was thd->db
*/
lex->select_lex.db= thd->strdup(db);
break; break;
} }
#endif #endif
......
...@@ -1793,14 +1793,28 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -1793,14 +1793,28 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
SELECT_LEX *select_lex= &lex->select_lex; SELECT_LEX *select_lex= &lex->select_lex;
SELECT_LEX *lsel= tables->schema_select_lex; SELECT_LEX *lsel= tables->schema_select_lex;
ST_SCHEMA_TABLE *schema_table= tables->schema_table; ST_SCHEMA_TABLE *schema_table= tables->schema_table;
DBUG_ENTER("fill_schema_tables"); SELECT_LEX sel;
INDEX_FIELD_VALUES idx_field_vals;
char path[FN_REFLEN], *end, *base_name, *file_name;
uint len;
bool with_i_schema;
enum enum_schema_tables schema_table_idx;
thr_lock_type lock_type;
List<char> bases;
COND *partial_cond;
DBUG_ENTER("get_all_tables");
LINT_INIT(end);
LINT_INIT(len);
if (lsel) if (lsel)
{ {
TABLE *old_open_tables= thd->open_tables; TABLE *old_open_tables= thd->open_tables;
TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first; TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
bool res;
lex->all_selects_list= lsel; lex->all_selects_list= lsel;
bool res= open_and_lock_tables(thd, show_table_list); res= open_and_lock_tables(thd, show_table_list);
if (schema_table->process_table(thd, show_table_list, if (schema_table->process_table(thd, show_table_list,
table, res, show_table_list->db, table, res, show_table_list->db,
show_table_list->table_name)) show_table_list->table_name))
...@@ -1813,15 +1827,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -1813,15 +1827,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
SELECT_LEX sel;
INDEX_FIELD_VALUES idx_field_vals;
char path[FN_REFLEN], *end= 0, *base_name, *file_name;
uint len= 0;
bool with_i_schema;
List<char> bases;
lex->all_selects_list= &sel; lex->all_selects_list= &sel;
enum enum_schema_tables schema_table_idx= get_schema_table_idx(schema_table); schema_table_idx= get_schema_table_idx(schema_table);
thr_lock_type lock_type= TL_UNLOCK; lock_type= TL_UNLOCK;
if (schema_table_idx == SCH_TABLES) if (schema_table_idx == SCH_TABLES)
lock_type= TL_READ; lock_type= TL_READ;
get_index_field_values(lex, &idx_field_vals); get_index_field_values(lex, &idx_field_vals);
...@@ -1833,9 +1842,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -1833,9 +1842,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
if (mysql_find_files(thd, &bases, NullS, mysql_data_home, if (mysql_find_files(thd, &bases, NullS, mysql_data_home,
idx_field_vals.db_value, 1)) idx_field_vals.db_value, 1))
return 1; return 1;
List_iterator_fast<char> it(bases); List_iterator_fast<char> it(bases);
COND *partial_cond= make_cond_for_info_schema(cond, tables); partial_cond= make_cond_for_info_schema(cond, tables);
while ((base_name=it++) || while ((base_name= it++) ||
/* /*
generate error for non existing database. generate error for non existing database.
(to save old behaviour for SHOW TABLES FROM db) (to save old behaviour for SHOW TABLES FROM db)
...@@ -1868,8 +1878,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -1868,8 +1878,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
List_iterator_fast<char> it(files); List_iterator_fast<char> it_files(files);
while ((file_name=it++)) while ((file_name= it_files++))
{ {
restore_record(table, s->default_values); restore_record(table, s->default_values);
table->field[schema_table->idx_field1]-> table->field[schema_table->idx_field1]->
...@@ -1889,8 +1899,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -1889,8 +1899,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
else else
{ {
my_snprintf(end, len, "/%s%s", file_name, reg_ext); my_snprintf(end, len, "/%s%s", file_name, reg_ext);
switch (mysql_frm_type(path)) switch (mysql_frm_type(path)) {
{
case FRMTYPE_ERROR: case FRMTYPE_ERROR:
table->field[3]->store("ERROR", 5, system_charset_info); table->field[3]->store("ERROR", 5, system_charset_info);
break; break;
...@@ -3188,9 +3197,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) ...@@ -3188,9 +3197,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
} }
table->s->tmp_table= TMP_TABLE; table->s->tmp_table= TMP_TABLE;
table->grant.privilege= SELECT_ACL; table->grant.privilege= SELECT_ACL;
table->alias_name_used= my_strcasecmp(table_alias_charset, table->alias_name_used= 0;
table_list->table_name,
table_list->alias);
table_list->schema_table_name= table_list->table_name; table_list->schema_table_name= table_list->table_name;
table_list->table_name= (char*) table->s->table_name; table_list->table_name= (char*) table->s->table_name;
table_list->table= table; table_list->table= table;
......
...@@ -31,7 +31,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields); ...@@ -31,7 +31,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields);
static bool compare_record(TABLE *table, ulong query_id) static bool compare_record(TABLE *table, ulong query_id)
{ {
if (!table->s->blob_fields) if (table->s->blob_fields + table->s->varchar_fields == 0)
return cmp_record(table,record[1]); return cmp_record(table,record[1]);
/* Compare null bits */ /* Compare null bits */
if (memcmp(table->null_flags, if (memcmp(table->null_flags,
......
...@@ -288,7 +288,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, ...@@ -288,7 +288,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
records=2; records=2;
else else
records=1; records=1;
if (prgflag & (READ_ALL+EXTRA_RECORD)) records++; if (prgflag & (READ_ALL+EXTRA_RECORD))
records++;
/* QQ: TODO, remove the +1 from below */ /* QQ: TODO, remove the +1 from below */
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + rec_buff_length= ALIGN_SIZE(share->reclength + 1 +
outparam->file->extra_rec_buf_length()); outparam->file->extra_rec_buf_length());
...@@ -304,12 +305,32 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, ...@@ -304,12 +305,32 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
MYF(MY_NABP))) MYF(MY_NABP)))
goto err_not_open; /* purecov: inspected */ goto err_not_open; /* purecov: inspected */
outparam->record[0]= record+ rec_buff_length; if (records == 1)
if (records > 2) {
outparam->record[1]= record+ rec_buff_length*2; /* We are probably in hard repair, and the buffers should not be used */
outparam->record[0]= outparam->record[1]= share->default_values;
}
else else
outparam->record[1]= outparam->record[0]; // Safety {
outparam->record[0]= record+ rec_buff_length;
if (records > 2)
outparam->record[1]= record+ rec_buff_length*2;
else
outparam->record[1]= outparam->record[0]; // Safety
}
#ifdef HAVE_purify
/*
We need this because when we read var-length rows, we are not updating
bytes after end of varchar
*/
if (records > 1)
{
memcpy(outparam->record[0], share->default_values, rec_buff_length);
if (records > 2)
memcpy(outparam->record[1], share->default_values, rec_buff_length);
}
#endif
VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open; if (my_read(file,(byte*) head,288,MYF(MY_NABP))) goto err_not_open;
if (crypted) if (crypted)
...@@ -822,7 +843,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, ...@@ -822,7 +843,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
outparam->file=0; // For easier errorchecking outparam->file=0; // For easier errorchecking
outparam->db_stat=0; outparam->db_stat=0;
hash_free(&share->name_hash); hash_free(&share->name_hash);
free_root(&share->mem_root, MYF(0)); free_root(&outparam->mem_root, MYF(0));
my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN (error); DBUG_RETURN (error);
} /* openfrm */ } /* openfrm */
......
...@@ -137,6 +137,7 @@ typedef struct st_table_share ...@@ -137,6 +137,7 @@ typedef struct st_table_share
uint uniques; /* Number of UNIQUE index */ uint uniques; /* Number of UNIQUE index */
uint null_fields; /* number of null fields */ uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */ uint blob_fields; /* number of blob fields */
uint varchar_fields; /* number of varchar fields */
uint db_create_options; /* Create options from database */ uint db_create_options; /* Create options from database */
uint db_options_in_use; /* Options in use */ uint db_options_in_use; /* Options in use */
uint db_record_offset; /* if HA_REC_IN_SEQ */ uint db_record_offset; /* if HA_REC_IN_SEQ */
......
...@@ -561,9 +561,9 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, ...@@ -561,9 +561,9 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
*min_str++= *max_str++ = *ptr; *min_str++= *max_str++ = *ptr;
} }
*min_length= *max_length = (uint) (min_str - min_org); *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end) while (min_str != min_end)
*min_str++= *max_str= ' '; /* Because if key compression */ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment