diff options
author | Jonathan Clark <jonathan@libreoffice.org> | 2024-10-04 11:50:25 -0600 |
---|---|---|
committer | Jonathan Clark <jonathan@libreoffice.org> | 2024-10-05 00:05:05 +0200 |
commit | 99c7cf2816b2d0016832552dbe6c55456ade42e0 (patch) | |
tree | e55d5c9f05ddbb3e416f63cc59b22c8ac6843bbe /i18nutil/source | |
parent | 75f3ee7e8a06ed5fec17c358c62e3efeb8d13e8d (diff) |
crashtesting: fix font-dependent infinite loop in kashida justification
Commit c3c29d31d77ff93aa50634cfd51c62d12dc0f6ec (tdf#140767 Implemented
Syriac justification) indirectly introduced a font-dependent infinite
loop in Writer layout by relaxing some restrictions on kashida candidate
positions. The infinite loop was found in tdf97806-2.odt.
This change fixes an underlying logic bug in Writer, which caused Writer
to attempt to apply kashida justification to non-Arabic/Syriac CTL
scripts. This change also reintroduces some of the previously-lifted
restrictions on kashida candidate positions.
Change-Id: I783bf327f4ef0f1f6a032f0d3dddbcfd60a026fa
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174503
Tested-by: Jenkins
Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
Diffstat (limited to 'i18nutil/source')
-rw-r--r-- | i18nutil/source/utility/kashida.cxx | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/i18nutil/source/utility/kashida.cxx b/i18nutil/source/utility/kashida.cxx index a992e5c8e643..aff667033a11 100644 --- a/i18nutil/source/utility/kashida.cxx +++ b/i18nutil/source/utility/kashida.cxx @@ -134,6 +134,13 @@ bool CanConnectToPrev(sal_Unicode cCh, sal_Unicode cPrevCh) return bRet; } +bool isSyriacChar(sal_Unicode cCh) +{ + return (cCh >= 0x700 && cCh <= 0x74F) || (cCh >= 0x860 && cCh <= 0x86A); +} + +bool isArabicChar(sal_Unicode cCh) { return cCh >= 0x60C && cCh <= 0x6FE; } + std::optional<i18nutil::KashidaPosition> GetWordKashidaPositionArabic(const OUString& rWord, const std::vector<bool>& pValidPositions) { @@ -283,7 +290,7 @@ GetWordKashidaPositionArabic(const OUString& rWord, const std::vector<bool>& pVa { // Reh, Zain (right joining) final form may appear in the middle of word // All others except Yeh - only at end of word - if (isRehChar(cCh) || (0x60C <= cCh && 0x6FE >= cCh && nIdx == nWordLen - 1)) + if (isRehChar(cCh) || (isArabicChar(cCh) && nIdx == nWordLen - 1)) { SAL_WARN_IF(0 == cPrevCh, "i18n", "No previous character"); // check if character is connectable to previous character, @@ -295,7 +302,8 @@ GetWordKashidaPositionArabic(const OUString& rWord, const std::vector<bool>& pVa } // 8. Try any valid position - if (nPriorityLevel >= 7 && nIdx > 0) + if (nPriorityLevel >= 7 && nIdx > 0 && isArabicChar(cPrevCh) && isArabicChar(cCh) + && !pValidPositions.empty()) { fnTryInsertBefore(7); } @@ -339,7 +347,7 @@ GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector<bool>& pVa sal_Int32 nWordMidpoint = nWordLen / 2; - auto fnPositionValid = [&pValidPositions](sal_Int32 nIdx) { + auto fnPositionValid = [&pValidPositions, &rWord](sal_Int32 nIdx) { // Exclusions: // tdf#163105: Do not insert kashida if the position is invalid @@ -348,7 +356,8 @@ GetWordKashidaPositionSyriac(const OUString& rWord, const std::vector<bool>& pVa return false; } - return true; + sal_Unicode cCh = rWord[nIdx]; + return isSyriacChar(cCh); }; // End to midpoint @@ -385,7 +394,7 @@ i18nutil::GetWordKashidaPosition(const OUString& rWord, const std::vector<bool>& { auto cCh = rWord[nIdx]; - if ((cCh >= 0x700 && cCh <= 0x74F) || (cCh >= 0x860 && cCh <= 0x86A)) + if (isSyriacChar(cCh)) { // This word contains Syriac characters. return GetWordKashidaPositionSyriac(rWord, pValidPositions); |