ofz#49713 Heap-use-after-free
the dtor of ScAttrArray where the std::vector<ScAttrEntry> ends up
will call ScDocumentPool::Remove on each entries pPattern, assuming
that a matching ScDocumentPool::Put was called on each, something
that is elided if we just do a simply copy here.
probably a problem since:
commit dddee125cc32f1ad5228e598a7de04e9654e65c1
Date: Thu Mar 10 15:03:25 2022 +0100
load ods/xlsx with full row attributes without allocating all columns
Change-Id: I3a5e2e3fa4d40343f30f9eefbabd1579d8a97e02
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138262
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/qa/unit/data/xls/pass/ofz49713-1.xls b/sc/qa/unit/data/xls/pass/ofz49713-1.xls
new file mode 100644
index 0000000..b325740
--- /dev/null
+++ b/sc/qa/unit/data/xls/pass/ofz49713-1.xls
Binary files differ
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index c7c8a92..4eb5671 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -2897,6 +2897,20 @@ void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
CreateColumnIfNotExists(i).ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray, pIsChanged);
}
namespace
{
std::vector<ScAttrEntry> duplicateScAttrEntries(ScDocument& rDocument, const std::vector<ScAttrEntry>& rOrigData)
{
std::vector<ScAttrEntry> aData(rOrigData);
for (size_t nIdx = 0; nIdx < aData.size(); ++nIdx)
{
ScPatternAttr aNewPattern(*aData[nIdx].pPattern);
aData[nIdx].pPattern = &rDocument.GetPool()->Put(aNewPattern);
}
return aData;
}
}
void ScTable::SetAttrEntries( SCCOL nStartCol, SCCOL nEndCol, std::vector<ScAttrEntry> && vNewData)
{
if (!ValidCol(nStartCol) || !ValidCol(nEndCol))
@@ -2908,8 +2922,7 @@ void ScTable::SetAttrEntries( SCCOL nStartCol, SCCOL nEndCol, std::vector<ScAttr
// If we would like set all columns to same attrs, then change only attrs for not existing columns
nEndCol = aCol.size() - 1;
for (SCCOL i = nStartCol; i <= nEndCol; i++)
// [-loplugin:redundantfcast] false positive:
aCol[i].SetAttrEntries( std::vector<ScAttrEntry>(vNewData));
aCol[i].SetAttrEntries(duplicateScAttrEntries(rDocument, vNewData));
aDefaultColData.SetAttrEntries(std::move(vNewData));
}
else
@@ -2922,8 +2935,7 @@ void ScTable::SetAttrEntries( SCCOL nStartCol, SCCOL nEndCol, std::vector<ScAttr
{
CreateColumnIfNotExists( nEndCol );
for (SCCOL i = nStartCol; i < nEndCol; i++) // all but last need a copy
// [-loplugin:redundantfcast] false positive:
aCol[i].SetAttrEntries( std::vector<ScAttrEntry>(vNewData));
aCol[i].SetAttrEntries(duplicateScAttrEntries(rDocument, vNewData));
aCol[nEndCol].SetAttrEntries( std::move(vNewData));
}
}