Commit 103395c0 authored by Kevin Babbitt's avatar Kevin Babbitt Committed by Commit Bot

Presumed fix for crash in AXFragmentRootWin

The Microsoft Edge team has reports of a null dereference crash showing
up in automated usage testing. The symptom is that, while responding to
a UIA Navigate call, we check to see whether the navigated-from element
is the child of a fragment root. We come across an entry in the fragment
root map from the element's HWND to a null fragment root pointer,
dereference that null pointer, and crash.

It's not expected that we'll ever have such an entry - the map is
supposed to map HWNDs to non-null fragment roots. From the crash data
we have, the exact sequence of calls leading up to this scenario is
unclear, but I was able to reproduce one way it can occur and captured
it in a unit test. The fix for the issue is, when looking up an entry
in the map, use unordered_map::find() rather than operator[], the latter
of which will create an entry if one doesn't exist.

Bug: 1071185
Change-Id: I5f04188e849ffc0969762d870b80603d4b7e15b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2148850Reviewed-by: default avatarIan Prest <iapres@microsoft.com>
Commit-Queue: Kevin Babbitt <kbabbitt@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#759435}
parent f1a8b72b
...@@ -204,8 +204,12 @@ class AXFragmentRootMapWin { ...@@ -204,8 +204,12 @@ class AXFragmentRootMapWin {
void RemoveFragmentRoot(gfx::AcceleratedWidget widget) { map_.erase(widget); } void RemoveFragmentRoot(gfx::AcceleratedWidget widget) { map_.erase(widget); }
ui::AXFragmentRootWin* GetFragmentRoot(gfx::AcceleratedWidget widget) { ui::AXFragmentRootWin* GetFragmentRoot(gfx::AcceleratedWidget widget) const {
return map_[widget]; const auto& entry = map_.find(widget);
if (entry != map_.end())
return entry->second;
return nullptr;
} }
ui::AXFragmentRootWin* GetFragmentRootParentOf( ui::AXFragmentRootWin* GetFragmentRootParentOf(
......
...@@ -430,4 +430,34 @@ TEST_F(AXFragmentRootTest, TestUIAMultipleFragmentRoots) { ...@@ -430,4 +430,34 @@ TEST_F(AXFragmentRootTest, TestUIAMultipleFragmentRoots) {
test_fragment.Get()); test_fragment.Get());
} }
TEST_F(AXFragmentRootTest, TestFragmentRootMap) {
AXNodeData root;
Init(root);
// There should be nothing in the map before we create a fragment root.
// Call GetForAcceleratedWidget() first to ensure that querying for a
// fragment root doesn't inadvertently create an empty entry in the map
// (https://crbug.com/1071185).
EXPECT_EQ(nullptr, AXFragmentRootWin::GetForAcceleratedWidget(
gfx::kMockAcceleratedWidget));
EXPECT_EQ(nullptr, AXFragmentRootWin::GetFragmentRootParentOf(
GetRootIAccessible().Get()));
// After initializing a fragment root, we should be able to retrieve it using
// its accelerated widget, or as the parent of its child.
InitFragmentRoot();
EXPECT_EQ(ax_fragment_root_.get(), AXFragmentRootWin::GetForAcceleratedWidget(
gfx::kMockAcceleratedWidget));
EXPECT_EQ(ax_fragment_root_.get(), AXFragmentRootWin::GetFragmentRootParentOf(
GetRootIAccessible().Get()));
// After deleting a fragment root, it should no longer be reachable from the
// map.
ax_fragment_root_.reset();
EXPECT_EQ(nullptr, AXFragmentRootWin::GetForAcceleratedWidget(
gfx::kMockAcceleratedWidget));
EXPECT_EQ(nullptr, AXFragmentRootWin::GetFragmentRootParentOf(
GetRootIAccessible().Get()));
}
} // namespace ui } // namespace ui
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