Sorry, what I wrote was (again) wrong. The main point is wanted to convey is that `0x7ffffffff0de7fff` is not a random value. It is the result of calling `mozWritePoison()`. This is a crucial hint that we can use for solving this crash. When we free most objects, we will use `e5` repeatedly to poison them. This is what [`arena_dalloc()`'s `MaybePoison()`](https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#3767) does. This is how the object behind `mView.mRawPtr` gets poisoned after it gets freed. Hence the problem is not with that object (contrary to what I wrote before). In a few locations, we do a similar kind of poisoning, except we do it with pattern `0x7ffffffff0de7fff` and not `e5`. In particular, `0x7ffffffff0de7fff` is used to poison `nsTreeBodyFrame` objects after they are destroyed. This goes through the following path: - [`nsTreeBodyFrame::DestroyFrom()` calls `SimpleXULLeafFrame::DestroyFrom()`](https://searchfox.org/mozilla-central/source/layout/xul/tree/nsTreeBodyFrame.cpp#330) (the `nsTreeBodyFrame*` is `this`); - `SimpleXULLeafFrame::DestroyFrom()` is actually `nsIFrame::DestroyFrom()` (the `nsTreeBodyFrame*` is `this`); - [`nsIFrame::DestroyFrom()` calls `mozilla::PresShell::FreeFrame()`](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.cpp#926) (the `nsTreeBodyFrame*` is `aPtr`); - this [ends up calling `mozWritePoison()`](https://searchfox.org/mozilla-central/source/layout/base/nsPresArena.cpp#112) on the `nsTreeBodyFrame` object. So, with high confidence this time, what we see in these crashes is that the layout of our `nsTreeBodyFrame` object has already been poisoned after it was freed through `nsTreeBodyFrame::DestroyFrom()`. Yet, we are now handling a blur event, that ends up calling `nsTreeBodyFrame::SetFocused()` on that same freed (and poisoned) `nsTreeBodyFrame` object. So, when we try to access its `mView.mRawPtr`, the value we get back is `(nsITreeView*)0x7ffffffff0de7fff`. When we try to use that pointer, we crash. I think [this is the JavaScript handler definition](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/tree.js#850-859) that ends up calling into `nsTreeBodyFrame::SetFocused()`: ```JavaScript this.addEventListener( "blur", event => { this.focused = false; if (event.target == this.inputField) { this.stopEditing(true); } }, true ); ``` This calls into [`XULTreeElement::SetFocused()`](https://searchfox.org/mozilla-central/source/dom/xul/XULTreeElement.cpp#157-162), which calls `nsTreeBodyFrame::SetFocused()` on the `nsTreeBodyFrame*` returned by `XULTreeElement::GetTreeBodyFrame()`. ``` void XULTreeElement::SetFocused(bool aFocused) { nsTreeBodyFrame* body = GetTreeBodyFrame(); if (body) { body->SetFocused(aFocused); } } ``` There, `XULTreeElement::GetTreeBodyFrame` will most likely return the cached pointer value stored in the `mTreeBodyFrame` field of the `XULTreeElement`. But this field is a raw pointer and I don't see any ref counting occur when the pointer is cached. I think that the `nsFocusManager` could be properly retaining the `XULTreeElement`, but that then the `XULTreeElement` would fails to guarantee that the pointer in `mTreeBodyFrame` lives for at least as long as the `XULTreeElement` itself, which would then result in this crash.
Bug 1809492 Comment 25 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
Sorry, what I wrote was (again) wrong. The main point is wanted to convey is that `0x7ffffffff0de7fff` is not a random value. It is the result of calling `mozWritePoison()`. This is a crucial hint that we should try to use for solving this crash. When we free most objects, we will use `e5` repeatedly to poison them. This is what [`arena_dalloc()`'s `MaybePoison()`](https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#3767) does. This is how the object behind `mView.mRawPtr` gets poisoned after it gets freed. Hence the problem is not with that object (contrary to what I wrote before). In a few locations, we do a similar kind of poisoning, except we do it with pattern `0x7ffffffff0de7fff` and not `e5`. In particular, `0x7ffffffff0de7fff` is used to poison `nsTreeBodyFrame` objects after they are destroyed. This goes through the following path: - [`nsTreeBodyFrame::DestroyFrom()` calls `SimpleXULLeafFrame::DestroyFrom()`](https://searchfox.org/mozilla-central/source/layout/xul/tree/nsTreeBodyFrame.cpp#330) (the `nsTreeBodyFrame*` is `this`); - `SimpleXULLeafFrame::DestroyFrom()` is actually `nsIFrame::DestroyFrom()` (the `nsTreeBodyFrame*` is `this`); - [`nsIFrame::DestroyFrom()` calls `mozilla::PresShell::FreeFrame()`](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.cpp#926) (the `nsTreeBodyFrame*` is `aPtr`); - this [ends up calling `mozWritePoison()`](https://searchfox.org/mozilla-central/source/layout/base/nsPresArena.cpp#112) on the `nsTreeBodyFrame` object. So, with high confidence this time, what we see in these crashes is that the layout of our `nsTreeBodyFrame` object has already been poisoned after it was freed through `nsTreeBodyFrame::DestroyFrom()`. Yet, we are now handling a blur event, that ends up calling `nsTreeBodyFrame::SetFocused()` on that same freed (and poisoned) `nsTreeBodyFrame` object. So, when we try to access its `mView.mRawPtr`, the value we get back is `(nsITreeView*)0x7ffffffff0de7fff`. When we try to use that pointer, we crash. I think [this is the JavaScript handler definition](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/tree.js#850-859) that ends up calling into `nsTreeBodyFrame::SetFocused()`: ```JavaScript this.addEventListener( "blur", event => { this.focused = false; if (event.target == this.inputField) { this.stopEditing(true); } }, true ); ``` This calls into [`XULTreeElement::SetFocused()`](https://searchfox.org/mozilla-central/source/dom/xul/XULTreeElement.cpp#157-162), which calls `nsTreeBodyFrame::SetFocused()` on the `nsTreeBodyFrame*` returned by `XULTreeElement::GetTreeBodyFrame()`. ``` void XULTreeElement::SetFocused(bool aFocused) { nsTreeBodyFrame* body = GetTreeBodyFrame(); if (body) { body->SetFocused(aFocused); } } ``` There, `XULTreeElement::GetTreeBodyFrame` will most likely return the cached pointer value stored in the `mTreeBodyFrame` field of the `XULTreeElement`. But this field is a raw pointer and I don't see any ref counting occur when the pointer is cached. I think that the `nsFocusManager` could be properly retaining the `XULTreeElement`, but that then the `XULTreeElement` would fails to guarantee that the pointer in `mTreeBodyFrame` lives for at least as long as the `XULTreeElement` itself, which would then result in this crash.
Sorry, what I wrote was (again) wrong. The main point is wanted to convey is that `0x7ffffffff0de7fff` is not a random value. It is the result of calling `mozWritePoison()`. This is a crucial hint that we should try to use for solving this crash. When we free most objects, we will use `e5` repeatedly to poison them. This is what [`arena_dalloc()`'s `MaybePoison()`](https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#3767) does. This is how the object behind `mView.mRawPtr` gets poisoned after it gets freed. Hence the problem is not with that object (contrary to what I wrote before). In a few locations, we do a similar kind of poisoning, except we do it with pattern `0x7ffffffff0de7fff` and not `e5`. In particular, `0x7ffffffff0de7fff` is used to poison `nsTreeBodyFrame` objects after they are destroyed. This goes through the following path: - [`nsTreeBodyFrame::DestroyFrom()` calls `SimpleXULLeafFrame::DestroyFrom()`](https://searchfox.org/mozilla-central/source/layout/xul/tree/nsTreeBodyFrame.cpp#330) (the `nsTreeBodyFrame*` is `this`); - `SimpleXULLeafFrame::DestroyFrom()` is actually `nsIFrame::DestroyFrom()` (the `nsTreeBodyFrame*` is `this`); - [`nsIFrame::DestroyFrom()` calls `mozilla::PresShell::FreeFrame()`](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.cpp#926) (the `nsTreeBodyFrame*` is `aPtr`); - this [ends up calling `mozWritePoison()`](https://searchfox.org/mozilla-central/source/layout/base/nsPresArena.cpp#112) on the `nsTreeBodyFrame` object. So, with high confidence this time, what we see in these crashes is that the layout of our `nsTreeBodyFrame` object has already been poisoned after it was freed through `nsTreeBodyFrame::DestroyFrom()`. Yet, we are now handling a blur event, that ends up calling `nsTreeBodyFrame::SetFocused()` on that same freed (and poisoned) `nsTreeBodyFrame` object. So, when we try to access its `mView.mRawPtr`, the value we get back is `(nsITreeView*)0x7ffffffff0de7fff`. When we try to use that pointer, we crash. I think [this is the JavaScript handler definition](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/tree.js#850-859) that ends up calling into `nsTreeBodyFrame::SetFocused()`: ```JavaScript this.addEventListener( "blur", event => { this.focused = false; if (event.target == this.inputField) { this.stopEditing(true); } }, true ); ``` This calls into [`XULTreeElement::SetFocused()`](https://searchfox.org/mozilla-central/source/dom/xul/XULTreeElement.cpp#157-162), which calls `nsTreeBodyFrame::SetFocused()` on the `nsTreeBodyFrame*` returned by `XULTreeElement::GetTreeBodyFrame()`. ``` void XULTreeElement::SetFocused(bool aFocused) { nsTreeBodyFrame* body = GetTreeBodyFrame(); if (body) { body->SetFocused(aFocused); } } ``` There, `XULTreeElement::GetTreeBodyFrame` will most likely return the cached pointer value stored in the `mTreeBodyFrame` field of the `XULTreeElement`. But this field is a raw pointer and I don't see any ref counting occur when the pointer is cached. I think that the `nsFocusManager` could be properly retaining the `XULTreeElement`, but that then the `XULTreeElement` would fail to guarantee that the pointer in `mTreeBodyFrame` lives for at least as long as the `XULTreeElement` itself, which would then result in this crash.
Sorry, what I wrote was (again) wrong. The main point is wanted to convey is that `0x7ffffffff0de7fff` is not a random value. It is the result of calling `mozWritePoison()`. This is a crucial hint that we should try to use for solving this crash. When we free most objects, we will use `e5` repeatedly to poison them. This is what [`arena_dalloc()`'s `MaybePoison()`](https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#3767) does. This is how the object behind `mView.mRawPtr` gets poisoned after it gets freed. Hence the problem is not with that object (contrary to what I wrote before). In a few locations, we do a similar kind of poisoning, except we do it with pattern `0x7ffffffff0de7fff` and not `e5`. In particular, `0x7ffffffff0de7fff` is used to poison `nsTreeBodyFrame` objects after they are destroyed. This goes through the following path: - [`nsTreeBodyFrame::DestroyFrom()` calls `SimpleXULLeafFrame::DestroyFrom()`](https://searchfox.org/mozilla-central/source/layout/xul/tree/nsTreeBodyFrame.cpp#330) (the `nsTreeBodyFrame*` is `this`); - `SimpleXULLeafFrame::DestroyFrom()` is actually `nsIFrame::DestroyFrom()` (the `nsTreeBodyFrame*` is `this`); - [`nsIFrame::DestroyFrom()` calls `mozilla::PresShell::FreeFrame()`](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.cpp#926) (the `nsTreeBodyFrame*` is `aPtr`); - this [ends up calling `mozWritePoison()`](https://searchfox.org/mozilla-central/source/layout/base/nsPresArena.cpp#112) on the `nsTreeBodyFrame` object. So, with high confidence this time, what we see in these crashes is that the layout of our `nsTreeBodyFrame` object has already been poisoned after it was freed through `nsTreeBodyFrame::DestroyFrom()`. Yet, we are now handling a blur event, that ends up calling `nsTreeBodyFrame::SetFocused()` on that same freed (and poisoned) `nsTreeBodyFrame` object. So, when we try to access its `mView.mRawPtr`, the value we get back is `(nsITreeView*)0x7ffffffff0de7fff`. When we try to use that pointer, we crash. I think [this is the JavaScript handler definition](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/tree.js#850-859) that ends up calling into `nsTreeBodyFrame::SetFocused()`: ```JavaScript this.addEventListener( "blur", event => { this.focused = false; if (event.target == this.inputField) { this.stopEditing(true); } }, true ); ``` This calls into [`XULTreeElement::SetFocused()`](https://searchfox.org/mozilla-central/source/dom/xul/XULTreeElement.cpp#157-162), which calls `nsTreeBodyFrame::SetFocused()` on the `nsTreeBodyFrame*` returned by `XULTreeElement::GetTreeBodyFrame()`. ``` void XULTreeElement::SetFocused(bool aFocused) { nsTreeBodyFrame* body = GetTreeBodyFrame(); if (body) { body->SetFocused(aFocused); } } ``` There, `XULTreeElement::GetTreeBodyFrame` will most likely return the cached pointer value stored in the `mTreeBody` field of the `XULTreeElement`. But this field is a raw pointer and I don't see any ref counting occur when the pointer is cached. I think that the `nsFocusManager` could be properly retaining the `XULTreeElement`, but that then the `XULTreeElement` would fail to guarantee that the pointer in `mTreeBody` lives for at least as long as the `XULTreeElement` itself, which would then result in this crash.
Sorry, what I wrote was (again) wrong. The main point is wanted to convey is that `0x7ffffffff0de7fff` is not a random value. It is the result of calling `mozWritePoison()`. This is a crucial hint that we should try to use for solving this crash. When we free most objects, we will use `e5` repeatedly to poison them. This is what [`arena_dalloc()`'s `MaybePoison()`](https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#3767) does. This is how the object behind `mView.mRawPtr` gets poisoned after it gets freed. Hence the problem is not with that object (contrary to what I wrote before). In a few locations, we do a similar kind of poisoning, except we do it with pattern `0x7ffffffff0de7fff` and not `e5`. In particular, `0x7ffffffff0de7fff` is used to poison `nsTreeBodyFrame` objects after they are destroyed. This goes through the following path: - [`nsTreeBodyFrame::DestroyFrom()` calls `SimpleXULLeafFrame::DestroyFrom()`](https://searchfox.org/mozilla-central/source/layout/xul/tree/nsTreeBodyFrame.cpp#330) (the `nsTreeBodyFrame*` is `this`); - `SimpleXULLeafFrame::DestroyFrom()` is actually `nsIFrame::DestroyFrom()` (the `nsTreeBodyFrame*` is `this`); - [`nsIFrame::DestroyFrom()` calls `mozilla::PresShell::FreeFrame()`](https://searchfox.org/mozilla-central/source/layout/generic/nsIFrame.cpp#926) (the `nsTreeBodyFrame*` is `aPtr`); - this [ends up calling `mozWritePoison()`](https://searchfox.org/mozilla-central/source/layout/base/nsPresArena.cpp#112) on the `nsTreeBodyFrame` object. So, with high confidence this time, what we see in these crashes is that the layout of our `nsTreeBodyFrame` object has already been poisoned after it was freed through `nsTreeBodyFrame::DestroyFrom()`. Yet, we are now handling a blur event, that ends up calling `nsTreeBodyFrame::SetFocused()` on that same freed (and poisoned) `nsTreeBodyFrame` object. So, when we try to access its `mView.mRawPtr`, the value we get back is `(nsITreeView*)0x7ffffffff0de7fff`. When we try to use that pointer, we crash. I think [this is the JavaScript handler definition](https://searchfox.org/mozilla-central/source/toolkit/content/widgets/tree.js#850-859) that ends up calling into `nsTreeBodyFrame::SetFocused()`: ```JavaScript this.addEventListener( "blur", event => { this.focused = false; if (event.target == this.inputField) { this.stopEditing(true); } }, true ); ``` This calls into [`XULTreeElement::SetFocused()`](https://searchfox.org/mozilla-central/source/dom/xul/XULTreeElement.cpp#157-162), which calls `nsTreeBodyFrame::SetFocused()` on the `nsTreeBodyFrame*` returned by `XULTreeElement::GetTreeBodyFrame()`. ``` void XULTreeElement::SetFocused(bool aFocused) { nsTreeBodyFrame* body = GetTreeBodyFrame(); if (body) { body->SetFocused(aFocused); } } ``` There, `XULTreeElement::GetTreeBodyFrame()` will most often return the cached pointer value stored in the `mTreeBody` field of the `XULTreeElement`. But this field is a raw pointer and I don't see any ref counting occur when the pointer is cached. I think that the `nsFocusManager` could be properly retaining the `XULTreeElement`, but that then the `XULTreeElement` would fail to guarantee that the pointer in `mTreeBody` lives for at least as long as the `XULTreeElement` itself, which would then result in this crash.