backport_1065122.patch 4.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Cheng Zhao <[email protected]>
  3. Date: Thu, 4 Oct 2018 14:57:02 -0700
  4. Subject: fix: add some crash debugging checks
  5. [1065122] [High]: heap-use-after-free : ui::AXTreeSerializerblink::WebAXObject,content::AXContentNodeData,content::AXContentTreeData::LeastCommonAncestor
  6. Backport https://chromium.googlesource.com/chromium/src/+/e0a661af6c2c7346183c47b106afecb01adbfa2e
  7. diff --git a/ui/accessibility/ax_tree_serializer.h b/ui/accessibility/ax_tree_serializer.h
  8. index d0cd8be8dbf3c15ce2a2c84446f5042819686b9a..8791c58789cef10a31799d57287860ba8e60af94 100644
  9. --- a/ui/accessibility/ax_tree_serializer.h
  10. +++ b/ui/accessibility/ax_tree_serializer.h
  11. @@ -180,6 +180,8 @@ class AXTreeSerializer {
  12. // like when Reset() is called.
  13. void InternalReset();
  14. + ClientTreeNode* GetClientTreeNodeParent(ClientTreeNode* obj);
  15. +
  16. // The tree source.
  17. AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree_;
  18. @@ -269,7 +271,7 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::LeastCommonAncestor(
  19. std::vector<ClientTreeNode*> client_ancestors;
  20. while (client_node) {
  21. client_ancestors.push_back(client_node);
  22. - client_node = client_node->parent;
  23. + client_node = GetClientTreeNodeParent(client_node);
  24. }
  25. // Start at the root. Keep going until the source ancestor chain and
  26. @@ -304,9 +306,12 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::LeastCommonAncestor(
  27. // that we're inside of an invalid subtree that all needs to be
  28. // re-serialized, so the LCA should be higher.
  29. ClientTreeNode* client_node = ClientTreeNodeById(tree_->GetId(node));
  30. - while (
  31. - tree_->IsValid(node) &&
  32. - (!client_node || (client_node->parent && client_node->parent->invalid))) {
  33. + while (tree_->IsValid(node)) {
  34. + if (client_node) {
  35. + ClientTreeNode* parent = GetClientTreeNodeParent(client_node);
  36. + if (!parent || !parent->invalid)
  37. + break;
  38. + }
  39. node = tree_->GetParent(node);
  40. if (tree_->IsValid(node))
  41. client_node = ClientTreeNodeById(tree_->GetId(node));
  42. @@ -326,12 +331,13 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
  43. int child_id = tree_->GetId(child);
  44. ClientTreeNode* client_child = ClientTreeNodeById(child_id);
  45. if (client_child) {
  46. - if (!client_child->parent) {
  47. + ClientTreeNode* parent = client_child->parent;
  48. + if (!parent) {
  49. // If the client child has no parent, it must have been the
  50. // previous root node, so there is no LCA and we can exit early.
  51. *out_lca = tree_->GetNull();
  52. return true;
  53. - } else if (client_child->parent->id != id) {
  54. + } else if (parent->id != id) {
  55. // If the client child's parent is not this node, update the LCA
  56. // and return true (reparenting was found).
  57. *out_lca = LeastCommonAncestor(*out_lca, client_child);
  58. @@ -362,6 +368,19 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::ClientTreeNodeById(
  59. return nullptr;
  60. }
  61. +template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
  62. +ClientTreeNode*
  63. +AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::GetClientTreeNodeParent(
  64. + ClientTreeNode* obj) {
  65. + ClientTreeNode* parent = obj->parent;
  66. +#if DCHECK_IS_ON()
  67. + if (!parent)
  68. + return nullptr;
  69. + DCHECK(ClientTreeNodeById(parent->id)) << "Parent not in id map.";
  70. +#endif // DCHECK_IS_ON()
  71. + return parent;
  72. +}
  73. +
  74. template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
  75. bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges(
  76. AXSourceNode node,
  77. @@ -545,8 +564,13 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
  78. // above. If this happens, reset and return an error.
  79. ClientTreeNode* client_child = ClientTreeNodeById(new_child_id);
  80. - if (client_child && client_child->parent != client_node) {
  81. - DVLOG(1) << "Reparenting detected";
  82. + if (client_child && GetClientTreeNodeParent(client_child) != client_node) {
  83. + DVLOG(1) << "Illegal reparenting detected";
  84. +#if defined(ADDRESS_SANITIZER)
  85. + // Wrapping this in ADDRESS_SANITIZER will cause it to run on
  86. + // clusterfuzz, which should help us narrow down the issue.
  87. + NOTREACHED() << "Illegal reparenting detected";
  88. +#endif
  89. Reset();
  90. return false;
  91. }