summaryrefslogtreecommitdiff
path: root/i18nutil/source
diff options
context:
space:
mode:
authorJonathan Clark <jonathan@libreoffice.org>2024-10-04 11:50:25 -0600
committerJonathan Clark <jonathan@libreoffice.org>2024-10-05 00:05:05 +0200
commit99c7cf2816b2d0016832552dbe6c55456ade42e0 (patch)
treee55d5c9f05ddbb3e416f63cc59b22c8ac6843bbe /i18nutil/source
parent75f3ee7e8a06ed5fec17c358c62e3efeb8d13e8d (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.cxx19
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);