Commit 1b749a28 authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

LayoutNG: Fix a crash with input[type=file]::after with huge margin

The crash is similar to crrev.com/806062.  In this case, both of
|line_width| and |item.InlineOffset()| are saturated to
LayoutUnit::Max(), then later width computation didn't work well.

This CL fixes the crash by checking the saturation, and also adds
vector index checking to prevent similar issues.

Bug: 1129570
Change-Id: I7b019fb09dda68b24a70cc6f4865dfa22a70ded1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2423759
Auto-Submit: Kent Tamura <tkent@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809868}
parent 992e5b90
...@@ -247,6 +247,9 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -247,6 +247,9 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
LayoutUnit static_width_right = LayoutUnit(0); LayoutUnit static_width_right = LayoutUnit(0);
if (initial_index_right + 1 < line.size()) { if (initial_index_right + 1 < line.size()) {
const NGLogicalLineItem& item = line[initial_index_right + 1]; const NGLogicalLineItem& item = line[initial_index_right + 1];
// |line_width| and/or InlineOffset() might be saturated.
if (line_width <= item.InlineOffset())
return line_width;
static_width_right = static_width_right =
line_width - item.InlineOffset() + item.margin_line_left; line_width - item.InlineOffset() + item.margin_line_left;
} }
...@@ -266,8 +269,13 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -266,8 +269,13 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
if (IsLtr(line_direction_)) { if (IsLtr(line_direction_)) {
// Find truncation point at the left, truncate, and add an ellipsis. // Find truncation point at the left, truncate, and add an ellipsis.
while (available_width_left >= line[index_left].inline_size) while (available_width_left >= line[index_left].inline_size) {
available_width_left -= line[index_left++].inline_size; available_width_left -= line[index_left++].inline_size;
if (index_left >= line.size()) {
// We have a logic bug. Do nothing.
return line_width;
}
}
DCHECK_LE(index_left, index_right); DCHECK_LE(index_left, index_right);
DCHECK(!line[index_left].IsPlaceholder()); DCHECK(!line[index_left].IsPlaceholder());
wtf_size_t new_index = AddTruncatedChild( wtf_size_t new_index = AddTruncatedChild(
...@@ -288,8 +296,15 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -288,8 +296,15 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
} }
// Find truncation point at the right. // Find truncation point at the right.
while (available_width_right >= line[index_right].inline_size) while (available_width_right >= line[index_right].inline_size) {
available_width_right -= line[index_right--].inline_size; available_width_right -= line[index_right].inline_size;
if (index_right == 0) {
// We have a logic bug. We proceed anyway because |line| was already
// modified.
break;
}
--index_right;
}
LayoutUnit new_modified_right_offset = LayoutUnit new_modified_right_offset =
line[line.size() - 1].InlineOffset() + ellipsis_width_; line[line.size() - 1].InlineOffset() + ellipsis_width_;
DCHECK_LE(index_left, index_right); DCHECK_LE(index_left, index_right);
...@@ -316,8 +331,14 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -316,8 +331,14 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
} else { } else {
// Find truncation point at the right, truncate, and add an ellipsis. // Find truncation point at the right, truncate, and add an ellipsis.
while (available_width_right >= line[index_right].inline_size) while (available_width_right >= line[index_right].inline_size) {
available_width_right -= line[index_right--].inline_size; available_width_right -= line[index_right].inline_size;
if (index_right == 0) {
// We have a logic bug. Do nothing.
return line_width;
}
--index_right;
}
DCHECK_LE(index_left, index_right); DCHECK_LE(index_left, index_right);
DCHECK(!line[index_right].IsPlaceholder()); DCHECK(!line[index_right].IsPlaceholder());
wtf_size_t new_index = wtf_size_t new_index =
...@@ -341,8 +362,14 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle( ...@@ -341,8 +362,14 @@ LayoutUnit NGLineTruncator::TruncateLineInTheMiddle(
LayoutUnit ellipsis_offset = line[line.size() - 1].InlineOffset(); LayoutUnit ellipsis_offset = line[line.size() - 1].InlineOffset();
// Find truncation point at the left. // Find truncation point at the left.
while (available_width_left >= line[index_left].inline_size) while (available_width_left >= line[index_left].inline_size) {
available_width_left -= line[index_left++].inline_size; available_width_left -= line[index_left++].inline_size;
if (index_left >= line.size()) {
// We have a logic bug. We proceed anyway because |line| was already
// modified.
break;
}
}
DCHECK_LE(index_left, index_right); DCHECK_LE(index_left, index_right);
DCHECK(!line[index_left].IsPlaceholder()); DCHECK(!line[index_left].IsPlaceholder());
if (available_width_left > 0) { if (available_width_left > 0) {
......
...@@ -10,6 +10,15 @@ ...@@ -10,6 +10,15 @@
width: 100%; width: 100%;
padding-right: 100%; padding-right: 100%;
} }
.c19 {
width: 400px;
}
.c19:after {
content: 'a';
margin-left: 2000000000%;
}
</style> </style>
<input type="file"> <input type="file">
<script> <script>
...@@ -19,4 +28,11 @@ test(() => { ...@@ -19,4 +28,11 @@ test(() => {
fileInput.offsetWidth; fileInput.offsetWidth;
// Ok if no crash. // Ok if no crash.
}, ':after with large padding should not cause a crash.'); }, ':after with large padding should not cause a crash.');
test(() => {
const fileInput = document.querySelector('input');
fileInput.classList.add('c19');
fileInput.offsetWidth;
// Ok if no crash.
}, ':after with huge margin should not cause a crash.');
</script> </script>
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