mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Bug#58003 Segfault on CHECKSUM TABLE performance_schema.EVENTS_WAITS_HISTORY_LONG EXTENDED
This fix is a follow up on the fix for similar issue 56761. When sanitizing data read from the events_waits_history_long table, the code needs also to sanitize the schema_name / object_name / file_name pointers, because such pointers could also hold invalid values. Checking the string length alone was required but not sufficient. This fix verifies that: - the table schema and table name used in table io events - the file name used in file io events are valid pointers before dereferencing these pointers.
This commit is contained in:
@@ -543,15 +543,9 @@ PFS_mutex_class *find_mutex_class(PFS_sync_key key)
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -566,7 +560,7 @@ PFS_rwlock_class *find_rwlock_class(PFS_sync_key key)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,7 +575,7 @@ PFS_cond_class *find_cond_class(PFS_sync_key key)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -636,7 +630,7 @@ PFS_thread_class *find_thread_class(PFS_sync_key key)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -687,7 +681,7 @@ PFS_file_class *find_file_class(PFS_file_key key)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -820,7 +814,59 @@ search:
|
||||
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user