// Adapter for CheckedObserver types so that they can use the same syntax as a // raw pointer when stored in the std::vector of observers in an ObserverList. // It wraps a WeakPtr<CheckedObserver> and allows a "null" pointer via // destruction to be distinguished from an observer marked for deferred removal // whilst an iteration is in progress. class BASE_EXPORT CheckedObserverAdapter {
public: explicit CheckedObserverAdapter(const CheckedObserver* observer);
// Move-only construction and assignment is required to store this in STL // types.
CheckedObserverAdapter(CheckedObserverAdapter&& other);
CheckedObserverAdapter& operator=(CheckedObserverAdapter&& other);
CheckedObserverAdapter(const CheckedObserverAdapter&) = delete;
CheckedObserverAdapter& operator=(const CheckedObserverAdapter&) = delete;
~CheckedObserverAdapter();
bool IsMarkedForRemoval() const { // If |weak_ptr_| was invalidated then this attempt to iterate over the // pointer is a UAF. Tip: If it's unclear where the `delete` occurred, try // adding CHECK(!IsInObserverList()) to the ~CheckedObserver() (destructor) // override. However, note that this is not always a bug: a destroyed // observer can exist in an ObserverList so long as nothing iterates over // the ObserverList before the list itself is destroyed.
CHECK(!weak_ptr_.WasInvalidated()); return weak_ptr_ == nullptr;
}
bool IsEqual(const CheckedObserver* rhs) const { // Note that inside an iteration, ObserverList::HasObserver() may call this // and |weak_ptr_| may be null due to a deferred removal, which is fine. return weak_ptr_.get() == rhs;
}
template <class ObserverType> static ObserverType* Get(const CheckedObserverAdapter& adapter) {
static_assert(
std::is_base_of_v<CheckedObserver, ObserverType>, "Observers should inherit from base::CheckedObserver. " "Use ObserverList<T>::Unchecked to observe with raw pointers.");
DCHECK(adapter.weak_ptr_); return static_cast<ObserverType*>(adapter.weak_ptr_.get());
}
// Wraps a pointer in a stack-allocated, base::LinkNode. The node is // automatically removed from the linked list upon destruction (of the node, not // the pointer). Nodes are detached from the list via Invalidate() in the // destructor of ObserverList. This invalidates all WeakLinkNodes. There is no // threading support. template <class ObserverList> class WeakLinkNode : public base::LinkNode<WeakLinkNode<ObserverList>> {
public:
WeakLinkNode() = default; explicit WeakLinkNode(ObserverList* list) { SetList(list); }
WeakLinkNode(const WeakLinkNode&) = delete;
WeakLinkNode& operator=(const WeakLinkNode&) = delete;
private: // `list_` is not a raw_ptr<...> for performance reasons: on-stack pointer + // based on analysis of sampling profiler data and tab_search:top100:2020.
RAW_PTR_EXCLUSION ObserverList* list_ = nullptr;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.