mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 01:32:14 -05:00
AK: Switch RefCounted to atomic refcounting
This fixes all sorts of race conditions, primarily in the kernel, where till now it's been possible to obtain either double free or use-after-free by exploiting refcounting races.
This commit is contained in:
parent
583108004c
commit
c80e657dda
Notes:
sideshowbarker
2024-07-19 05:42:14 +09:00
Author: https://github.com/bugaevc Commit: https://github.com/SerenityOS/serenity/commit/c80e657dda3 Pull-request: https://github.com/SerenityOS/serenity/pull/2547
1 changed files with 11 additions and 9 deletions
|
@ -27,6 +27,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/Atomic.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
|
||||
|
@ -62,8 +63,8 @@ public:
|
|||
|
||||
ALWAYS_INLINE void ref() const
|
||||
{
|
||||
ASSERT(m_ref_count);
|
||||
++m_ref_count;
|
||||
auto old_ref_count = m_ref_count++;
|
||||
ASSERT(old_ref_count > 0);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE RefCountType ref_count() const
|
||||
|
@ -78,13 +79,14 @@ protected:
|
|||
ASSERT(m_ref_count == 0);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void deref_base() const
|
||||
ALWAYS_INLINE RefCountType deref_base() const
|
||||
{
|
||||
ASSERT(m_ref_count);
|
||||
--m_ref_count;
|
||||
auto old_ref_count = m_ref_count--;
|
||||
ASSERT(old_ref_count > 0);
|
||||
return old_ref_count - 1;
|
||||
}
|
||||
|
||||
mutable RefCountType m_ref_count { 1 };
|
||||
mutable Atomic<RefCountType> m_ref_count { 1 };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -92,11 +94,11 @@ class RefCounted : public RefCountedBase {
|
|||
public:
|
||||
void unref() const
|
||||
{
|
||||
deref_base();
|
||||
if (m_ref_count == 0) {
|
||||
auto new_ref_count = deref_base();
|
||||
if (new_ref_count == 0) {
|
||||
call_will_be_destroyed_if_present(static_cast<const T*>(this));
|
||||
delete static_cast<const T*>(this);
|
||||
} else if (m_ref_count == 1) {
|
||||
} else if (new_ref_count == 1) {
|
||||
call_one_ref_left_if_present(static_cast<const T*>(this));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue