diff --git a/mysql-test/suite/perfschema/r/misc.result b/mysql-test/suite/perfschema/r/misc.result index d944b4b1d3d..3c0a4a58e08 100644 --- a/mysql-test/suite/perfschema/r/misc.result +++ b/mysql-test/suite/perfschema/r/misc.result @@ -11,3 +11,17 @@ create table test.t1 like performance_schema.EVENTS_WAITS_CURRENT; ERROR HY000: Invalid performance_schema usage. create table performance_schema.t1(a int); ERROR 42000: CREATE command denied to user 'root'@'localhost' for table 't1' +drop table if exists test.ghost; +create table test.ghost (a int, b int); +alter table test.ghost add index index_a(a); +alter table test.ghost add index index_b(b); +insert into test.ghost values (1, 3); +insert into test.ghost values (2, 4); +select * from test.ghost; +a b +1 3 +2 4 +drop table test.ghost; +select * from performance_schema.FILE_INSTANCES +where file_name like "%ghost%"; +FILE_NAME EVENT_NAME OPEN_COUNT diff --git a/mysql-test/suite/perfschema/t/misc.test b/mysql-test/suite/perfschema/t/misc.test index d9b97d8441e..749eccca793 100644 --- a/mysql-test/suite/perfschema/t/misc.test +++ b/mysql-test/suite/perfschema/t/misc.test @@ -55,3 +55,24 @@ create table test.t1 like performance_schema.EVENTS_WAITS_CURRENT; --error ER_TABLEACCESS_DENIED_ERROR create table performance_schema.t1(a int); +# +# Bug#51447 performance schema evil twin files +# + +--disable_warnings +drop table if exists test.ghost; +--enable_warnings + +create table test.ghost (a int, b int); +alter table test.ghost add index index_a(a); +alter table test.ghost add index index_b(b); +insert into test.ghost values (1, 3); +insert into test.ghost values (2, 4); +select * from test.ghost; + +drop table test.ghost; + +# Shoud return nothing +select * from performance_schema.FILE_INSTANCES + where file_name like "%ghost%"; + diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index 2ce3a844290..557ec1c14b5 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -746,8 +746,23 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, } } - if (len >= sizeof(pfs->m_filename)) - len= sizeof(pfs->m_filename) - 1; + /* + Normalize the file name to avoid duplicates when using aliases: + - absolute or relative paths + - symbolic links + */ + char buffer[FN_REFLEN]; + const char *normalized_filename; + int normalized_length; + + /* + Ignore errors, the file may not exist. + my_realpath always provide a best effort result in buffer. + */ + (void) my_realpath(buffer, filename, MYF(0)); + + normalized_filename= buffer; + normalized_length= strlen(normalized_filename); PFS_file **entry; uint retry_count= 0; @@ -755,7 +770,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, search: entry= reinterpret_cast (lf_hash_search(&filename_hash, thread->m_filename_hash_pins, - filename, len)); + normalized_filename, normalized_length)); if (entry && (entry != MY_ERRPTR)) { pfs= *entry; @@ -783,9 +798,9 @@ search: if (pfs->m_lock.free_to_dirty()) { pfs->m_class= klass; - strncpy(pfs->m_filename, filename, len); - pfs->m_filename[len]= '\0'; - pfs->m_filename_length= len; + strncpy(pfs->m_filename, normalized_filename, normalized_length); + pfs->m_filename[normalized_length]= '\0'; + pfs->m_filename_length= normalized_length; pfs->m_file_stat.m_open_count= 1; pfs->m_wait_stat.m_control_flag= &flag_events_waits_summary_by_instance;