editeng/qa/unit/core-test.cxx       |   64 ++++++++++++++++++++++++++++++++++++
 editeng/source/editeng/impedit3.cxx |    2 +
 2 files changed, 66 insertions(+)

New commits:
commit 7ff601feca1796b6656e66c7ce2e77edcf0bdd67
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Wed Sep 4 03:16:06 2024 -0600
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Wed Sep 4 19:29:51 2024 +0200

    tdf#151748 editeng: Fix crash in kashida justification after update
    
    Commit 937023bca427f803a9e7085d5090d5d2b17623ed aggravated a bug that
    would cause editeng to use stale kashida positions after document
    changes (for example, font changes). This could cause crashes or
    spurious kashida, and both much more often after the above commit.
    
    This change fixes the underlying logic error.
    
    Change-Id: Id6465e739740a38ed11c9d9378d30faa51948731
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172866
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>
    Tested-by: Jenkins

diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx
index 1286c7ade36a..7c6ff42a05b8 100644
--- a/editeng/qa/unit/core-test.cxx
+++ b/editeng/qa/unit/core-test.cxx
@@ -18,6 +18,7 @@
 
 #include <sfx2/app.hxx>
 #include <svl/itempool.hxx>
+#include <editeng/adjustitem.hxx>
 #include <editeng/editeng.hxx>
 #include <editeng/eeitem.hxx>
 #include <editeng/lspcitem.hxx>
@@ -127,6 +128,7 @@ public:
     void testMoveParagraph();
     void testCreateLines();
     void testTdf154248MultilineFieldWrapping();
+    void testTdf151748StaleKashidaArray();
 
     DECL_STATIC_LINK(Test, CalcFieldValueHdl, EditFieldInfo*, void);
 
@@ -159,6 +161,7 @@ public:
     CPPUNIT_TEST(testMoveParagraph);
     CPPUNIT_TEST(testCreateLines);
     CPPUNIT_TEST(testTdf154248MultilineFieldWrapping);
+    CPPUNIT_TEST(testTdf151748StaleKashidaArray);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -2239,6 +2242,67 @@ void Test::testTdf154248MultilineFieldWrapping()
     }
 }
 
+void Test::testTdf151748StaleKashidaArray()
+{
+    ScopedVclPtrInstance<VirtualDevice> 
pVirtualDevice(DeviceFormat::WITHOUT_ALPHA);
+
+    EditEngine aEditEngine(mpItemPool.get());
+    aEditEngine.SetRefDevice(pVirtualDevice.get());
+    aEditEngine.SetPaperSize(Size(1500, 500));
+    
aEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::R2L);
+    aEditEngine.SetText(u"خط تخوردگی و توسط"_ustr);
+
+    CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aEditEngine.GetParagraphCount());
+
+    SfxItemSet aSet{ aEditEngine.GetParaAttribs(0) };
+    aSet.Put(SvxAdjustItem{ SvxAdjust::Block, EE_PARA_JUST });
+    aEditEngine.SetParaAttribs(0, aSet);
+
+    CPPUNIT_ASSERT_EQUAL(SvxAdjust::Block, aEditEngine.GetParaAttrib(0, 
EE_PARA_JUST).GetAdjust());
+    CPPUNIT_ASSERT_EQUAL(true, aEditEngine.IsFormatted());
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aEditEngine.GetLineCount(0));
+
+    // Initial state: Check that a kashida array has been created
+    {
+        ParaPortionList& rParagraphPortionList = aEditEngine.GetParaPortions();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rParagraphPortionList.Count());
+
+        EditLineList& rLines = rParagraphPortionList.getRef(0).GetLines();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rLines.Count());
+        EditLine const& rLine = rLines[0];
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rLine.GetStart());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd());
+
+        std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray();
+        CPPUNIT_ASSERT_EQUAL(size_t(17), rArray.size());
+    }
+
+    // Resize the paper so there is no longer room for kashida
+    aEditEngine.SetPaperSize(Size(1400, 500));
+
+    // Follow-up state: Check that the kashida array has been cleared
+    {
+        ParaPortionList& rParagraphPortionList = aEditEngine.GetParaPortions();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rParagraphPortionList.Count());
+
+        EditLineList& rLines = rParagraphPortionList.getRef(0).GetLines();
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rLines.Count());
+        EditLine const& rLine = rLines[0];
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rLine.GetStart());
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(11), rLine.GetEnd());
+
+        std::vector<sal_Bool> const& rArray = rLine.GetKashidaArray();
+
+        // Since there is no room for kashida, the kashida array should be 
empty.
+        // Without the bug fix, this will be 17:
+        CPPUNIT_ASSERT_EQUAL(size_t(0), rArray.size());
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 }
 
diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index 3cd8ef12eb4d..d7c3111d9e8e 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -2378,6 +2378,8 @@ void ImpEditEngine::ImpAdjustBlocks(ParaPortion& 
rParaPortion, EditLine& rLine,
 
     // Mark Kashida positions, so that VCL knows where to insert Kashida and
     // where to only expand the width.
+    // The underlying array may be reused across updates. Ensure there is no 
stale data.
+    rLine.GetKashidaArray().clear();
     if (nKashidas)
     {
         rLine.GetKashidaArray().resize(rLine.GetCharPosArray().size(), false);

Reply via email to