List:Commits« Previous MessageNext Message »
From:Marc Alff Date:November 16 2010 6:28am
Subject:bzr push into mysql-trunk branch (marc.alff:3347 to 3348)
View as plain text  
 3348 Marc Alff	2010-11-16 [merge]
      Merge mysql-5.5-bugteam --> mysql-trunk-bugfixing

    modified:
      mysys/mf_iocache.c
      sql/binlog.cc
      sql/log.cc
      sql/log.h
      sql/mysqld.cc
      sql/mysqld.h
      storage/perfschema/pfs_global.h
      storage/perfschema/pfs_instr.cc
      storage/perfschema/pfs_instr.h
      storage/perfschema/pfs_instr_class.cc
      storage/perfschema/pfs_instr_class.h
      storage/perfschema/table_events_waits.cc
 3347 Marc Alff	2010-11-16 [merge]
      local merge

    modified:
      mysql-test/suite/perfschema/t/threads_mysql.test
=== modified file 'mysys/mf_iocache.c'
--- a/mysys/mf_iocache.c	2010-07-29 12:33:56 +0000
+++ b/mysys/mf_iocache.c	2010-11-16 06:27:18 +0000
@@ -173,7 +173,7 @@ int init_io_cache(IO_CACHE *info, File f
 
   if (file >= 0)
   {
-    pos= my_tell(file, MYF(0));
+    pos= mysql_file_tell(file, MYF(0));
     if ((pos == (my_off_t) -1) && (my_errno == ESPIPE))
     {
       /*
@@ -205,7 +205,7 @@ int init_io_cache(IO_CACHE *info, File f
     if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
     {
       /* Calculate end of file to avoid allocating oversized buffers */
-      end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
+      end_of_file= mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0));
       /* Need to reset seek_not_done now that we just did a seek. */
       info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
       if (end_of_file < seek_offset)
@@ -485,7 +485,7 @@ int _my_b_read(register IO_CACHE *info, 
   */
   if (info->seek_not_done)
   {
-    if ((my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) 
+    if ((mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) 
         != MY_FILEPOS_ERROR))
     {
       /* No error, reset seek_not_done flag. */
@@ -529,7 +529,7 @@ int _my_b_read(register IO_CACHE *info, 
       end aligned with a block.
     */
     length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
-    if ((read_length= my_read(info->file,Buffer, length, info->myflags))
+    if ((read_length= mysql_file_read(info->file,Buffer, length, info->myflags))
 	!= length)
     {
       /*
@@ -572,7 +572,7 @@ int _my_b_read(register IO_CACHE *info, 
     }
     length=0;				/* Didn't read any chars */
   }
-  else if ((length= my_read(info->file,info->buffer, max_length,
+  else if ((length= mysql_file_read(info->file,info->buffer, max_length,
                             info->myflags)) < Count ||
 	   length == (size_t) -1)
   {
@@ -1056,7 +1056,7 @@ int _my_b_read_r(register IO_CACHE *cach
         */
         if (cache->seek_not_done)
         {
-          if (my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
+          if (mysql_file_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
               == MY_FILEPOS_ERROR)
           {
             cache->error= -1;
@@ -1064,7 +1064,7 @@ int _my_b_read_r(register IO_CACHE *cach
             DBUG_RETURN(1);
           }
         }
-        len= my_read(cache->file, cache->buffer, length, cache->myflags);
+        len= mysql_file_read(cache->file, cache->buffer, length, cache->myflags);
       }
       DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len));
 
@@ -1203,7 +1203,7 @@ int _my_b_seq_read(register IO_CACHE *in
     With read-append cache we must always do a seek before we read,
     because the write could have moved the file pointer astray
   */
-  if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == MY_FILEPOS_ERROR)
+  if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
   {
    info->error= -1;
    unlock_append_buffer(info);
@@ -1220,8 +1220,8 @@ int _my_b_seq_read(register IO_CACHE *in
     size_t read_length;
 
     length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
-    if ((read_length= my_read(info->file,Buffer, length,
-                              info->myflags)) == (size_t) -1)
+    if ((read_length= mysql_file_read(info->file,Buffer, length,
+                                      info->myflags)) == (size_t) -1)
     {
       info->error= -1;
       unlock_append_buffer(info);
@@ -1254,7 +1254,7 @@ int _my_b_seq_read(register IO_CACHE *in
   }
   else
   {
-    length= my_read(info->file,info->buffer, max_length, info->myflags);
+    length= mysql_file_read(info->file,info->buffer, max_length, info->myflags);
     if (length == (size_t) -1)
     {
       info->error= -1;
@@ -1431,7 +1431,7 @@ int _my_b_async_read(register IO_CACHE *
       return 1;
     }
     
-    if (my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0))
+    if (mysql_file_seek(info->file, next_pos_in_file, MY_SEEK_SET, MYF(0))
         == MY_FILEPOS_ERROR)
     {
       info->error= -1;
@@ -1441,8 +1441,8 @@ int _my_b_async_read(register IO_CACHE *
     read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1));
     if (Count < read_length)
     {					/* Small block, read to cache */
-      if ((read_length=my_read(info->file,info->request_pos,
-			       read_length, info->myflags)) == (size_t) -1)
+      if ((read_length=mysql_file_read(info->file,info->request_pos,
+			               read_length, info->myflags)) == (size_t) -1)
         return info->error= -1;
       use_length=min(Count,read_length);
       memcpy(Buffer,info->request_pos,(size_t) use_length);
@@ -1462,7 +1462,7 @@ int _my_b_async_read(register IO_CACHE *
     }
     else
     {						/* Big block, don't cache it */
-      if ((read_length= my_read(info->file,Buffer, Count,info->myflags))
+      if ((read_length= mysql_file_read(info->file, Buffer, Count,info->myflags))
 	  != Count)
       {
 	info->error= read_length == (size_t) -1 ? -1 : read_length+left_length;
@@ -1569,14 +1569,14 @@ int _my_b_write(register IO_CACHE *info,
         "seek_not_done" to indicate this to other functions operating
         on the IO_CACHE.
       */
-      if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)))
+      if (mysql_file_seek(info->file, info->pos_in_file, MY_SEEK_SET, MYF(0)))
       {
         info->error= -1;
         return (1);
       }
       info->seek_not_done=0;
     }
-    if (my_write(info->file, Buffer, length, info->myflags | MY_NABP))
+    if (mysql_file_write(info->file, Buffer, length, info->myflags | MY_NABP))
       return info->error= -1;
 
 #ifdef THREAD
@@ -1639,7 +1639,7 @@ int my_b_append(register IO_CACHE *info,
   if (Count >= IO_SIZE)
   {					/* Fill first intern buffer */
     length=Count & (size_t) ~(IO_SIZE-1);
-    if (my_write(info->file,Buffer, length, info->myflags | MY_NABP))
+    if (mysql_file_write(info->file,Buffer, length, info->myflags | MY_NABP))
     {
       unlock_append_buffer(info);
       return info->error= -1;
@@ -1695,11 +1695,11 @@ int my_block_write(register IO_CACHE *in
   {
     /* Of no overlap, write everything without buffering */
     if (pos + Count <= info->pos_in_file)
-      return my_pwrite(info->file, Buffer, Count, pos,
-		       info->myflags | MY_NABP);
+      return mysql_file_pwrite(info->file, Buffer, Count, pos,
+		               info->myflags | MY_NABP);
     /* Write the part of the block that is before buffer */
     length= (uint) (info->pos_in_file - pos);
-    if (my_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP))
+    if (mysql_file_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP))
       info->error= error= -1;
     Buffer+=length;
     pos+=  length;
@@ -1789,7 +1789,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
       */
       if (!append_cache && info->seek_not_done)
       {					/* File touched, do seek */
-	if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
+	if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) ==
 	    MY_FILEPOS_ERROR)
 	{
 	  UNLOCK_APPEND_BUFFER;
@@ -1803,7 +1803,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
       info->write_end= (info->write_buffer+info->buffer_length-
 			((pos_in_file+length) & (IO_SIZE-1)));
 
-      if (my_write(info->file,info->write_buffer,length,
+      if (mysql_file_write(info->file,info->write_buffer,length,
 		   info->myflags | MY_NABP))
 	info->error= -1;
       else
@@ -1815,7 +1815,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
       else
       {
 	info->end_of_file+=(info->write_pos-info->append_read_pos);
-	DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0)));
+	DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0)));
       }
 
       info->append_read_pos=info->write_pos=info->write_buffer;

=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2010-10-27 14:46:44 +0000
+++ b/sql/binlog.cc	2010-11-16 06:27:18 +0000
@@ -1594,8 +1594,8 @@ bool MYSQL_BIN_LOG::open(const char *log
   write_error= 0;
 
   /* open the main log file */
-  if (MYSQL_LOG::open(log_name, log_type_arg, new_name,
-                      io_cache_type_arg))
+  if (MYSQL_LOG::open(key_file_binlog,
+                      log_name, log_type_arg, new_name, io_cache_type_arg))
   {
 #ifdef HAVE_REPLICATION
     close_purge_index_file();

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-10-27 10:28:09 +0000
+++ b/sql/log.cc	2010-11-16 06:27:18 +0000
@@ -1359,7 +1359,11 @@ bool MYSQL_LOG::init_and_set_log_file_na
     1   error
 */
 
-bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
+bool MYSQL_LOG::open(
+#ifdef HAVE_PSI_INTERFACE
+                     PSI_file_key log_file_key,
+#endif
+                     const char *log_name, enum_log_type log_type_arg,
                      const char *new_name, enum cache_type io_cache_type_arg)
 {
   char buff[FN_REFLEN];
@@ -1387,7 +1391,12 @@ bool MYSQL_LOG::open(const char *log_nam
 
   db[0]= 0;
 
-  if ((file= mysql_file_open(key_file_MYSQL_LOG,
+#ifdef HAVE_PSI_INTERFACE
+  /* Keep the key for reopen */
+  m_log_file_key= log_file_key;
+#endif
+
+  if ((file= mysql_file_open(log_file_key,
                              log_file_name, open_flags,
                              MYF(MY_WME | ME_WAITTANG))) < 0 ||
       init_io_cache(&log_file, file, IO_SIZE, io_cache_type,
@@ -1571,7 +1580,11 @@ void MYSQL_QUERY_LOG::reopen_file()
      Note that at this point, log_state != LOG_CLOSED (important for is_open()).
   */
 
-  open(save_name, log_type, 0, io_cache_type);
+  open(
+#ifdef HAVE_PSI_INTERFACE
+       m_log_file_key,
+#endif
+       save_name, log_type, 0, io_cache_type);
   my_free(save_name);
 
   mysql_mutex_unlock(&LOCK_log);

=== modified file 'sql/log.h'
--- a/sql/log.h	2010-10-27 10:28:09 +0000
+++ b/sql/log.h	2010-11-16 06:27:18 +0000
@@ -179,7 +179,11 @@ public:
   MYSQL_LOG();
   void init_pthread_objects();
   void cleanup();
-  bool open(const char *log_name,
+  bool open(
+#ifdef HAVE_PSI_INTERFACE
+            PSI_file_key log_file_key,
+#endif
+            const char *log_name,
             enum_log_type log_type,
             const char *new_name,
             enum cache_type io_cache_type_arg);
@@ -206,6 +210,10 @@ public:
   volatile enum_log_state log_state;
   enum cache_type io_cache_type;
   friend class Log_event;
+#ifdef HAVE_PSI_INTERFACE
+  /** Instrumentation key to use for file io in @c log_file */
+  PSI_file_key m_log_file_key;
+#endif
 };
 
 class MYSQL_QUERY_LOG: public MYSQL_LOG
@@ -224,14 +232,22 @@ public:
   bool open_slow_log(const char *log_name)
   {
     char buf[FN_REFLEN];
-    return open(generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0,
-                WRITE_CACHE);
+    return open(
+#ifdef HAVE_PSI_INTERFACE
+                key_file_slow_log,
+#endif
+                generate_name(log_name, "-slow.log", 0, buf),
+                LOG_NORMAL, 0, WRITE_CACHE);
   }
   bool open_query_log(const char *log_name)
   {
     char buf[FN_REFLEN];
-    return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
-                WRITE_CACHE);
+    return open(
+#ifdef HAVE_PSI_INTERFACE
+                key_file_query_log,
+#endif
+                generate_name(log_name, ".log", 0, buf),
+                LOG_NORMAL, 0, WRITE_CACHE);
   }
 
 private:

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-11-09 20:10:44 +0000
+++ b/sql/mysqld.cc	2010-11-16 06:27:18 +0000
@@ -7962,9 +7962,10 @@ PSI_file_key key_file_binlog, key_file_b
   key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
   key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
   key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
-  key_file_master_info, key_file_misc, key_file_MYSQL_LOG, key_file_partition,
+  key_file_master_info, key_file_misc, key_file_partition,
   key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
   key_file_trg, key_file_trn, key_file_init;
+PSI_file_key key_file_query_log, key_file_slow_log;
 
 static PSI_file_info all_server_files[]=
 {
@@ -7987,11 +7988,12 @@ static PSI_file_info all_server_files[]=
   { &key_file_log_event_info, "log_event_info", 0},
   { &key_file_master_info, "master_info", 0},
   { &key_file_misc, "misc", 0},
-  { &key_file_MYSQL_LOG, "MYSQL_LOG", 0},
   { &key_file_partition, "partition", 0},
   { &key_file_pid, "pid", 0},
+  { &key_file_query_log, "query_log", 0},
   { &key_file_relay_log_info, "relay_log_info", 0},
   { &key_file_send_file, "send_file", 0},
+  { &key_file_slow_log, "slow_log", 0},
   { &key_file_tclog, "tclog", 0},
   { &key_file_trg, "trigger_name", 0},
   { &key_file_trn, "trigger", 0},

=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h	2010-11-08 14:35:45 +0000
+++ b/sql/mysqld.h	2010-11-16 06:27:18 +0000
@@ -275,9 +275,10 @@ extern PSI_file_key key_file_binlog, key
   key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
   key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
   key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
-  key_file_master_info, key_file_misc, key_file_MYSQL_LOG, key_file_partition,
+  key_file_master_info, key_file_misc, key_file_partition,
   key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
   key_file_trg, key_file_trn, key_file_init;
+extern PSI_file_key key_file_query_log, key_file_slow_log;
 
 void init_server_psi_keys();
 #endif /* HAVE_PSI_INTERFACE */

=== modified file 'storage/perfschema/pfs_global.h'
--- a/storage/perfschema/pfs_global.h	2010-07-16 01:28:30 +0000
+++ b/storage/perfschema/pfs_global.h	2010-11-16 06:27:18 +0000
@@ -79,5 +79,21 @@ inline uint randomized_index(const void 
 
 void pfs_print_error(const char *format, ...);
 
+/**
+  Given an array defined as T ARRAY[MAX],
+  check that an UNSAFE pointer actually points to an element
+  within the array.
+*/
+#define SANITIZE_ARRAY_BODY(T, ARRAY, MAX, UNSAFE)          \
+  intptr offset;                                            \
+  if ((&ARRAY[0] <= UNSAFE) &&                              \
+      (UNSAFE < &ARRAY[MAX]))                               \
+  {                                                         \
+    offset= ((intptr) UNSAFE - (intptr) ARRAY) % sizeof(T); \
+    if (offset == 0)                                        \
+      return UNSAFE;                                        \
+  }                                                         \
+  return NULL
+
 #endif
 

=== modified file 'storage/perfschema/pfs_instr.cc'
--- a/storage/perfschema/pfs_instr.cc	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/pfs_instr.cc	2010-11-16 06:27:18 +0000
@@ -775,9 +775,26 @@ PFS_thread* create_thread(PFS_thread_cla
 */
 PFS_thread *sanitize_thread(PFS_thread *unsafe)
 {
-  if ((&thread_array[0] <= unsafe) &&
-      (unsafe < &thread_array[thread_max]))
-    return unsafe;
+  SANITIZE_ARRAY_BODY(PFS_thread, thread_array, thread_max, unsafe);
+}
+
+const char *sanitize_file_name(const char *unsafe)
+{
+  intptr ptr= (intptr) unsafe;
+  intptr first= (intptr) &file_array[0];
+  intptr last= (intptr) &file_array[file_max];
+
+  /* Check if unsafe points inside file_array[] */
+  if (likely((first <= ptr) && (ptr < last)))
+  {
+    /* Check if unsafe points to PFS_file::m_filename */
+    intptr offset= (ptr - first) % sizeof(PFS_file);
+    intptr valid_offset= my_offsetof(PFS_file, m_filename[0]);
+    if (likely(offset == valid_offset))
+    {   
+      return unsafe;
+    }   
+  }
   return NULL;
 }
 

=== modified file 'storage/perfschema/pfs_instr.h'
--- a/storage/perfschema/pfs_instr.h	2010-07-30 09:02:32 +0000
+++ b/storage/perfschema/pfs_instr.h	2010-11-16 06:27:18 +0000
@@ -260,6 +260,7 @@ struct PFS_thread
 };
 
 PFS_thread *sanitize_thread(PFS_thread *unsafe);
+const char *sanitize_file_name(const char *unsafe);
 
 PFS_single_stat_chain*
 find_per_thread_mutex_class_wait_stat(PFS_thread *thread,

=== modified file 'storage/perfschema/pfs_instr_class.cc'
--- a/storage/perfschema/pfs_instr_class.cc	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/pfs_instr_class.cc	2010-11-16 06:27:18 +0000
@@ -602,15 +602,9 @@ PFS_mutex_class *find_mutex_class(PFS_sy
   FIND_CLASS_BODY(key, mutex_class_allocated_count, mutex_class_array);
 }
 
-#define SANITIZE_ARRAY_BODY(ARRAY, MAX, UNSAFE) \
-  if ((&ARRAY[0] <= UNSAFE) &&                  \
-      (UNSAFE < &ARRAY[MAX]))                   \
-    return UNSAFE;                              \
-  return NULL
-
 PFS_mutex_class *sanitize_mutex_class(PFS_mutex_class *unsafe)
 {
-  SANITIZE_ARRAY_BODY(mutex_class_array, mutex_class_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_mutex_class, mutex_class_array, mutex_class_max, unsafe);
 }
 
 /**
@@ -625,7 +619,7 @@ PFS_rwlock_class *find_rwlock_class(PFS_
 
 PFS_rwlock_class *sanitize_rwlock_class(PFS_rwlock_class *unsafe)
 {
-  SANITIZE_ARRAY_BODY(rwlock_class_array, rwlock_class_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_rwlock_class, rwlock_class_array, rwlock_class_max, unsafe);
 }
 
 /**
@@ -640,7 +634,7 @@ PFS_cond_class *find_cond_class(PFS_sync
 
 PFS_cond_class *sanitize_cond_class(PFS_cond_class *unsafe)
 {
-  SANITIZE_ARRAY_BODY(cond_class_array, cond_class_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_cond_class, cond_class_array, cond_class_max, unsafe);
 }
 
 /**
@@ -695,7 +689,7 @@ PFS_thread_class *find_thread_class(PFS_
 
 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe)
 {
-  SANITIZE_ARRAY_BODY(thread_class_array, thread_class_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_thread_class, thread_class_array, thread_class_max, unsafe);
 }
 
 /**
@@ -746,7 +740,7 @@ PFS_file_class *find_file_class(PFS_file
 
 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe)
 {
-  SANITIZE_ARRAY_BODY(file_class_array, file_class_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_file_class, file_class_array, file_class_max, unsafe);
 }
 
 /**
@@ -936,7 +930,59 @@ void drop_table_share(PFS_thread *thread
 */
 PFS_table_share *sanitize_table_share(PFS_table_share *unsafe)
 {
-  SANITIZE_ARRAY_BODY(table_share_array, table_share_max, unsafe);
+  SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe);
+}
+
+const char *sanitize_table_schema_name(const char *unsafe)
+{
+  intptr ptr= (intptr) unsafe;
+  intptr first= (intptr) &table_share_array[0];
+  intptr last= (intptr) &table_share_array[table_share_max];
+
+  PFS_table_share dummy;
+
+  /* Check if unsafe points inside table_share_array[] */
+  if (likely((first <= ptr) && (ptr < last)))
+  {
+    intptr offset= (ptr - first) % sizeof(PFS_table_share);
+    intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key);
+    intptr len= sizeof(dummy.m_key.m_hash_key);
+    /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
+    if (likely((from <= offset) && (offset < from + len)))
+    {
+      PFS_table_share *base= (PFS_table_share*) (ptr - offset);
+      /* Check if unsafe really is the schema name */
+      if (likely(base->m_schema_name == unsafe))
+        return unsafe;
+    }
+  }
+  return NULL;
+}
+
+const char *sanitize_table_object_name(const char *unsafe)
+{
+  intptr ptr= (intptr) unsafe;
+  intptr first= (intptr) &table_share_array[0];
+  intptr last= (intptr) &table_share_array[table_share_max];
+
+  PFS_table_share dummy;
+
+  /* Check if unsafe points inside table_share_array[] */
+  if (likely((first <= ptr) && (ptr < last)))
+  {
+    intptr offset= (ptr - first) % sizeof(PFS_table_share);
+    intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key);
+    intptr len= sizeof(dummy.m_key.m_hash_key);
+    /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
+    if (likely((from <= offset) && (offset < from + len)))
+    {
+      PFS_table_share *base= (PFS_table_share*) (ptr - offset);
+      /* Check if unsafe really is the table name */
+      if (likely(base->m_table_name == unsafe))
+        return unsafe;
+    }
+  }
+  return NULL;
 }
 
 static void reset_mutex_class_waits(void)

=== modified file 'storage/perfschema/pfs_instr_class.h'
--- a/storage/perfschema/pfs_instr_class.h	2010-07-23 17:08:41 +0000
+++ b/storage/perfschema/pfs_instr_class.h	2010-11-16 06:27:18 +0000
@@ -229,6 +229,8 @@ PFS_thread_class *find_thread_class(PSI_
 PFS_thread_class *sanitize_thread_class(PFS_thread_class *unsafe);
 PFS_file_class *find_file_class(PSI_file_key key);
 PFS_file_class *sanitize_file_class(PFS_file_class *unsafe);
+const char *sanitize_table_schema_name(const char *unsafe);
+const char *sanitize_table_object_name(const char *unsafe);
 
 PFS_table_share *find_or_create_table_share(PFS_thread *thread,
                                             bool temporary,

=== modified file 'storage/perfschema/table_events_waits.cc'
--- a/storage/perfschema/table_events_waits.cc	2010-11-09 08:16:50 +0000
+++ b/storage/perfschema/table_events_waits.cc	2010-11-16 06:27:18 +0000
@@ -197,6 +197,9 @@ void table_events_waits_common::make_row
   PFS_instr_class *safe_class;
   const char *base;
   const char *safe_source_file;
+  const char *safe_table_schema_name;
+  const char *safe_table_object_name;
+  const char *safe_file_name;
 
   m_row_exists= false;
   safe_thread= sanitize_thread(pfs_thread);
@@ -264,15 +267,19 @@ void table_events_waits_common::make_row
       m_row.m_object_type_length= 15;
     }
     m_row.m_object_schema_length= wait->m_schema_name_length;
+    safe_table_schema_name= sanitize_table_schema_name(wait->m_schema_name);
     if (unlikely((m_row.m_object_schema_length == 0) ||
-                 (m_row.m_object_schema_length > sizeof(m_row.m_object_schema))))
+                 (m_row.m_object_schema_length > sizeof(m_row.m_object_schema)) ||
+                 (safe_table_schema_name == NULL)))
       return;
-    memcpy(m_row.m_object_schema, wait->m_schema_name, m_row.m_object_schema_length);
+    memcpy(m_row.m_object_schema, safe_table_schema_name, m_row.m_object_schema_length);
     m_row.m_object_name_length= wait->m_object_name_length;
+    safe_table_object_name= sanitize_table_object_name(wait->m_object_name);
     if (unlikely((m_row.m_object_name_length == 0) ||
-                 (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+                 (m_row.m_object_name_length > sizeof(m_row.m_object_name)) ||
+                 (safe_table_object_name == NULL)))
       return;
-    memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
+    memcpy(m_row.m_object_name, safe_table_object_name, m_row.m_object_name_length);
     safe_class= &global_table_class;
     break;
   case WAIT_CLASS_FILE:
@@ -280,10 +287,12 @@ void table_events_waits_common::make_row
     m_row.m_object_type_length= 4;
     m_row.m_object_schema_length= 0;
     m_row.m_object_name_length= wait->m_object_name_length;
+    safe_file_name= sanitize_file_name(wait->m_object_name);
     if (unlikely((m_row.m_object_name_length == 0) ||
-                 (m_row.m_object_name_length > sizeof(m_row.m_object_name))))
+                 (m_row.m_object_name_length > sizeof(m_row.m_object_name)) ||
+                 (safe_file_name == NULL)))
       return;
-    memcpy(m_row.m_object_name, wait->m_object_name, m_row.m_object_name_length);
+    memcpy(m_row.m_object_name, safe_file_name, m_row.m_object_name_length);
     safe_class= sanitize_file_class((PFS_file_class*) wait->m_class);
     break;
   case NO_WAIT_CLASS:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (marc.alff:3347 to 3348) Marc Alff16 Nov