diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-09-03 12:58:41 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-09-03 12:58:41 +0200 |
commit | 530a6e74819ec14b5fdc42aa588b236ecb9f2fcd (patch) | |
tree | a4d45b1fd0e434c23577507364fa443226676eb5 /storage/perfschema | |
parent | 5088cbf4ed7224698678f3eaf406361c6e7db4b8 (diff) | |
parent | 4b41e3c7f33714186c97a6cc2e6d3bb93b050c61 (diff) | |
download | mariadb-git-530a6e74819ec14b5fdc42aa588b236ecb9f2fcd.tar.gz |
Merge branch '10.0' into 10.1
referenced_by_foreign_key2(), needed for InnoDB to compile,
was taken from 10.0-galera
Diffstat (limited to 'storage/perfschema')
27 files changed, 293 insertions, 103 deletions
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index 81592c85d0c..29e74271670 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -225,7 +225,7 @@ maria_declare_plugin(perfschema) 0x0001, pfs_status_vars, NULL, - "5.6.25", + "5.6.26", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc index 3eff670f44d..4e3a6d8d1d3 100644 --- a/storage/perfschema/pfs_account.cc +++ b/storage/perfschema/pfs_account.cc @@ -69,8 +69,8 @@ int init_account(const PFS_global_param *param) if (account_max > 0) { - account_array= PFS_MALLOC_ARRAY(account_max, PFS_account, - MYF(MY_ZEROFILL)); + account_array= PFS_MALLOC_ARRAY(account_max, sizeof(PFS_account), PFS_account, + MYF(MY_ZEROFILL)); if (unlikely(account_array == NULL)) return 1; } diff --git a/storage/perfschema/pfs_con_slice.cc b/storage/perfschema/pfs_con_slice.cc index 263f25c1c08..bd449df0a4b 100644 --- a/storage/perfschema/pfs_con_slice.cc +++ b/storage/perfschema/pfs_con_slice.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,7 +39,8 @@ PFS_connection_slice::alloc_waits_slice(uint sizing) if (sizing > 0) { - slice= PFS_MALLOC_ARRAY(sizing, PFS_single_stat, MYF(MY_ZEROFILL)); + slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_single_stat), PFS_single_stat, + MYF(MY_ZEROFILL)); if (unlikely(slice == NULL)) return NULL; @@ -58,7 +59,8 @@ PFS_connection_slice::alloc_stages_slice(uint sizing) if (sizing > 0) { - slice= PFS_MALLOC_ARRAY(sizing, PFS_stage_stat, MYF(MY_ZEROFILL)); + slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_stage_stat), PFS_stage_stat, + MYF(MY_ZEROFILL)); if (unlikely(slice == NULL)) return NULL; @@ -77,7 +79,8 @@ PFS_connection_slice::alloc_statements_slice(uint sizing) if (sizing > 0) { - slice= PFS_MALLOC_ARRAY(sizing, PFS_statement_stat, MYF(MY_ZEROFILL)); + slice= PFS_MALLOC_ARRAY(sizing, sizeof(PFS_statement_stat), PFS_statement_stat, + MYF(MY_ZEROFILL)); if (unlikely(slice == NULL)) return NULL; diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc index 6c0b41908e1..0a01ee08993 100644 --- a/storage/perfschema/pfs_digest.cc +++ b/storage/perfschema/pfs_digest.cc @@ -35,7 +35,7 @@ #include "sql_string.h" #include <string.h> -ulong digest_max= 0; +size_t digest_max= 0; ulong digest_lost= 0; /** EVENTS_STATEMENTS_HISTORY_LONG circular buffer. */ @@ -59,8 +59,6 @@ static bool digest_hash_inited= false; */ int init_digest(const PFS_global_param *param) { - unsigned int index; - /* Allocate memory for statements_digest_stat_array based on performance_schema_digests_size values @@ -75,6 +73,7 @@ int init_digest(const PFS_global_param *param) statements_digest_stat_array= PFS_MALLOC_ARRAY(digest_max, + sizeof(PFS_statements_digest_stat), PFS_statements_digest_stat, MYF(MY_ZEROFILL)); @@ -86,8 +85,12 @@ int init_digest(const PFS_global_param *param) if (pfs_max_digest_length > 0) { + /* Size of each digest array. */ + size_t digest_memory_size= pfs_max_digest_length * sizeof(unsigned char); + statements_digest_token_array= - PFS_MALLOC_ARRAY(digest_max * pfs_max_digest_length, + PFS_MALLOC_ARRAY(digest_max, + digest_memory_size, unsigned char, MYF(MY_ZEROFILL)); @@ -98,7 +101,7 @@ int init_digest(const PFS_global_param *param) } } - for (index= 0; index < digest_max; index++) + for (size_t index= 0; index < digest_max; index++) { statements_digest_stat_array[index].reset_data(statements_digest_token_array + index * pfs_max_digest_length, pfs_max_digest_length); @@ -336,8 +339,6 @@ void PFS_statements_digest_stat::reset_index(PFS_thread *thread) void reset_esms_by_digest() { - uint index; - if (statements_digest_stat_array == NULL) return; @@ -346,7 +347,7 @@ void reset_esms_by_digest() return; /* Reset statements_digest_stat_array. */ - for (index= 0; index < digest_max; index++) + for (size_t index= 0; index < digest_max; index++) { statements_digest_stat_array[index].reset_index(thread); statements_digest_stat_array[index].reset_data(statements_digest_token_array + index * pfs_max_digest_length, pfs_max_digest_length); diff --git a/storage/perfschema/pfs_digest.h b/storage/perfschema/pfs_digest.h index 9d021737c44..76d6c33d984 100644 --- a/storage/perfschema/pfs_digest.h +++ b/storage/perfschema/pfs_digest.h @@ -27,7 +27,7 @@ #include "sql_digest.h" extern bool flag_statements_digest; -extern ulong digest_max; +extern size_t digest_max; extern ulong digest_lost; struct PFS_thread; diff --git a/storage/perfschema/pfs_events_stages.cc b/storage/perfschema/pfs_events_stages.cc index 282071f830e..7351c95c9cb 100644 --- a/storage/perfschema/pfs_events_stages.cc +++ b/storage/perfschema/pfs_events_stages.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,8 +59,8 @@ int init_events_stages_history_long(uint events_stages_history_long_sizing) return 0; events_stages_history_long_array= - PFS_MALLOC_ARRAY(events_stages_history_long_size, PFS_events_stages, - MYF(MY_ZEROFILL)); + PFS_MALLOC_ARRAY(events_stages_history_long_size, sizeof(PFS_events_stages), + PFS_events_stages, MYF(MY_ZEROFILL)); return (events_stages_history_long_array ? 0 : 1); } diff --git a/storage/perfschema/pfs_events_statements.cc b/storage/perfschema/pfs_events_statements.cc index dc34755d747..cecd0167c38 100644 --- a/storage/perfschema/pfs_events_statements.cc +++ b/storage/perfschema/pfs_events_statements.cc @@ -30,7 +30,7 @@ #include "pfs_atomic.h" #include "m_string.h" -ulong events_statements_history_long_size= 0; +size_t events_statements_history_long_size= 0; /** Consumer flag for table EVENTS_STATEMENTS_CURRENT. */ bool flag_events_statements_current= false; /** Consumer flag for table EVENTS_STATEMENTS_HISTORY. */ @@ -50,9 +50,8 @@ static unsigned char *h_long_stmts_digest_token_array= NULL; Initialize table EVENTS_STATEMENTS_HISTORY_LONG. @param events_statements_history_long_sizing table sizing */ -int init_events_statements_history_long(uint events_statements_history_long_sizing) +int init_events_statements_history_long(size_t events_statements_history_long_sizing) { - uint index; events_statements_history_long_size= events_statements_history_long_sizing; events_statements_history_long_full= false; PFS_atomic::store_u32(&events_statements_history_long_index, 0); @@ -61,8 +60,8 @@ int init_events_statements_history_long(uint events_statements_history_long_sizi return 0; events_statements_history_long_array= - PFS_MALLOC_ARRAY(events_statements_history_long_size, PFS_events_statements, - MYF(MY_ZEROFILL)); + PFS_MALLOC_ARRAY(events_statements_history_long_size, sizeof(PFS_events_statements), + PFS_events_statements, MYF(MY_ZEROFILL)); if (events_statements_history_long_array == NULL) { @@ -72,8 +71,11 @@ int init_events_statements_history_long(uint events_statements_history_long_sizi if (pfs_max_digest_length > 0) { + /* Size of each digest token array. */ + size_t digest_text_size= pfs_max_digest_length * sizeof(unsigned char); + h_long_stmts_digest_token_array= - PFS_MALLOC_ARRAY(events_statements_history_long_size * pfs_max_digest_length, + PFS_MALLOC_ARRAY(events_statements_history_long_size, digest_text_size, unsigned char, MYF(MY_ZEROFILL)); if (h_long_stmts_digest_token_array == NULL) { @@ -82,7 +84,7 @@ int init_events_statements_history_long(uint events_statements_history_long_sizi } } - for (index= 0; index < events_statements_history_long_size; index++) + for (size_t index= 0; index < events_statements_history_long_size; index++) { events_statements_history_long_array[index].m_digest_storage.reset(h_long_stmts_digest_token_array + index * pfs_max_digest_length, pfs_max_digest_length); diff --git a/storage/perfschema/pfs_events_statements.h b/storage/perfschema/pfs_events_statements.h index 3637e4ca764..b1e303e7021 100644 --- a/storage/perfschema/pfs_events_statements.h +++ b/storage/perfschema/pfs_events_statements.h @@ -106,9 +106,9 @@ extern bool flag_events_statements_history_long; extern bool events_statements_history_long_full; extern volatile uint32 events_statements_history_long_index; extern PFS_events_statements *events_statements_history_long_array; -extern ulong events_statements_history_long_size; +extern size_t events_statements_history_long_size; -int init_events_statements_history_long(uint events_statements_history_long_sizing); +int init_events_statements_history_long(size_t events_statements_history_long_sizing); void cleanup_events_statements_history_long(); void reset_events_statements_current(); diff --git a/storage/perfschema/pfs_events_waits.cc b/storage/perfschema/pfs_events_waits.cc index 2799550c81d..1120ac2a445 100644 --- a/storage/perfschema/pfs_events_waits.cc +++ b/storage/perfschema/pfs_events_waits.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,8 +63,8 @@ int init_events_waits_history_long(uint events_waits_history_long_sizing) return 0; events_waits_history_long_array= - PFS_MALLOC_ARRAY(events_waits_history_long_size, PFS_events_waits, - MYF(MY_ZEROFILL)); + PFS_MALLOC_ARRAY(events_waits_history_long_size, sizeof(PFS_events_waits), + PFS_events_waits, MYF(MY_ZEROFILL)); return (events_waits_history_long_array ? 0 : 1); } diff --git a/storage/perfschema/pfs_global.cc b/storage/perfschema/pfs_global.cc index 0744bbab7d5..bd346f2b235 100644 --- a/storage/perfschema/pfs_global.cc +++ b/storage/perfschema/pfs_global.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,7 +52,7 @@ void *pfs_malloc(size_t size, myf flags) DBUG_ASSERT(! pfs_initialized); DBUG_ASSERT(size > 0); - void *ptr; + void *ptr= NULL; #ifdef PFS_ALIGNEMENT #ifdef HAVE_POSIX_MEMALIGN @@ -128,6 +128,40 @@ void pfs_print_error(const char *format, ...) fflush(stderr); } +/** + Array allocation for the performance schema. + Checks for overflow of n * size before allocating. + @param n number of array elements + @param size element size + @param flags malloc flags + @return pointer to memory on success, else NULL +*/ +void *pfs_malloc_array(size_t n, size_t size, myf flags) +{ + DBUG_ASSERT(n > 0); + DBUG_ASSERT(size > 0); + size_t array_size= n * size; + /* Check for overflow before allocating. */ + if (is_overflow(array_size, n, size)) + return NULL; + return pfs_malloc(array_size, flags); +} + +/** + Detect multiplication overflow. + @param product multiplication product + @param n1 operand + @param n2 operand + @return true if multiplication caused an overflow. +*/ +bool is_overflow(size_t product, size_t n1, size_t n2) +{ + if (n1 != 0 && (product / n1 != n2)) + return true; + else + return false; +} + /** Convert raw ip address into readable format. Do not do a reverse DNS lookup. */ uint pfs_get_socket_address(char *host, diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h index f9687524cd5..f3326c5589f 100644 --- a/storage/perfschema/pfs_global.h +++ b/storage/perfschema/pfs_global.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,18 +44,24 @@ extern size_t pfs_allocated_memory; void *pfs_malloc(size_t size, myf flags); +/** Allocate an array of structures with overflow check. */ +void *pfs_malloc_array(size_t n, size_t size, myf flags); + /** Helper, to allocate an array of structures. - @param n number of elements in the array. - @param T type of an element. + @param n number of elements in the array + @param s size of array element + @param T type of an element @param f flags to use when allocating memory */ -#define PFS_MALLOC_ARRAY(n, T, f) \ - reinterpret_cast<T*> (pfs_malloc((n) * sizeof(T), (f))) +#define PFS_MALLOC_ARRAY(n, s, T, f) \ + reinterpret_cast<T*>(pfs_malloc_array((n), (s), (f))) /** Free memory allocated with @sa pfs_malloc. */ void pfs_free(void *ptr); +/** Detect multiplication overflow. */ +bool is_overflow(size_t product, size_t n1, size_t n2); uint pfs_get_socket_address(char *host, uint host_len, @@ -107,7 +113,7 @@ inline uint randomized_index(const void *ptr, uint max_size) value= (reinterpret_cast<intptr> (ptr)) >> 3; value*= 1789; value+= seed2 + seed1 + 1; - + result= (static_cast<uint> (value)) % max_size; seed2= seed1*seed1; diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc index 80f3900275d..7da34a6d5f6 100644 --- a/storage/perfschema/pfs_host.cc +++ b/storage/perfschema/pfs_host.cc @@ -66,7 +66,7 @@ int init_host(const PFS_global_param *param) if (host_max > 0) { - host_array= PFS_MALLOC_ARRAY(host_max, PFS_host, + host_array= PFS_MALLOC_ARRAY(host_max, sizeof(PFS_host), PFS_host, MYF(MY_ZEROFILL)); if (unlikely(host_array == NULL)) return 1; diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index 5e75df4a16f..a9ea6faf212 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -94,7 +94,7 @@ ulong events_stages_history_per_thread; /** Number of EVENTS_STATEMENTS_HISTORY records per thread. */ ulong events_statements_history_per_thread; uint statement_stack_max; -uint pfs_max_digest_length= 0; +size_t pfs_max_digest_length= 0; /** Number of locker lost. @sa LOCKER_STACK_SIZE. */ ulong locker_lost= 0; /** Number of statement lost. @sa STATEMENT_STACK_SIZE. */ @@ -287,56 +287,56 @@ int init_instruments(const PFS_global_param *param) if (mutex_max > 0) { - mutex_array= PFS_MALLOC_ARRAY(mutex_max, PFS_mutex, MYF(MY_ZEROFILL)); + mutex_array= PFS_MALLOC_ARRAY(mutex_max, sizeof(PFS_mutex), PFS_mutex, MYF(MY_ZEROFILL)); if (unlikely(mutex_array == NULL)) return 1; } if (rwlock_max > 0) { - rwlock_array= PFS_MALLOC_ARRAY(rwlock_max, PFS_rwlock, MYF(MY_ZEROFILL)); + rwlock_array= PFS_MALLOC_ARRAY(rwlock_max, sizeof(PFS_rwlock), PFS_rwlock, MYF(MY_ZEROFILL)); if (unlikely(rwlock_array == NULL)) return 1; } if (cond_max > 0) { - cond_array= PFS_MALLOC_ARRAY(cond_max, PFS_cond, MYF(MY_ZEROFILL)); + cond_array= PFS_MALLOC_ARRAY(cond_max, sizeof(PFS_cond), PFS_cond, MYF(MY_ZEROFILL)); if (unlikely(cond_array == NULL)) return 1; } if (file_max > 0) { - file_array= PFS_MALLOC_ARRAY(file_max, PFS_file, MYF(MY_ZEROFILL)); + file_array= PFS_MALLOC_ARRAY(file_max, sizeof(PFS_file), PFS_file, MYF(MY_ZEROFILL)); if (unlikely(file_array == NULL)) return 1; } if (file_handle_max > 0) { - file_handle_array= PFS_MALLOC_ARRAY(file_handle_max, PFS_file*, MYF(MY_ZEROFILL)); + file_handle_array= PFS_MALLOC_ARRAY(file_handle_max, sizeof(PFS_file*), PFS_file*, MYF(MY_ZEROFILL)); if (unlikely(file_handle_array == NULL)) return 1; } if (table_max > 0) { - table_array= PFS_MALLOC_ARRAY(table_max, PFS_table, MYF(MY_ZEROFILL)); + table_array= PFS_MALLOC_ARRAY(table_max, sizeof(PFS_table), PFS_table, MYF(MY_ZEROFILL)); if (unlikely(table_array == NULL)) return 1; } if (socket_max > 0) { - socket_array= PFS_MALLOC_ARRAY(socket_max, PFS_socket, MYF(MY_ZEROFILL)); + socket_array= PFS_MALLOC_ARRAY(socket_max, sizeof(PFS_socket), PFS_socket, MYF(MY_ZEROFILL)); if (unlikely(socket_array == NULL)) return 1; } if (thread_max > 0) { - thread_array= PFS_MALLOC_ARRAY(thread_max, PFS_thread, MYF(MY_ZEROFILL)); + thread_array= PFS_MALLOC_ARRAY(thread_max, sizeof(PFS_thread), PFS_thread, MYF(MY_ZEROFILL)); if (unlikely(thread_array == NULL)) return 1; } @@ -344,7 +344,7 @@ int init_instruments(const PFS_global_param *param) if (thread_waits_history_sizing > 0) { thread_waits_history_array= - PFS_MALLOC_ARRAY(thread_waits_history_sizing, PFS_events_waits, + PFS_MALLOC_ARRAY(thread_waits_history_sizing, sizeof(PFS_events_waits), PFS_events_waits, MYF(MY_ZEROFILL)); if (unlikely(thread_waits_history_array == NULL)) return 1; @@ -354,7 +354,7 @@ int init_instruments(const PFS_global_param *param) { thread_instr_class_waits_array= PFS_MALLOC_ARRAY(thread_instr_class_waits_sizing, - PFS_single_stat, MYF(MY_ZEROFILL)); + sizeof(PFS_single_stat), PFS_single_stat, MYF(MY_ZEROFILL)); if (unlikely(thread_instr_class_waits_array == NULL)) return 1; @@ -365,7 +365,7 @@ int init_instruments(const PFS_global_param *param) if (thread_stages_history_sizing > 0) { thread_stages_history_array= - PFS_MALLOC_ARRAY(thread_stages_history_sizing, PFS_events_stages, + PFS_MALLOC_ARRAY(thread_stages_history_sizing, sizeof(PFS_events_stages), PFS_events_stages, MYF(MY_ZEROFILL)); if (unlikely(thread_stages_history_array == NULL)) return 1; @@ -375,7 +375,7 @@ int init_instruments(const PFS_global_param *param) { thread_instr_class_stages_array= PFS_MALLOC_ARRAY(thread_instr_class_stages_sizing, - PFS_stage_stat, MYF(MY_ZEROFILL)); + sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL)); if (unlikely(thread_instr_class_stages_array == NULL)) return 1; @@ -386,8 +386,8 @@ int init_instruments(const PFS_global_param *param) if (thread_statements_history_sizing > 0) { thread_statements_history_array= - PFS_MALLOC_ARRAY(thread_statements_history_sizing, PFS_events_statements, - MYF(MY_ZEROFILL)); + PFS_MALLOC_ARRAY(thread_statements_history_sizing, sizeof(PFS_events_statements), + PFS_events_statements, MYF(MY_ZEROFILL)); if (unlikely(thread_statements_history_array == NULL)) return 1; } @@ -395,8 +395,8 @@ int init_instruments(const PFS_global_param *param) if (thread_statements_stack_sizing > 0) { thread_statements_stack_array= - PFS_MALLOC_ARRAY(thread_statements_stack_sizing, PFS_events_statements, - MYF(MY_ZEROFILL)); + PFS_MALLOC_ARRAY(thread_statements_stack_sizing, sizeof(PFS_events_statements), + PFS_events_statements, MYF(MY_ZEROFILL)); if (unlikely(thread_statements_stack_array == NULL)) return 1; } @@ -405,7 +405,7 @@ int init_instruments(const PFS_global_param *param) { thread_instr_class_statements_array= PFS_MALLOC_ARRAY(thread_instr_class_statements_sizing, - PFS_statement_stat, MYF(MY_ZEROFILL)); + sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL)); if (unlikely(thread_instr_class_statements_array == NULL)) return 1; @@ -477,7 +477,7 @@ int init_instruments(const PFS_global_param *param) { global_instr_class_stages_array= PFS_MALLOC_ARRAY(stage_class_max, - PFS_stage_stat, MYF(MY_ZEROFILL)); + sizeof(PFS_stage_stat), PFS_stage_stat, MYF(MY_ZEROFILL)); if (unlikely(global_instr_class_stages_array == NULL)) return 1; @@ -489,7 +489,7 @@ int init_instruments(const PFS_global_param *param) { global_instr_class_statements_array= PFS_MALLOC_ARRAY(statement_class_max, - PFS_statement_stat, MYF(MY_ZEROFILL)); + sizeof(PFS_statement_stat), PFS_statement_stat, MYF(MY_ZEROFILL)); if (unlikely(global_instr_class_statements_array == NULL)) return 1; diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h index a639f94fada..b25f5769b69 100644 --- a/storage/perfschema/pfs_instr.h +++ b/storage/perfschema/pfs_instr.h @@ -299,7 +299,7 @@ struct PFS_ALIGNED PFS_socket : public PFS_instr /** Max size of the statements stack. */ extern uint statement_stack_max; /** Max size of the digests token array. */ -extern uint pfs_max_digest_length; +extern size_t pfs_max_digest_length; /** @def PFS_MAX_ALLOC_RETRY diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index 84e0a0357a0..c67c120283d 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -255,24 +255,24 @@ int init_sync_class(uint mutex_class_sizing, if (mutex_class_max > 0) { - mutex_class_array= PFS_MALLOC_ARRAY(mutex_class_max, PFS_mutex_class, - MYF(MY_ZEROFILL)); + mutex_class_array= PFS_MALLOC_ARRAY(mutex_class_max, sizeof(PFS_mutex_class), + PFS_mutex_class, MYF(MY_ZEROFILL)); if (unlikely(mutex_class_array == NULL)) return 1; } if (rwlock_class_max > 0) { - rwlock_class_array= PFS_MALLOC_ARRAY(rwlock_class_max, PFS_rwlock_class, - MYF(MY_ZEROFILL)); + rwlock_class_array= PFS_MALLOC_ARRAY(rwlock_class_max, sizeof(PFS_rwlock_class), + PFS_rwlock_class, MYF(MY_ZEROFILL)); if (unlikely(rwlock_class_array == NULL)) return 1; } if (cond_class_max > 0) { - cond_class_array= PFS_MALLOC_ARRAY(cond_class_max, PFS_cond_class, - MYF(MY_ZEROFILL)); + cond_class_array= PFS_MALLOC_ARRAY(cond_class_max, sizeof(PFS_cond_class), + PFS_cond_class, MYF(MY_ZEROFILL)); if (unlikely(cond_class_array == NULL)) return 1; } @@ -308,8 +308,8 @@ int init_thread_class(uint thread_class_sizing) if (thread_class_max > 0) { - thread_class_array= PFS_MALLOC_ARRAY(thread_class_max, PFS_thread_class, - MYF(MY_ZEROFILL)); + thread_class_array= PFS_MALLOC_ARRAY(thread_class_max, sizeof(PFS_thread_class), + PFS_thread_class, MYF(MY_ZEROFILL)); if (unlikely(thread_class_array == NULL)) result= 1; } @@ -341,8 +341,8 @@ int init_table_share(uint table_share_sizing) if (table_share_max > 0) { - table_share_array= PFS_MALLOC_ARRAY(table_share_max, PFS_table_share, - MYF(MY_ZEROFILL)); + table_share_array= PFS_MALLOC_ARRAY(table_share_max, sizeof(PFS_table_share), + PFS_table_share, MYF(MY_ZEROFILL)); if (unlikely(table_share_array == NULL)) result= 1; } @@ -481,8 +481,8 @@ int init_file_class(uint file_class_sizing) if (file_class_max > 0) { - file_class_array= PFS_MALLOC_ARRAY(file_class_max, PFS_file_class, - MYF(MY_ZEROFILL)); + file_class_array= PFS_MALLOC_ARRAY(file_class_max, sizeof(PFS_file_class), + PFS_file_class, MYF(MY_ZEROFILL)); if (unlikely(file_class_array == NULL)) return 1; } @@ -515,8 +515,8 @@ int init_stage_class(uint stage_class_sizing) if (stage_class_max > 0) { - stage_class_array= PFS_MALLOC_ARRAY(stage_class_max, PFS_stage_class, - MYF(MY_ZEROFILL)); + stage_class_array= PFS_MALLOC_ARRAY(stage_class_max, sizeof(PFS_stage_class), + PFS_stage_class, MYF(MY_ZEROFILL)); if (unlikely(stage_class_array == NULL)) return 1; } @@ -549,8 +549,8 @@ int init_statement_class(uint statement_class_sizing) if (statement_class_max > 0) { - statement_class_array= PFS_MALLOC_ARRAY(statement_class_max, PFS_statement_class, - MYF(MY_ZEROFILL)); + statement_class_array= PFS_MALLOC_ARRAY(statement_class_max, sizeof(PFS_statement_class), + PFS_statement_class, MYF(MY_ZEROFILL)); if (unlikely(statement_class_array == NULL)) return 1; } @@ -583,8 +583,8 @@ int init_socket_class(uint socket_class_sizing) if (socket_class_max > 0) { - socket_class_array= PFS_MALLOC_ARRAY(socket_class_max, PFS_socket_class, - MYF(MY_ZEROFILL)); + socket_class_array= PFS_MALLOC_ARRAY(socket_class_max, sizeof(PFS_socket_class), + PFS_socket_class, MYF(MY_ZEROFILL)); if (unlikely(socket_class_array == NULL)) return 1; } diff --git a/storage/perfschema/pfs_server.h b/storage/perfschema/pfs_server.h index e0fe71bc8c5..bc0c69e86b9 100644 --- a/storage/perfschema/pfs_server.h +++ b/storage/perfschema/pfs_server.h @@ -200,7 +200,7 @@ struct PFS_global_param /** Maximum number of session attribute strings per thread */ long m_session_connect_attrs_sizing; - uint m_max_digest_length; + long m_max_digest_length; /** Sizing hints, for auto tuning. */ PFS_sizing_hints m_hints; diff --git a/storage/perfschema/pfs_setup_actor.cc b/storage/perfschema/pfs_setup_actor.cc index ff45e4a0971..f12d70840c1 100644 --- a/storage/perfschema/pfs_setup_actor.cc +++ b/storage/perfschema/pfs_setup_actor.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,8 +60,8 @@ int init_setup_actor(const PFS_global_param *param) if (setup_actor_max > 0) { - setup_actor_array= PFS_MALLOC_ARRAY(setup_actor_max, PFS_setup_actor, - MYF(MY_ZEROFILL)); + setup_actor_array= PFS_MALLOC_ARRAY(setup_actor_max, sizeof(PFS_setup_actor), + PFS_setup_actor, MYF(MY_ZEROFILL)); if (unlikely(setup_actor_array == NULL)) return 1; } diff --git a/storage/perfschema/pfs_setup_object.cc b/storage/perfschema/pfs_setup_object.cc index c77039663b2..809fe8edd24 100644 --- a/storage/perfschema/pfs_setup_object.cc +++ b/storage/perfschema/pfs_setup_object.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,8 +55,8 @@ int init_setup_object(const PFS_global_param *param) if (setup_object_max > 0) { - setup_object_array= PFS_MALLOC_ARRAY(setup_object_max, PFS_setup_object, - MYF(MY_ZEROFILL)); + setup_object_array= PFS_MALLOC_ARRAY(setup_object_max, sizeof(PFS_setup_object), + PFS_setup_object, MYF(MY_ZEROFILL)); if (unlikely(setup_object_array == NULL)) return 1; } diff --git a/storage/perfschema/pfs_user.cc b/storage/perfschema/pfs_user.cc index a009e5d65ef..528457fe017 100644 --- a/storage/perfschema/pfs_user.cc +++ b/storage/perfschema/pfs_user.cc @@ -66,7 +66,7 @@ int init_user(const PFS_global_param *param) if (user_max > 0) { - user_array= PFS_MALLOC_ARRAY(user_max, PFS_user, + user_array= PFS_MALLOC_ARRAY(user_max, sizeof(PFS_user), PFS_user, MYF(MY_ZEROFILL)); if (unlikely(user_array == NULL)) return 1; diff --git a/storage/perfschema/table_events_stages.cc b/storage/perfschema/table_events_stages.cc index f98ff60d569..42761d92abf 100644 --- a/storage/perfschema/table_events_stages.cc +++ b/storage/perfschema/table_events_stages.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -121,6 +121,7 @@ void table_events_stages_common::make_row(PFS_events_stages *stage) { const char *base; const char *safe_source_file; + ulonglong timer_end; m_row_exists= false; @@ -135,7 +136,16 @@ void table_events_stages_common::make_row(PFS_events_stages *stage) m_row.m_nesting_event_id= stage->m_nesting_event_id; m_row.m_nesting_event_type= stage->m_nesting_event_type; - m_normalizer->to_pico(stage->m_timer_start, stage->m_timer_end, + if (m_row.m_end_event_id == 0) + { + timer_end= get_timer_raw_value(stage_timer); + } + else + { + timer_end= stage->m_timer_end; + } + + m_normalizer->to_pico(stage->m_timer_start, timer_end, & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait); m_row.m_name= klass->m_name; diff --git a/storage/perfschema/table_events_statements.cc b/storage/perfschema/table_events_statements.cc index 16f048a0a7f..84f30ce000f 100644 --- a/storage/perfschema/table_events_statements.cc +++ b/storage/perfschema/table_events_statements.cc @@ -215,6 +215,7 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat { const char *base; const char *safe_source_file; + ulonglong timer_end; m_row_exists= false; @@ -229,7 +230,16 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat m_row.m_nesting_event_id= statement->m_nesting_event_id; m_row.m_nesting_event_type= statement->m_nesting_event_type; - m_normalizer->to_pico(statement->m_timer_start, statement->m_timer_end, + if (m_row.m_end_event_id == 0) + { + timer_end= get_timer_raw_value(statement_timer); + } + else + { + timer_end= statement->m_timer_end; + } + + m_normalizer->to_pico(statement->m_timer_start, timer_end, & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait); m_row.m_lock_time= statement->m_lock_time * MICROSEC_TO_PICOSEC; @@ -249,8 +259,8 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat return; base= base_name(safe_source_file); - m_row.m_source_length= my_snprintf(m_row.m_source, sizeof(m_row.m_source), - "%s:%d", base, statement->m_source_line); + m_row.m_source_length= (uint)my_snprintf(m_row.m_source, sizeof(m_row.m_source), + "%s:%d", base, statement->m_source_line); if (m_row.m_source_length > sizeof(m_row.m_source)) m_row.m_source_length= sizeof(m_row.m_source); @@ -291,7 +301,7 @@ void table_events_statements_common::make_row_part_2(const sql_digest_storage *d /* Filling up statement digest information. */ - uint safe_byte_count= digest->m_byte_count; + size_t safe_byte_count= digest->m_byte_count; if (safe_byte_count > 0 && safe_byte_count <= pfs_max_digest_length) { @@ -428,7 +438,7 @@ int table_events_statements_common::read_row_values(TABLE *table, f->set_null(); break; case 19: /* MESSAGE_TEXT */ - len= strlen(m_row.m_message_text); + len= (uint)strlen(m_row.m_message_text); if (len) set_field_varchar_utf8(f, m_row.m_message_text, len); else @@ -790,7 +800,7 @@ int table_events_statements_history_long::rnd_init(bool scan) int table_events_statements_history_long::rnd_next(void) { PFS_events_statements *statement; - uint limit; + size_t limit; if (events_statements_history_long_size == 0) return HA_ERR_END_OF_FILE; @@ -819,7 +829,7 @@ int table_events_statements_history_long::rnd_next(void) int table_events_statements_history_long::rnd_pos(const void *pos) { PFS_events_statements *statement; - uint limit; + size_t limit; if (events_statements_history_long_size == 0) return HA_ERR_RECORD_DELETED; diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc index 8e2d0064538..cd32d81519e 100644 --- a/storage/perfschema/table_events_waits.cc +++ b/storage/perfschema/table_events_waits.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -318,6 +318,8 @@ void table_events_waits_common::make_row(bool thread_own_wait, PFS_instr_class *safe_class; const char *base; const char *safe_source_file; + enum_timer_name timer_name= wait_timer; + ulonglong timer_end; m_row_exists= false; safe_thread= sanitize_thread(pfs_thread); @@ -356,6 +358,7 @@ void table_events_waits_common::make_row(bool thread_own_wait, case WAIT_CLASS_IDLE: clear_object_columns(); safe_class= sanitize_idle_class(wait->m_class); + timer_name= idle_timer; break; case WAIT_CLASS_MUTEX: clear_object_columns(); @@ -399,7 +402,17 @@ void table_events_waits_common::make_row(bool thread_own_wait, m_row.m_nesting_event_type= wait->m_nesting_event_type; get_normalizer(safe_class); - m_normalizer->to_pico(wait->m_timer_start, wait->m_timer_end, + + if (m_row.m_end_event_id == 0) + { + timer_end= get_timer_raw_value(timer_name); + } + else + { + timer_end= wait->m_timer_end; + } + + m_normalizer->to_pico(wait->m_timer_start, timer_end, & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait); m_row.m_name= safe_class->m_name; diff --git a/storage/perfschema/table_helper.cc b/storage/perfschema/table_helper.cc index c9def1bfc74..d064333dc7e 100644 --- a/storage/perfschema/table_helper.cc +++ b/storage/perfschema/table_helper.cc @@ -110,7 +110,7 @@ int PFS_digest_row::make_row(PFS_statements_digest_stat* pfs) if (m_schema_name_length > 0) memcpy(m_schema_name, pfs->m_digest_key.m_schema_name, m_schema_name_length); - uint safe_byte_count= pfs->m_digest_storage.m_byte_count; + size_t safe_byte_count= pfs->m_digest_storage.m_byte_count; if (safe_byte_count > pfs_max_digest_length) safe_byte_count= 0; diff --git a/storage/perfschema/unittest/CMakeLists.txt b/storage/perfschema/unittest/CMakeLists.txt index e8b11e807bf..4c6b0b91021 100644 --- a/storage/perfschema/unittest/CMakeLists.txt +++ b/storage/perfschema/unittest/CMakeLists.txt @@ -28,5 +28,5 @@ ADD_CONVENIENCE_LIBRARY(pfs_server_stubs pfs_server_stubs.cc) ADD_DEPENDENCIES(pfs_server_stubs GenError) MY_ADD_TESTS(pfs_instr_class pfs_instr_class-oom pfs_instr pfs_instr-oom - pfs_account-oom pfs_host-oom pfs_timer pfs_user-oom pfs + pfs_account-oom pfs_host-oom pfs_timer pfs_user-oom pfs pfs_misc EXT "cc" LINK_LIBRARIES perfschema mysys pfs_server_stubs) diff --git a/storage/perfschema/unittest/pfs_misc-t.cc b/storage/perfschema/unittest/pfs_misc-t.cc new file mode 100644 index 00000000000..a4b11b9a727 --- /dev/null +++ b/storage/perfschema/unittest/pfs_misc-t.cc @@ -0,0 +1,72 @@ +/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <pfs_instr.h> +#include <pfs_stat.h> +#include <pfs_global.h> +#include <pfs_instr_class.h> +#include <tap.h> + +#include <memory.h> + +void test_digest_length_overflow() +{ + if (sizeof(size_t) != 4) + { + skip(2, "digest length overflow requires a 32-bit environment"); + return; + } + + PFS_global_param param; + memset(¶m, 0, sizeof(param)); + param.m_enabled= true; + /* + Force 32-bit arithmetic overflow using the digest memory allocation + parameters. The Performance Schema should detect the overflow, free + allocated memory and abort initialization with a warning. + */ + + /* Max digest length, events_statements_history_long. */ + param.m_events_statements_history_long_sizing= 10000; + param.m_digest_sizing= 1000; + param.m_max_digest_length= (1024 * 1024); + pfs_max_digest_length= param.m_max_digest_length; + + int rc = init_events_statements_history_long(param.m_events_statements_history_long_sizing); + ok(rc == 1, "digest length overflow (init_events_statements_history_long"); + + /* Max digest length, events_statements_summary_by_digest. */ + param.m_max_digest_length= (1024 * 1024); + param.m_digest_sizing= 10000; + + rc = init_digest(¶m); + ok(rc == 1, "digest length overflow (init_digest)"); +} + +void do_all_tests() +{ + test_digest_length_overflow(); +} + +int main(int, char **) +{ + plan(2); + MY_INIT("pfs_misc-t"); + do_all_tests(); + my_end(0); + return exit_status(); +} + diff --git a/storage/perfschema/unittest/stub_pfs_global.h b/storage/perfschema/unittest/stub_pfs_global.h index 34c52e18b5a..8f204006f48 100644 --- a/storage/perfschema/unittest/stub_pfs_global.h +++ b/storage/perfschema/unittest/stub_pfs_global.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,11 @@ int stub_alloc_fails_after_count= 0; void *pfs_malloc(size_t size, myf) { + /* + Catch non initialized sizing parameter in the unit tests. + */ + DBUG_ASSERT(size <= 100*1024*1024); + if (stub_alloc_always_fails) return NULL; @@ -43,6 +48,23 @@ void pfs_free(void *ptr) free(ptr); } +void *pfs_malloc_array(size_t n, size_t size, myf flags) +{ + size_t array_size= n * size; + /* Check for overflow before allocating. */ + if (is_overflow(array_size, n, size)) + return NULL; + return pfs_malloc(array_size, flags); +} + +bool is_overflow(size_t product, size_t n1, size_t n2) +{ + if (n1 != 0 && (product / n1 != n2)) + return true; + else + return false; +} + void pfs_print_error(const char *format, ...) { } diff --git a/storage/perfschema/unittest/stub_print_error.h b/storage/perfschema/unittest/stub_print_error.h index caad24e5257..e9b8bc25548 100644 --- a/storage/perfschema/unittest/stub_print_error.h +++ b/storage/perfschema/unittest/stub_print_error.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,6 +33,23 @@ void pfs_free(void *ptr) free(ptr); } +void *pfs_malloc_array(size_t n, size_t size, myf flags) +{ + size_t array_size= n * size; + /* Check for overflow before allocating. */ + if (is_overflow(array_size, n, size)) + return NULL; + return pfs_malloc(array_size, flags); +} + +bool is_overflow(size_t product, size_t n1, size_t n2) +{ + if (n1 != 0 && (product / n1 != n2)) + return true; + else + return false; +} + void pfs_print_error(const char *format, ...) { /* Do not pollute the unit test output with annoying messages. */ |