Commit b1af726a authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Revert "Revert "Fix Heap-use-after-free Bug""

This reverts commit 0814d71d.

Reason for revert: A fix is ready, but requires this reland.

Original change's description:
> Revert "Fix Heap-use-after-free Bug"
> 
> This reverts commit d09047bc.
> 
> Reason for revert: 
> This CL breaks Linux Trusty MSAN bot.
> See
> https://luci-milo.appspot.com/buildbot/chromium.webkit/WebKit%20Linux%20Trusty%20MSAN/2350
> and successive builds.
> 
> Sample logs:
> 17:44:44.594 32438   ==1:1==WARNING: MemorySanitizer: use-of-uninitialized-value
> 17:44:44.594 32438       #0 0xf548000 in blink::LayoutTableCell::ShouldClipOverflow() const third_party/WebKit/Source/core/layout/LayoutTableCell.cpp:459:35
> 17:44:44.594 32438       #1 0xfdd1161 in NeedsOverflowClip third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp:803:48
> 17:44:44.594 32438       #2 0xfdd1161 in UpdatePaintProperties third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp:1208:0
> 17:44:44.594 32438       #3 0xfdd1161 in blink::PaintPropertyTreeBuilder::UpdatePropertiesForSelf(blink::LayoutObject const&, blink::PaintPropertyTreeBuilderContext&) third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp:1244:0
> 17:44:44.594 32438       #4 0xfd6963c in blink::PrePaintTreeWalk::Walk(blink::LayoutObject const&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:190:28
> 17:44:44.594 32438       #5 0xfd6a1bb in blink::PrePaintTreeWalk::Walk(blink::LayoutObject const&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:215:5
> 17:44:44.594 32438       #6 0xfd6a1bb in blink::PrePaintTreeWalk::Walk(blink::LayoutObject const&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:215:5
> 17:44:44.594 32438       #7 0xfd6a1bb in blink::PrePaintTreeWalk::Walk(blink::LayoutObject const&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:215:5
> 17:44:44.594 32438       #8 0xfd6a1bb in blink::PrePaintTreeWalk::Walk(blink::LayoutObject const&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:215:5
> 17:44:44.594 32438       #9 0xfd68046 in blink::PrePaintTreeWalk::Walk(blink::LocalFrameView&, blink::PrePaintTreeWalkContext const&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:92:5
> 17:44:44.594 32438       #10 0xfd674b4 in blink::PrePaintTreeWalk::Walk(blink::LocalFrameView&) third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp:66:3
> 17:44:44.594 32438       #11 0xe513327 in blink::LocalFrameView::PrePaint() third_party/WebKit/Source/core/frame/LocalFrameView.cpp:3255:24
> 17:44:44.594 32438       #12 0xe50d013 in blink::LocalFrameView::UpdateLifecyclePhasesInternal(blink::DocumentLifecycle::LifecycleState) third_party/WebKit/Source/core/frame/LocalFrameView.cpp:3186:9
> 17:44:44.594 32438       #13 0xfb2ff7c in blink::PageAnimator::UpdateAllLifecyclePhases(blink::LocalFrame&) third_party/WebKit/Source/core/page/PageAnimator.cpp:100:9
> 17:44:44.594 32438       #14 0x1451947d in blink::WebViewImpl::UpdateAllLifecyclePhases() third_party/WebKit/Source/core/exported/WebViewImpl.cpp:1984:3
> 17:44:44.594 32438       #15 0x6b9e8bb in content::BlinkTestRunner::TestFinished() content/shell/renderer/layout_test/blink_test_runner.cc:606:11
> 17:44:44.594 32438       #16 0x11d957ed in test_runner::TestRunner::WorkQueue::ProcessWorkSoon() content/shell/test_runner/test_runner.cc:1572:29
> 17:44:44.595 32438       #17 0x11d9db51 in LocationChangeDone content/shell/test_runner/test_runner.cc:2819:17
> 17:44:44.595 32438       #18 0x11d9db51 in test_runner::TestRunner::tryToClearTopLoadingFrame(blink::WebFrame*) content/shell/test_runner/test_runner.cc:1951:0
> 17:44:44.595 32438       #19 0xf9a560e in blink::ProgressTracker::ProgressCompleted() third_party/WebKit/Source/core/loader/ProgressTracker.cpp:122:26
> 17:44:44.595 32438       #20 0xf94bfe5 in blink::FrameLoader::DidFinishNavigation() third_party/WebKit/Source/core/loader/FrameLoader.cpp:478:24
> 17:44:44.595 32438       #21 0xdbf17f7 in blink::Document::CheckCompleted() third_party/WebKit/Source/core/dom/Document.cpp:3234:20
> 17:44:44.595 32438       #22 0xf94b490 in blink::FrameLoader::FinishedParsing() third_party/WebKit/Source/core/loader/FrameLoader.cpp:448:26
> 17:44:44.595 32438       #23 0xdc2c180 in blink::Document::FinishedParsing() third_party/WebKit/Source/core/dom/Document.cpp:5636:21
> 17:44:44.595 32438       #24 0x10359be3 in blink::XMLDocumentParser::end() third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp:413:18
> 17:44:44.595 32438       #25 0xf9134e4 in blink::DocumentWriter::end() third_party/WebKit/Source/core/loader/DocumentWriter.cpp:109:12
> 17:44:44.595 32438       #26 0xf8f9e7f in EndWriting third_party/WebKit/Source/core/loader/DocumentLoader.cpp:896:12
> 17:44:44.595 32438       #27 0xf8f9e7f in blink::DocumentLoader::FinishedLoading(double) third_party/WebKit/Source/core/loader/DocumentLoader.cpp:455:0
> 17:44:44.595 32438       #28 0x45cfb05 in blink::Resource::CheckNotify() third_party/WebKit/Source/platform/loader/fetch/Resource.cpp:336:8
> 17:44:44.595 32438       #29 0x46125d0 in blink::ResourceFetcher::HandleLoaderFinish(blink::Resource*, double, blink::ResourceFetcher::LoaderFinishType) third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp:1333:15
> 17:44:44.595 32438       #30 0x1375febb in content::WebURLLoaderImpl::Context::OnCompletedRequest(int, bool, bool, base::TimeTicks const&, long, long, long) content/child/web_url_loader_impl.cc:904:16
> 17:44:44.595 32438       #31 0xc0c93f5 in content::ResourceDispatcher::OnRequestComplete(int, content::ResourceRequestCompletionStatus const&) content/child/resource_dispatcher.cc:374:9
> 17:44:44.595 32438       #32 0xc0d0e07 in DispatchToMethodImpl<content::ResourceDispatcher *, void (content::ResourceDispatcher::*)(int, const content::ResourceRequestCompletionStatus &), const std::__1::tuple<int, content::ResourceRequestCompletionStatus> &, 0, 1> base/tuple.h:77:3
> 17:44:44.595 32438       #33 0xc0d0e07 in DispatchToMethod<content::ResourceDispatcher *, void (content::ResourceDispatcher::*)(int, const content::ResourceRequestCompletionStatus &), const std::__1::tuple<int, content::ResourceRequestCompletionStatus> &> base/tuple.h:84:0
> 17:44:44.595 32438       #34 0xc0d0e07 in DispatchToMethod<content::ResourceDispatcher, void (content::ResourceDispatcher::*)(int, const content::ResourceRequestCompletionStatus &), void, std::__1::tuple<int, content::ResourceRequestCompletionStatus> > ipc/ipc_message_templates.h:26:0
> 17:44:44.595 32438       #35 0xc0d0e07 in bool IPC::MessageT<ResourceMsg_RequestComplete_Meta, std::__1::tuple<int, content::ResourceRequestCompletionStatus>, void>::Dispatch<content::ResourceDispatcher, content::ResourceDispatcher, void, void (content::ResourceDispatcher::*)(int, content::ResourceRequestCompletionStatus const&)>(IPC::Message const*, content::ResourceDispatcher*, content::ResourceDispatcher*, void*, void (content::ResourceDispatcher::*)(int, content::ResourceRequestCompletionStatus const&)) ipc/ipc_message_templates.h:121:0
> 17:44:44.595 32438       #36 0xc0bfe8a in content::ResourceDispatcher::DispatchMessage(IPC::Message const&) content/child/resource_dispatcher.cc:535:5
> 17:44:44.595 32438       #37 0xc0bd497 in content::ResourceDispatcher::OnMessageReceived(IPC::Message const&) content/child/resource_dispatcher.cc:136:3
> 17:44:44.595 32438       #38 0xc0d86f9 in content::ResourceSchedulingFilter::DispatchMessage(IPC::Message const&) content/child/resource_scheduling_filter.cc:74:27
> 17:44:44.595 32438       #39 0x6c8e490 in Run base/callback.h:91:12
> 17:44:44.595 32438       #40 0x6c8e490 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:59:0
> 17:44:44.595 32438       #41 0x46c2540 in blink::scheduler::TaskQueueManager::ProcessTaskFromWorkQueue(blink::scheduler::internal::WorkQueue*, bool, blink::scheduler::LazyNow, base::TimeTicks*) third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc:532:19
> 17:44:44.595 32438       #42 0x46b600a in blink::scheduler::TaskQueueManager::DoWork(bool) third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.cc:330:13
> 17:44:44.595 32438       #43 0x6c8e490 in Run base/callback.h:91:12
> 17:44:44.595 32438       #44 0x6c8e490 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) base/debug/task_annotator.cc:59:0
> 17:44:44.595 32438       #45 0x6d1f88e in base::MessageLoop::RunTask(base::PendingTask*) base/message_loop/message_loop.cc:404:19
> 17:44:44.595 32438       #46 0x6d22ad9 in base::MessageLoop::DeferOrRunPendingTask(base::PendingTask) base/message_loop/message_loop.cc:415:5
> 17:44:44.595 32438       #47 0x6d23ad6 in base::MessageLoop::DoWork() base/message_loop/message_loop.cc:522:13
> 17:44:44.595 32438       #48 0x6d3023a in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) base/message_loop/message_pump_default.cc:33:31
> 17:44:44.595 32438       #49 0x6dbef5b in base::RunLoop::Run() base/run_loop.cc:112:14
> 17:44:44.595 32438       #50 0x113da4bf in content::RendererMain(content::MainFunctionParams const&) content/renderer/renderer_main.cc:219:23
> 17:44:44.595 32438       #51 0x4821509 in content::RunZygote(content::MainFunctionParams const&, content::ContentMainDelegate*) content/app/content_main_runner.cc:337:14
> 17:44:44.595 32438       #52 0x48240fa in content::RunNamedProcessTypeMain(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, content::MainFunctionParams const&, content::ContentMainDelegate*) content/app/content_main_runner.cc:416:12
> 17:44:44.595 32438       #53 0x4826d77 in content::ContentMainRunnerImpl::Run() content/app/content_main_runner.cc:687:12
> 17:44:44.595 32438       #54 0xbfb00ba in service_manager::Main(service_manager::MainParams const&) services/service_manager/embedder/main.cc:469:29
> 17:44:44.595 32438       #55 0x16265ee in content::ContentMain(content::ContentMainParams const&) content/app/content_main.cc:19:10
> 17:44:44.595 32438       #56 0x4a904f in main content/shell/app/shell_main.cc:48:10
> 17:44:44.595 32438       #57 0x7fa0d53baf44 in __libc_start_main /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287:0
> 17:44:44.595 32438       #58 0x43cf9a in _start ??:0:0
> 17:44:44.595 32438   
> 17:44:44.595 32438     Uninitialized value was stored to memory at
> 17:44:44.596 32438       #0 0xf5430fb in SetCellWidthChanged third_party/WebKit/Source/core/layout/LayoutTableCell.h:235:65
> 17:44:44.596 32438       #1 0xf5430fb in blink::LayoutTableCell::UpdateLayout() third_party/WebKit/Source/core/layout/LayoutTableCell.cpp:327:0
> 17:44:44.596 32438       #2 0xf59d164 in LayoutIfNeeded third_party/WebKit/Source/core/layout/LayoutObject.h:1110:7
> 17:44:44.596 32438       #3 0xf59d164 in blink::LayoutTableSection::LayoutRows() third_party/WebKit/Source/core/layout/LayoutTableSection.cpp:1252:0
> 17:44:44.596 32438       #4 0xf524b1c in blink::LayoutTable::UpdateLayout() third_party/WebKit/Source/core/layout/LayoutTable.cpp:717:16
> 17:44:44.596 32438       #5 0xf185d49 in LayoutIfNeeded third_party/WebKit/Source/core/layout/LayoutObject.h:1110:7
> 17:44:44.596 32438       #6 0xf185d49 in blink::LayoutBlock::LayoutPositionedObject(blink::LayoutBox*, bool, blink::LayoutBlock::PositionedLayoutBehavior) third_party/WebKit/Source/core/layout/LayoutBlock.cpp:828:0
> 17:44:44.596 32438       #7 0xf184ef7 in blink::LayoutBlock::LayoutPositionedObjects(bool, blink::LayoutBlock::PositionedLayoutBehavior) third_party/WebKit/Source/core/layout/LayoutBlock.cpp:773:5
> 17:44:44.596 32438       #8 0xf1b1e0e in blink::LayoutBlockFlow::UpdateBlockLayout(bool) third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp:485:3
> 17:44:44.596 32438       #9 0xf17eb46 in blink::LayoutBlock::UpdateLayout() third_party/WebKit/Source/core/layout/LayoutBlock.cpp:427:3
> 17:44:44.596 32438       #10 0xf645987 in LayoutContent third_party/WebKit/Source/core/layout/LayoutView.cpp:224:20
> 17:44:44.596 32438       #11 0xf645987 in blink::LayoutView::UpdateLayout() third_party/WebKit/Source/core/layout/LayoutView.cpp:316:0
> 17:44:44.596 32438       #12 0xe4eadff in blink::LocalFrameView::PerformLayout(bool) third_party/WebKit/Source/core/frame/LocalFrameView.cpp:1082:22
> 17:44:44.596 32438       #13 0xe4dee95 in blink::LocalFrameView::UpdateLayout() third_party/WebKit/Source/core/frame/LocalFrameView.cpp:1265:10
> 17:44:44.596 32438       #14 0xdbf2315 in blink::Document::ImplicitClose() third_party/WebKit/Source/core/dom/Document.cpp:3155:15
> 17:44:44.596 32438       #15 0xdbf1070 in blink::Document::CheckCompleted() third_party/WebKit/Source/core/dom/Document.cpp:3212:5
> 17:44:44.596 32438       #16 0xf94b490 in blink::FrameLoader::FinishedParsing() third_party/WebKit/Source/core/loader/FrameLoader.cpp:448:26
> 17:44:44.596 32438       #17 0xdc2c180 in blink::Document::FinishedParsing() third_party/WebKit/Source/core/dom/Document.cpp:5636:21
> 17:44:44.596 32438       #18 0x10359be3 in blink::XMLDocumentParser::end() third_party/WebKit/Source/core/xml/parser/XMLDocumentParser.cpp:413:18
> 17:44:44.596 32438       #19 0xf9134e4 in blink::DocumentWriter::end() third_party/WebKit/Source/core/loader/DocumentWriter.cpp:109:12
> 17:44:44.596 32438       #20 0xf8f9e7f in EndWriting third_party/WebKit/Source/core/loader/DocumentLoader.cpp:896:12
> 17:44:44.596 32438       #21 0xf8f9e7f in blink::DocumentLoader::FinishedLoading(double) third_party/WebKit/Source/core/loader/DocumentLoader.cpp:455:0
> 17:44:44.596 32438       #22 0x45cfb05 in blink::Resource::CheckNotify() third_party/WebKit/Source/platform/loader/fetch/Resource.cpp:336:8
> 17:44:44.596 32438       #23 0x46125d0 in blink::ResourceFetcher::HandleLoaderFinish(blink::Resource*, double, blink::ResourceFetcher::LoaderFinishType) third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp:1333:15
> 17:44:44.596 32438       #24 0x1375febb in content::WebURLLoaderImpl::Context::OnCompletedRequest(int, bool, bool, base::TimeTicks const&, long, long, long) content/child/web_url_loader_impl.cc:904:16
> 17:44:44.596 32438   
> 
> 
> Original change's description:
> > Fix Heap-use-after-free Bug
> > 
> > Add a new member variable LayoutTableCell::is_spanning_collapsed_row_ so that
> > there is no need to access LayoutTableSection::RowHasVisibilityCollapse
> > in LayoutTableCell. This avoids using the memory that has already been
> > freed.
> > 
> > Bug: 750016
> > Change-Id: I1838a775f3b45315b2dee3e15942af0dff0c5955
> > Reviewed-on: https://chromium-review.googlesource.com/594935
> > Reviewed-by: Morten Stenshorne <mstensho@opera.com>
> > Commit-Queue: Joy Yu <joysyu@google.com>
> > Cr-Commit-Position: refs/heads/master@{#491139}
> 
> TBR=dgrogan@chromium.org,mstensho@opera.com,joysyu@google.com
> 
> Change-Id: Idaad8aba8647775eb2387688919c25b6ad4a8eda
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 750016
> Reviewed-on: https://chromium-review.googlesource.com/597667
> Reviewed-by: Guido Urdaneta <guidou@chromium.org>
> Commit-Queue: Guido Urdaneta <guidou@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#491315}

TBR=dgrogan@chromium.org,mstensho@opera.com,guidou@chromium.org,joysyu@google.com

Change-Id: I4e1b4c59275699a5aa610d9ff338c062d8982268
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 750016
Reviewed-on: https://chromium-review.googlesource.com/597687Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491322}
parent 209f5623
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<table>
<tbody>
<tr>
<td id="rowspanned" rowspan="2"></td>
</tr>
<tr id="removeMe"></tr>
</tbody>
</table>
<script>
test(() => {
var rowspanned = document.getElementById("rowspanned");
var removeMe = document.getElementById("removeMe");
// First trigger a layout pass, to build and lay out what we already have.
document.body.offsetTop;
// Then remove the second table row. This will trigger SetNeedsCellRecalc()
// on the table section. Many operations on the table will now be dangerous
// (because there might be dangling pointers), until we have recalculated
// the data structures (by calling RecalcCells()). Unless someone explicitly
// demands this to be done, this recalculation won't happen until the next
// layout pass.
removeMe.parentNode.removeChild(removeMe);
// Before we actually get around to updating the data structures in the
// table, change some arbitrary style on the table cell to trigger
// StyleDidChange() on the cell, which will call ShouldClipOverflow().
rowspanned.style.color = "blue";
}, "No crash or assertion failure. crbug.com/750016");
</script>
\ No newline at end of file
...@@ -456,17 +456,7 @@ void LayoutTableCell::ComputeOverflow(LayoutUnit old_client_after_edge, ...@@ -456,17 +456,7 @@ void LayoutTableCell::ComputeOverflow(LayoutUnit old_client_after_edge,
} }
bool LayoutTableCell::ShouldClipOverflow() const { bool LayoutTableCell::ShouldClipOverflow() const {
if (LayoutBox::ShouldClipOverflow()) return IsSpanningCollapsedRow() || LayoutBox::ShouldClipOverflow();
return true;
unsigned row_span = RowSpan();
if (row_span == 1)
return false;
unsigned row_index = RowIndex();
for (unsigned r = row_index; r < row_index + row_span; r++) {
if (Section()->RowHasVisibilityCollapse(r))
return true;
}
return false;
} }
LayoutUnit LayoutTableCell::CellBaselinePosition() const { LayoutUnit LayoutTableCell::CellBaselinePosition() const {
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
namespace blink { namespace blink {
#define BITS_OF_ABSOLUTE_COLUMN_INDEX 28 #define BITS_OF_ABSOLUTE_COLUMN_INDEX 27
static const unsigned kUnsetColumnIndex = static const unsigned kUnsetColumnIndex =
(1u << BITS_OF_ABSOLUTE_COLUMN_INDEX) - 1; (1u << BITS_OF_ABSOLUTE_COLUMN_INDEX) - 1;
static const unsigned kMaxColumnIndex = kUnsetColumnIndex - 1; static const unsigned kMaxColumnIndex = kUnsetColumnIndex - 1;
...@@ -329,6 +329,12 @@ class CORE_EXPORT LayoutTableCell final : public LayoutBlockFlow { ...@@ -329,6 +329,12 @@ class CORE_EXPORT LayoutTableCell final : public LayoutBlockFlow {
RowIndex() + RowSpan() == other->RowIndex() + other->RowSpan(); RowIndex() + RowSpan() == other->RowIndex() + other->RowSpan();
} }
void SetIsSpanningCollapsedRow(bool spanningCollapsedRow) {
is_spanning_collapsed_row_ = spanningCollapsedRow;
}
bool IsSpanningCollapsedRow() const { return is_spanning_collapsed_row_; }
protected: protected:
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void ComputePreferredLogicalWidths() override; void ComputePreferredLogicalWidths() override;
...@@ -476,6 +482,7 @@ class CORE_EXPORT LayoutTableCell final : public LayoutBlockFlow { ...@@ -476,6 +482,7 @@ class CORE_EXPORT LayoutTableCell final : public LayoutBlockFlow {
unsigned cell_width_changed_ : 1; unsigned cell_width_changed_ : 1;
unsigned has_col_span_ : 1; unsigned has_col_span_ : 1;
unsigned has_row_span_ : 1; unsigned has_row_span_ : 1;
unsigned is_spanning_collapsed_row_ : 1;
// This is set when collapsed_border_values_ needs recalculation. // This is set when collapsed_border_values_ needs recalculation.
mutable unsigned collapsed_border_values_valid_ : 1; mutable unsigned collapsed_border_values_valid_ : 1;
......
...@@ -888,6 +888,16 @@ int LayoutTableSection::CalcRowLogicalHeight() { ...@@ -888,6 +888,16 @@ int LayoutTableSection::CalcRowLogicalHeight() {
std::max(index_of_first_stretchable_row, row_index_below_cell); std::max(index_of_first_stretchable_row, row_index_below_cell);
} else if (cell->RowSpan() > 1) { } else if (cell->RowSpan() > 1) {
DCHECK(!row_span_cells.Contains(cell)); DCHECK(!row_span_cells.Contains(cell));
cell->SetIsSpanningCollapsedRow(false);
unsigned end_row = cell->RowSpan() + r;
for (unsigned spanning = r; spanning < end_row; spanning++) {
if (RowHasVisibilityCollapse(spanning)) {
cell->SetIsSpanningCollapsedRow(true);
break;
}
}
row_span_cells.push_back(cell); row_span_cells.push_back(cell);
} }
......
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