From bd5f334bed8d9901fe11a746900491a3dc40381d Mon Sep 17 00:00:00 2001 From: "knielsen@mysql.com" <> Date: Thu, 22 Jun 2006 16:42:50 +0200 Subject: [PATCH] BUG#20549: Fix missing memory initialization. Some values were not initialized, causing Valgrind errors (and potential random bugs): - NDB binlog thread thd->variables.pseudo_thread_id. - Table null bits. - Field bytes for columns with NULL values. --- sql/ha_ndbcluster_binlog.cc | 21 ++++++++++++++++++--- sql/sql_class.cc | 8 ++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 022c8a021cb..dac6419b198 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -311,8 +311,10 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share, if (!reopen) { // allocate memory on ndb share so it can be reused after online alter table - share->record[0]= (byte*) alloc_root(&share->mem_root, table->s->rec_buff_length); - share->record[1]= (byte*) alloc_root(&share->mem_root, table->s->rec_buff_length); + (void)multi_alloc_root(&share->mem_root, + &(share->record[0]), table->s->rec_buff_length, + &(share->record[1]), table->s->rec_buff_length, + NULL); } { my_ptrdiff_t row_offset= share->record[0] - table->record[0]; @@ -2159,6 +2161,9 @@ int ndb_add_binlog_index(THD *thd, void *_row) break; } + // Set all fields non-null. + if(binlog_index->s->null_bytes > 0) + bzero(binlog_index->record[0], binlog_index->s->null_bytes); binlog_index->field[0]->store(row.master_log_pos); binlog_index->field[1]->store(row.master_log_file, strlen(row.master_log_file), @@ -3275,6 +3280,13 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) thd= new THD; /* note that contructor of THD uses DBUG_ */ THD_CHECK_SENTRY(thd); + /* We need to set thd->thread_id before thd->store_globals, or it will + set an invalid value for thd->variables.pseudo_thread_id. + */ + pthread_mutex_lock(&LOCK_thread_count); + thd->thread_id= thread_id++; + pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_stack= (char*) &thd; /* remember where our stack is */ if (thd->store_globals()) { @@ -3307,7 +3319,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) pthread_detach_this_thread(); thd->real_id= pthread_self(); pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id= thread_id++; threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); thd->lex->start_transaction_opt= 0; @@ -3641,6 +3652,10 @@ restart: injector::transaction::table tbl(table, TRUE); int ret= trans.use_table(::server_id, tbl); DBUG_ASSERT(ret == 0); + + // Set all fields non-null. + if(table->s->null_bytes > 0) + bzero(table->record[0], table->s->null_bytes); table->field[0]->store((longlong)::server_id); table->field[1]->store((longlong)gci); trans.write_row(::server_id, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0ede042da17..1c7d00a5fe1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2475,15 +2475,19 @@ my_size_t THD::pack_row(TABLE *table, MY_BITMAP const* cols, byte *row_data, int n_null_bytes= table->s->null_bytes; byte *ptr; uint i; - my_ptrdiff_t const offset= (my_ptrdiff_t) (record - (byte*) - table->record[0]); + my_ptrdiff_t const rec_offset= record - table->record[0]; + my_ptrdiff_t const def_offset= table->s->default_values - table->record[0]; memcpy(row_data, record, n_null_bytes); ptr= row_data+n_null_bytes; for (i= 0 ; (field= *p_field) ; i++, p_field++) { if (bitmap_is_set(cols,i)) + { + my_ptrdiff_t const offset= + field->is_null(rec_offset) ? def_offset : rec_offset; ptr= (byte*)field->pack((char *) ptr, field->ptr + offset); + } } return (static_cast(ptr - row_data)); }