Commit fc124899 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[LayoutNG] Fix invalid memory access after reallocations

This patch fixes use-after-free when memory reallocation
occurs by adding BoxData for bidi inline fragmentations.

Bug: 925247, 961943
Change-Id: I5c2cd26546b45772fbff7d001d9e98e49ab19461
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1607719
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#658976}
parent e5b46ebc
......@@ -394,12 +394,15 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
const unsigned box_data_index = start->box_data_index;
if (!box_data_index)
continue;
// |box_data_list_[box_data_index - 1]| is the box for |start| child.
// Avoid keeping a pointer to the |BoxData| because it maybe invalidated as
// we add to |box_data_list_|.
// As |box_data_index| is converted to start/end of BoxData, update
// |box_data_index| to the parent box, or to 0 if no parent boxes.
// This allows including this box to the nested parent box.
BoxData* box_data = &box_data_list_[box_data_index - 1];
start->box_data_index = box_data->parent_box_data_index;
start->box_data_index =
box_data_list_[box_data_index - 1].parent_box_data_index;
// Find the end line box item.
const unsigned start_index = index;
......@@ -415,27 +418,32 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
// because the update is limited only when its |box_data_index| is lower.
while (end->box_data_index && end->box_data_index < box_data_index) {
UpdateBoxDataFragmentRange(line_box, index);
// Re-compute |box_data| in case |box_data_list_| was reallocated when
// |UpdateBoxDataFragmentRange| added new fragments.
box_data = &box_data_list_[box_data_index - 1];
}
if (box_data_index != end->box_data_index)
break;
end->box_data_index = box_data->parent_box_data_index;
end->box_data_index =
box_data_list_[box_data_index - 1].parent_box_data_index;
}
// If this is the first range for this BoxData, set it.
if (!box_data->fragment_end) {
box_data->fragment_start = start_index;
box_data->fragment_end = index;
if (!box_data_list_[box_data_index - 1].fragment_end) {
box_data_list_[box_data_index - 1].SetFragmentRange(start_index, index);
} else {
// This box is fragmented by BiDi reordering. Add a new BoxData for the
// fragmented range.
box_data->fragmented_box_data_index = box_data_list_.size();
box_data_list_.emplace_back(*box_data, start_index, index);
box_data_list_[box_data_index - 1].fragmented_box_data_index =
box_data_list_.size();
// Do not use `emplace_back()` here because adding to |box_data_list_| may
// reallocate the buffer. Create a new instance and |push_back()| instead.
BoxData fragmented_box_data(box_data_list_[box_data_index - 1],
start_index, index);
box_data_list_.push_back(fragmented_box_data);
}
return box_data->parent_box_data_index ? start_index : index;
// If this box has parent boxes, we need to process it again.
if (box_data_list_[box_data_index - 1].parent_box_data_index)
return start_index;
return index;
}
return index;
}
......
......@@ -214,6 +214,11 @@ class CORE_EXPORT NGInlineLayoutStateStack {
size(other.size),
offset(other.offset) {}
void SetFragmentRange(unsigned start_index, unsigned end_index) {
fragment_start = start_index;
fragment_end = end_index;
}
// The range of child fragments this box contains.
unsigned fragment_start;
unsigned fragment_end;
......
<!DOCTYPE html>
<title>CSS Writing Modes Test: many levels of bidi inline fragmentations does not crash</title>
<link rel="help" href="http://crbug.com/925247">
<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
span {
border: blue solid 2px;
}
</style>
<body>
<div>
<span>
1&#x202E;2&#x202D;
<span>3&#x202E;4&#x202D;
<span>5&#x202E;6&#x202D;
<span>7&#x202E;8&#x202D;</span>
</span>
</span>
</span>
x
</div>
<script>
test(() => {
document.body.offsetTop;
});
</script>
</body>
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