A bit more about what's happening here: - We call ReflowSVGNonDisplayText for the SVG Text frame with id #a. - This invalidates its rendering observers (a collection of SVGTextPathObserver objects), pulling them into a local variable like so in [`SVGRenderingObserverSet::InvalidateAll`](https://searchfox.org/mozilla-central/rev/080e18fa4748456003164f58b0d925b8c3826a67/layout/svg/SVGObserverUtils.cpp#1058,1063-1067): ```c++ const auto observers = std::move(mObservers); for (const auto& observer : observers) { observer->OnNonDOMMutationRenderingChange(); } ``` - Its first rendering observer is the next SVG text frame. As part of invalidating there, we call ReflowSVGNonDisplayText() on that next text frame. - That next text frame has two lines in its anonymous block. During this reflow, it deletes a no-longer-needed next-continuation for its textPath's inline-frame (deleting the part that was in the second line). - While deleting this frame, we of course have to delete all of its frame-properties, including its SVGTextPathObserver. **This is bad since we are currently iterating over `observers` (many stack levels up) which includes a pointer to this object, which it hasn't yet reached in its iteration.** - In the SVGTextPathObserver destructor, SVGTextPathObserver attempts to unregister from the observation target (for safety, so that it doesn't get a callback after it's been deleted). But this fails because the observation target doesn't have the observer in its `mObservers` collection anymore -- it has moved to the local `observers` variable, which we don't have access to modify. - Later on, the above-quoted ` observer : observers` presumably reaches the now-deleted SVGTextPathObserver, and triggers a use-after-free and we crash.
Bug 1736243 Comment 16 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
A bit more about what's happening here: - We call ReflowSVGNonDisplayText for the SVG Text frame with id `a`. - This invalidates its rendering observers (a collection of `SVGTextPathObserver` objects), pulling them into a local variable like so in [`SVGRenderingObserverSet::InvalidateAll`](https://searchfox.org/mozilla-central/rev/080e18fa4748456003164f58b0d925b8c3826a67/layout/svg/SVGObserverUtils.cpp#1058,1063-1067): ```c++ const auto observers = std::move(mObservers); for (const auto& observer : observers) { observer->OnNonDOMMutationRenderingChange(); } ``` - Its first rendering observer is the next SVG text frame. As part of invalidating there, we call ReflowSVGNonDisplayText() on that next text frame. - That next text frame has two lines in its anonymous block. During this reflow, it deletes a no-longer-needed next-continuation for its textPath's inline-frame (deleting the part that was in the second line). - While deleting this frame, we of course have to delete all of its frame-properties, including its SVGTextPathObserver. **This is bad since we are currently iterating over `observers` (many stack levels up) which includes a pointer to this object, which it hasn't yet reached in its iteration.** - In the SVGTextPathObserver destructor, SVGTextPathObserver attempts to unregister from the observation target (for safety, so that it doesn't get a callback after it's been deleted). But this fails because the observation target doesn't have the observer in its `mObservers` collection anymore -- it has moved to the local `observers` variable, which we don't have access to modify. - Later on, the above-quoted `for (const auto& observer : observers) {` loop presumably reaches the now-deleted `SVGTextPathObserver` (which still has a straggling pointer in the `observers` collection). We use that pointer and trigger a use-after-free when using it, and we crash.
A bit more about what's happening here: - We call ReflowSVGNonDisplayText for the SVG Text frame with id `a`. - This invalidates its rendering observers (a collection of `SVGTextPathObserver` objects), pulling them into a local variable like so in [`SVGRenderingObserverSet::InvalidateAll`](https://searchfox.org/mozilla-central/rev/080e18fa4748456003164f58b0d925b8c3826a67/layout/svg/SVGObserverUtils.cpp#1058,1063-1067): ```c++ const auto observers = std::move(mObservers); for (const auto& observer : observers) { observer->OnNonDOMMutationRenderingChange(); } ``` - Its first rendering observer is the next SVG text frame. As part of invalidating there, we call ReflowSVGNonDisplayText() on that next text frame. - That next text frame has two lines in its anonymous block. During this reflow, it deletes a no-longer-needed next-continuation for its textPath's inline-frame (deleting the part that was in the second line). - While deleting this frame, we of course have to delete all of its frame-properties, including its SVGTextPathObserver. **This is bad since we are currently iterating over `observers` (many stack levels up) which includes a pointer to this object, which it hasn't yet reached in its iteration.** - In the SVGTextPathObserver destructor, SVGTextPathObserver attempts to unregister from the observation target (for safety, so that it doesn't get a callback after it's been deleted). But this fails because the observation target doesn't have the observer in its `mObservers` collection anymore -- it has moved to the local `observers` variable, which we don't have access to modify. - Later on, the above-quoted `for (const auto& observer : observers) {` loop presumably reaches the now-deleted `SVGTextPathObserver` (which still has a straggling pointer that was left behind in the `observers` collection). We use that pointer and trigger a use-after-free when using it, and we crash.