Commit 6b2b5108 authored by Marko Mäkelä's avatar Marko Mäkelä

PFS_events_statements cleanup: Use offsetof

The macro my_offsetof() performs pointer arithmetics that may be
undefined behavior. As reported in MDEV-26272, it may cause
clang -fsanitize=undefined to generate invalid memory references.

struct PFS_events_statements: Convert to std::is_standard_layout
by encapsulating the standard-layout struct PFS_events instead of
deriving from it, so that the standard macro offsetof() can be used.

PFS_events_statements::copy(): Renamed from copy_events_statements().
A cast to void* is now needed in memcpy() to avoid GCC -Wclass-memaccess
"writing to an object ... leaves 64 bytes unchanged".
parent 8d398710
......@@ -4841,8 +4841,8 @@ pfs_start_stage_v1(PSI_stage_key key, const char *src_file, int src_line)
pfs->m_class= NULL;
/* New waits will now be attached directly to the parent statement. */
child_wait->m_event_id= parent_statement->m_event_id;
child_wait->m_event_type= parent_statement->m_event_type;
child_wait->m_event_id= parent_statement->m_event.m_event_id;
child_wait->m_event_type= parent_statement->m_event.m_event_type;
/* See below for new stages, that may overwrite this. */
}
......@@ -4957,8 +4957,8 @@ void pfs_end_stage_v1()
/* New waits will now be attached directly to the parent statement. */
PFS_events_waits *child_wait= & pfs_thread->m_events_waits_stack[0];
PFS_events_statements *parent_statement= & pfs_thread->m_statement_stack[0];
child_wait->m_event_id= parent_statement->m_event_id;
child_wait->m_event_type= parent_statement->m_event_type;
child_wait->m_event_id= parent_statement->m_event.m_event_id;
child_wait->m_event_type= parent_statement->m_event.m_event_type;
/* This stage is completed */
pfs->m_class= NULL;
......@@ -5009,13 +5009,13 @@ pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state,
pfs_dirty_state dirty_state;
pfs_thread->m_stmt_lock.allocated_to_dirty(& dirty_state);
PFS_events_statements *pfs= & pfs_thread->m_statement_stack[pfs_thread->m_events_statements_count];
pfs->m_thread_internal_id= pfs_thread->m_thread_internal_id;
pfs->m_event_id= event_id;
pfs->m_event_type= EVENT_TYPE_STATEMENT;
pfs->m_end_event_id= 0;
pfs->m_class= klass;
pfs->m_timer_start= 0;
pfs->m_timer_end= 0;
pfs->m_event.m_thread_internal_id= pfs_thread->m_thread_internal_id;
pfs->m_event.m_event_id= event_id;
pfs->m_event.m_event_type= EVENT_TYPE_STATEMENT;
pfs->m_event.m_end_event_id= 0;
pfs->m_event.m_class= klass;
pfs->m_event.m_timer_start= 0;
pfs->m_event.m_timer_end= 0;
pfs->m_lock_time= 0;
pfs->m_current_schema_name_length= 0;
pfs->m_sqltext_length= 0;
......@@ -5065,9 +5065,9 @@ pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state,
if (pfs_thread->m_events_statements_count > 0)
{
parent_statement= pfs - 1;
parent_event= parent_statement->m_event_id;
parent_type= parent_statement->m_event_type;
parent_level= parent_statement->m_nesting_event_level + 1;
parent_event= parent_statement->m_event.m_event_id;
parent_type= parent_statement->m_event.m_event_type;
parent_level= parent_statement->m_event.m_nesting_event_level + 1;
}
if (parent_transaction->m_state == TRANS_STATE_ACTIVE &&
......@@ -5077,9 +5077,9 @@ pfs_get_thread_statement_locker_v1(PSI_statement_locker_state *state,
parent_type= parent_transaction->m_event_type;
}
pfs->m_nesting_event_id= parent_event;
pfs->m_nesting_event_type= parent_type;
pfs->m_nesting_event_level= parent_level;
pfs->m_event.m_nesting_event_id= parent_event;
pfs->m_event.m_nesting_event_type= parent_type;
pfs->m_event.m_nesting_event_level= parent_level;
/* Set parent Stored Procedure information for this statement. */
if(sp_share)
......@@ -5197,7 +5197,7 @@ pfs_refine_statement_v1(PSI_statement_locker *locker,
DBUG_ASSERT(pfs != NULL);
/* mutate EVENTS_STATEMENTS_CURRENT.EVENT_NAME */
pfs->m_class= klass;
pfs->m_event.m_class= klass;
}
state->m_class= klass;
......@@ -5233,9 +5233,9 @@ void pfs_start_statement_v1(PSI_statement_locker *locker,
PFS_events_statements *pfs= reinterpret_cast<PFS_events_statements*> (state->m_statement);
DBUG_ASSERT(pfs != NULL);
pfs->m_timer_start= timer_start;
pfs->m_source_file= src_file;
pfs->m_source_line= src_line;
pfs->m_event.m_timer_start= timer_start;
pfs->m_event.m_source_file= src_file;
pfs->m_event.m_source_line= src_line;
DBUG_ASSERT(db_len <= sizeof(pfs->m_current_schema_name));
if (db_len > 0)
......@@ -5492,8 +5492,8 @@ void pfs_end_statement_v1(PSI_statement_locker *locker, void *stmt_da)
break;
}
pfs->m_timer_end= timer_end;
pfs->m_end_event_id= thread->m_event_id;
pfs->m_event.m_timer_end= timer_end;
pfs->m_event.m_end_event_id= thread->m_event_id;
if (digest_storage != NULL)
{
......@@ -5970,8 +5970,8 @@ pfs_get_thread_transaction_locker_v1(PSI_transaction_locker_state *state,
{
PFS_events_statements *pfs_statement=
&pfs_thread->m_statement_stack[statements_count - 1];
pfs->m_nesting_event_id= pfs_statement->m_event_id;
pfs->m_nesting_event_type= pfs_statement->m_event_type;
pfs->m_nesting_event_id= pfs_statement->m_event.m_event_id;
pfs->m_nesting_event_type= pfs_statement->m_event.m_event_type;
}
else
{
......
......@@ -147,27 +147,26 @@ void cleanup_events_statements_history_long(void)
h_long_stmts_text_array= NULL;
}
static inline void copy_events_statements(PFS_events_statements *dest,
const PFS_events_statements *source)
inline void PFS_events_statements::copy(const PFS_events_statements &source)
{
/* Copy all attributes except SQL TEXT and DIGEST */
memcpy(dest, source, my_offsetof(PFS_events_statements, m_sqltext));
memcpy((void*) this, &source, offsetof(PFS_events_statements, m_sqltext));
/* Copy SQL TEXT */
int sqltext_length= source->m_sqltext_length;
int sqltext_length= source.m_sqltext_length;
if (sqltext_length > 0)
{
memcpy(dest->m_sqltext, source->m_sqltext, sqltext_length);
dest->m_sqltext_length= sqltext_length;
memcpy(m_sqltext, source.m_sqltext, sqltext_length);
m_sqltext_length= sqltext_length;
}
else
{
dest->m_sqltext_length= 0;
m_sqltext_length= 0;
}
/* Copy DIGEST */
dest->m_digest_storage.copy(& source->m_digest_storage);
m_digest_storage.copy(&source.m_digest_storage);
}
/**
......@@ -192,7 +191,7 @@ void insert_events_statements_history(PFS_thread *thread, PFS_events_statements
to make this thread (the writer) faster.
This is ok, the readers of m_statements_history will filter this out.
*/
copy_events_statements(&thread->m_statements_history[index], statement);
thread->m_statements_history[index].copy(*statement);
index++;
if (index >= events_statements_history_per_thread)
......@@ -221,7 +220,7 @@ void insert_events_statements_history_long(PFS_events_statements *statement)
events_statements_history_long_full= true;
/* See related comment in insert_events_statements_history. */
copy_events_statements(&events_statements_history_long_array[index], statement);
events_statements_history_long_array[index].copy(*statement);
}
static void fct_reset_events_statements_current(PFS_thread *pfs_thread)
......@@ -230,7 +229,7 @@ static void fct_reset_events_statements_current(PFS_thread *pfs_thread)
PFS_events_statements *pfs_stmt_last= pfs_stmt + statement_stack_max;
for ( ; pfs_stmt < pfs_stmt_last; pfs_stmt++)
pfs_stmt->m_class= NULL;
pfs_stmt->m_event.m_class= nullptr;
}
/** Reset table EVENTS_STATEMENTS_CURRENT data. */
......@@ -247,7 +246,7 @@ static void fct_reset_events_statements_history(PFS_thread *pfs_thread)
pfs_thread->m_statements_history_index= 0;
pfs_thread->m_statements_history_full= false;
for ( ; pfs < pfs_last; pfs++)
pfs->m_class= NULL;
pfs->m_event.m_class= nullptr;
}
/** Reset table EVENTS_STATEMENTS_HISTORY data. */
......@@ -265,7 +264,7 @@ void reset_events_statements_history_long(void)
PFS_events_statements *pfs= events_statements_history_long_array;
PFS_events_statements *pfs_last= pfs + events_statements_history_long_size;
for ( ; pfs < pfs_last; pfs++)
pfs->m_class= NULL;
pfs->m_event.m_class= nullptr;
}
static void fct_reset_events_statements_by_thread(PFS_thread *thread)
......
......@@ -38,8 +38,9 @@ struct PFS_user;
struct PFS_host;
/** A statement record. */
struct PFS_events_statements : public PFS_events
struct PFS_events_statements
{
PFS_events m_event;
enum_object_type m_sp_type;
char m_schema_name[NAME_LEN];
uint m_schema_name_length;
......@@ -117,6 +118,8 @@ struct PFS_events_statements : public PFS_events
and always point to pre allocated memory.
*/
sql_digest_storage m_digest_storage;
inline void copy(const PFS_events_statements &source);
};
void insert_events_statements_history(PFS_thread *thread, PFS_events_statements *statement);
......
......@@ -126,9 +126,9 @@ create_prepared_stmt(void *identity,
if (pfs_stmt)
{
if (pfs_program)
pfs->m_owner_event_id= pfs_stmt->m_nesting_event_id;
pfs->m_owner_event_id= pfs_stmt->m_event.m_nesting_event_id;
else
pfs->m_owner_event_id= pfs_stmt->m_event_id;
pfs->m_owner_event_id= pfs_stmt->m_event.m_event_id;
}
/* Insert this record. */
......
......@@ -228,17 +228,18 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
m_row_exists= false;
PFS_statement_class *unsafe= (PFS_statement_class*) statement->m_class;
PFS_statement_class *unsafe= (PFS_statement_class*)
statement->m_event.m_class;
PFS_statement_class *klass= sanitize_statement_class(unsafe);
if (unlikely(klass == NULL))
return;
m_row.m_thread_internal_id= statement->m_thread_internal_id;
m_row.m_event_id= statement->m_event_id;
m_row.m_end_event_id= statement->m_end_event_id;
m_row.m_nesting_event_id= statement->m_nesting_event_id;
m_row.m_nesting_event_type= statement->m_nesting_event_type;
m_row.m_nesting_event_level= statement->m_nesting_event_level;
m_row.m_thread_internal_id= statement->m_event.m_thread_internal_id;
m_row.m_event_id= statement->m_event.m_event_id;
m_row.m_end_event_id= statement->m_event.m_end_event_id;
m_row.m_nesting_event_id= statement->m_event.m_nesting_event_id;
m_row.m_nesting_event_type= statement->m_event.m_nesting_event_type;
m_row.m_nesting_event_level= statement->m_event.m_nesting_event_level;
if (m_row.m_end_event_id == 0)
{
......@@ -246,10 +247,10 @@ void table_events_statements_common::make_row_part_1(PFS_events_statements *stat
}
else
{
timer_end= statement->m_timer_end;
timer_end= statement->m_event.m_timer_end;
}
m_normalizer->to_pico(statement->m_timer_start, timer_end,
m_normalizer->to_pico(statement->m_event.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;
......@@ -662,7 +663,7 @@ int table_events_statements_current::rnd_pos(const void *pos)
statement= &pfs_thread->m_statement_stack[m_pos.m_index_2];
if (statement->m_class != NULL)
if (statement->m_event.m_class)
{
make_row(pfs_thread, statement);
return 0;
......@@ -762,7 +763,7 @@ int table_events_statements_history::rnd_next(void)
statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
if (statement->m_class != NULL)
if (statement->m_event.m_class)
{
make_row(pfs_thread, statement);
/* Next iteration, look for the next history in this thread */
......@@ -793,7 +794,7 @@ int table_events_statements_history::rnd_pos(const void *pos)
return HA_ERR_RECORD_DELETED;
statement= &pfs_thread->m_statements_history[m_pos.m_index_2];
if (statement->m_class != NULL)
if (statement->m_event.m_class)
{
make_row(pfs_thread, statement);
return 0;
......@@ -876,7 +877,7 @@ int table_events_statements_history_long::rnd_next(void)
{
statement= &events_statements_history_long_array[m_pos.m_index];
if (statement->m_class != NULL)
if (statement->m_event.m_class)
{
make_row(statement);
/* Next iteration, look for the next entry */
......@@ -908,7 +909,7 @@ int table_events_statements_history_long::rnd_pos(const void *pos)
statement= &events_statements_history_long_array[m_pos.m_index];
if (statement->m_class == NULL)
if (!statement->m_event.m_class)
return HA_ERR_RECORD_DELETED;
make_row(statement);
......
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