crashtesting: clamp string concatenation to each matrix operand's size
Concatenating two matrices of different sizes gives a result the size
of the larger one.
Each operand was read across the whole result. The shorter operand
has fewer cells than the result, so the read ran past the operand's
end and went out of bounds, which crashed. Now each operand is read
only within its own size.
A cell that only the larger operand covers has no partner in the
shorter one to join with, so it stays empty.
a problem since:
commit b4957ed105bcaa4a73666a6a5e119d523284b0c9
Date: Sat Jun 27 19:26:56 2026 +0900
sc: extend mismatched-extent matrix arithmetic to the longer side
Signed-off-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Change-Id: I0ae4a0b71a846bb88383cd1cb472a022895ae14a
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/6696
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 645e103b914f07f80c0c425fb1b3262e5e4f1648)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208007
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
committed by
Xisco Fauli
parent
ed9864df27
commit
35ddb41dcc
@@ -2273,6 +2273,44 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixArithmeticMismatchedExtent)
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixConcatMismatchedExtent)
|
||||
{
|
||||
// String concatenation of two two-dimensional ranges of unequal
|
||||
// length extends the result to the longer range. Where the two
|
||||
// ranges overlap the cells join together. The rows past the shorter
|
||||
// operand have no partner to join and stay empty.
|
||||
sc::AutoCalcSwitch aACSwitch(*m_pDoc, true);
|
||||
m_pDoc->InsertTab(0, u"Test"_ustr);
|
||||
|
||||
// First operand A1:B3, three rows by two columns.
|
||||
m_pDoc->SetString(ScAddress(0, 0, 0), u"a"_ustr);
|
||||
m_pDoc->SetString(ScAddress(1, 0, 0), u"b"_ustr);
|
||||
m_pDoc->SetString(ScAddress(0, 1, 0), u"c"_ustr);
|
||||
m_pDoc->SetString(ScAddress(1, 1, 0), u"d"_ustr);
|
||||
m_pDoc->SetString(ScAddress(0, 2, 0), u"e"_ustr);
|
||||
m_pDoc->SetString(ScAddress(1, 2, 0), u"f"_ustr);
|
||||
|
||||
// Second operand D1:E2, two rows by two columns, one row shorter.
|
||||
m_pDoc->SetString(ScAddress(3, 0, 0), u"1"_ustr);
|
||||
m_pDoc->SetString(ScAddress(4, 0, 0), u"2"_ustr);
|
||||
m_pDoc->SetString(ScAddress(3, 1, 0), u"3"_ustr);
|
||||
m_pDoc->SetString(ScAddress(4, 1, 0), u"4"_ustr);
|
||||
|
||||
ScMarkData aMark(m_pDoc->GetSheetLimits());
|
||||
aMark.SelectOneTable(0);
|
||||
m_pDoc->InsertMatrixFormula(6, 0, 7, 2, aMark, u"=A1:B3&D1:E2"_ustr);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(u"a1"_ustr, m_pDoc->GetString(ScAddress(6, 0, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(u"b2"_ustr, m_pDoc->GetString(ScAddress(7, 0, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(u"c3"_ustr, m_pDoc->GetString(ScAddress(6, 1, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(u"d4"_ustr, m_pDoc->GetString(ScAddress(7, 1, 0)));
|
||||
// The third row is past the second operand, so those cells stay empty.
|
||||
CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(6, 2, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(OUString(), m_pDoc->GetString(ScAddress(7, 2, 0)));
|
||||
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixOp)
|
||||
{
|
||||
m_pDoc->InsertTab(0, u"Test"_ustr);
|
||||
|
||||
@@ -2888,7 +2888,7 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef&
|
||||
else
|
||||
xMat1->ExecuteOperation(
|
||||
std::pair<size_t, size_t>(0, 0),
|
||||
std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
|
||||
std::pair<size_t, size_t>(std::min(nR1, nMaxRow) - 1, std::min(nC1, nMaxCol) - 1),
|
||||
std::move(aDoubleFunc), std::move(aBoolFunc), std::move(aStringFunc), std::move(aEmptyFunc));
|
||||
|
||||
std::vector<svl::SharedString> aSharedString(nMaxCol*nMaxRow);
|
||||
@@ -2952,7 +2952,7 @@ void ScMatrixImpl::MatConcat(SCSIZE nMaxCol, SCSIZE nMaxRow, const ScMatrixRef&
|
||||
else
|
||||
xMat2->ExecuteOperation(
|
||||
std::pair<size_t, size_t>(0, 0),
|
||||
std::pair<size_t, size_t>(nMaxRow - 1, nMaxCol - 1),
|
||||
std::pair<size_t, size_t>(std::min(nR2, nMaxRow) - 1, std::min(nC2, nMaxCol) - 1),
|
||||
std::move(aDoubleFunc2), std::move(aBoolFunc2), std::move(aStringFunc2), std::move(aEmptyFunc2));
|
||||
|
||||
aString.clear();
|
||||
|
||||
Reference in New Issue
Block a user