Commit e6a808be authored by Marko Mäkelä's avatar Marko Mäkelä

Fix heap-use-after-free in debug code

rw_lock_get_debug_info(): Remove. This function is inherently unsafe
to use, because the copied pointers can become stale between
rw_lock_debug_mutex_exit() and the dereferencing of the pointer in
the caller.
parent be370efa
......@@ -1047,86 +1047,52 @@ rw_lock_own(
return(FALSE);
}
/** For collecting the debug information for a thread's rw-lock */
typedef std::vector<rw_lock_debug_t*> Infos;
/** Get the thread debug info
@param[in] infos The rw-lock mode owned by the threads
@param[in] lock rw-lock to check
@return the thread debug info or NULL if not found */
void
rw_lock_get_debug_info(const rw_lock_t* lock, Infos* infos)
{
rw_lock_debug_t* info = NULL;
ut_ad(rw_lock_validate(lock));
rw_lock_debug_mutex_enter();
for (info = UT_LIST_GET_FIRST(lock->debug_list);
info != NULL;
info = UT_LIST_GET_NEXT(list, info)) {
if (os_thread_eq(info->thread_id, os_thread_get_curr_id())) {
infos->push_back(info);
}
}
rw_lock_debug_mutex_exit();
}
/** Checks if the thread has locked the rw-lock in the specified mode, with
the pass value == 0.
@param[in] lock rw-lock
@param[in] flags specify lock types with OR of the
rw_lock_flag_t values
@return true if locked */
bool
rw_lock_own_flagged(
const rw_lock_t* lock,
rw_lock_flags_t flags)
bool rw_lock_own_flagged(const rw_lock_t* lock, rw_lock_flags_t flags)
{
Infos infos;
rw_lock_get_debug_info(lock, &infos);
Infos::const_iterator end = infos.end();
for (Infos::const_iterator it = infos.begin(); it != end; ++it) {
ut_ad(rw_lock_validate(lock));
const rw_lock_debug_t* info = *it;
rw_lock_debug_mutex_enter();
if (info->pass) {
for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list);
info != NULL;
info = UT_LIST_GET_NEXT(list, info)) {
if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())
|| info->pass) {
continue;
}
ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
switch (info->lock_type) {
case RW_LOCK_S:
if (flags & RW_LOCK_FLAG_S) {
return(true);
if (!(flags & RW_LOCK_FLAG_S)) {
continue;
}
break;
case RW_LOCK_X:
if (flags & RW_LOCK_FLAG_X) {
return(true);
if (!(flags & RW_LOCK_FLAG_X)) {
continue;
}
break;
case RW_LOCK_SX:
if (flags & RW_LOCK_FLAG_SX) {
return(true);
if (!(flags & RW_LOCK_FLAG_SX)) {
continue;
}
break;
}
rw_lock_debug_mutex_exit();
return true;
}
return(false);
rw_lock_debug_mutex_exit();
return false;
}
/***************************************************************//**
......@@ -1227,28 +1193,31 @@ rw_lock_t::locked_from() const
the same thread can call X lock recursively. */
std::ostringstream msg;
Infos infos;
bool written = false;
rw_lock_get_debug_info(this, &infos);
ut_ad(rw_lock_validate(this));
ulint i = 0;
Infos::const_iterator end = infos.end();
for (Infos::const_iterator it = infos.begin(); it != end; ++it, ++i) {
const rw_lock_debug_t* info = *it;
rw_lock_debug_mutex_enter();
ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list);
info != NULL;
info = UT_LIST_GET_NEXT(list, info)) {
if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())) {
continue;
}
if (i > 0) {
if (written) {
msg << ", ";
}
written = true;
msg << info->file_name << ":" << info->line;
}
return(msg.str());
rw_lock_debug_mutex_exit();
return(msg.str());
}
/** Print the rw-lock information.
......
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