From a04969affec3486045cfc954bda59d1a3217e319 Mon Sep 17 00:00:00 2001
From: Alexander Golubev <fatzer2@gmail.com>
Date: Wed, 18 Mar 2026 13:35:30 +0300
Subject: Fix infinite looping in TQTextEngine::shape()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With certain characters a loop inside TQTextEngine::shape() could
repeat forever because some script engines were requesting more memory
because of a mistake.

In particular this were observed with at least letters "ई" (U+0908,
DEVANAGARI LETTER II) and "ༀ" (U+0F00, TIBETAN SYLLABLE OM).

The problem was already solved in Qt somewhere between last Qt3 release
and first Qt4. But due to no public VCS is available it's impossible to
pinpoint an exact commit. This patch is heavily based on the Qt-4.3.5
code.

Closes: https://mirror.git.trinitydesktop.org/gitea/TDE/tqt/issues/270
Bug: https://mirror.git.trinitydesktop.org/gitea/TDE/tdeutils/issues/93
Signed-off-by: Alexander Golubev <fatzer2@gmail.com>
---
 src/kernel/tqfontengine_p.h       |  2 +-
 src/kernel/tqfontengine_x11.cpp   |  4 ++--
 src/kernel/tqscriptengine.cpp     |  6 +++---
 src/kernel/tqscriptengine_x11.cpp | 28 ++++++++++++++++++++++------
 4 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/src/kernel/tqfontengine_p.h b/src/kernel/tqfontengine_p.h
index e7d7f2162..52bc66d7c 100644
--- a/src/kernel/tqfontengine_p.h
+++ b/src/kernel/tqfontengine_p.h
@@ -434,7 +434,7 @@ public:
     void selectScript(unsigned int script, const Features *features = 0);
 
     bool shape(TQShaperItem *item, const unsigned int *properties = 0);
-    bool positionAndAdd(TQShaperItem *item, bool doLogClusters = true);
+    bool positionAndAdd(TQShaperItem *item, int availableGlyphs, bool doLogClusters = true);
 
     OTL_GlyphItem glyphs() const { return otl_buffer->in_string; }
     int len() const { return otl_buffer->in_length; }
diff --git a/src/kernel/tqfontengine_x11.cpp b/src/kernel/tqfontengine_x11.cpp
index 1a7b95ebb..7f514f914 100644
--- a/src/kernel/tqfontengine_x11.cpp
+++ b/src/kernel/tqfontengine_x11.cpp
@@ -2428,7 +2428,7 @@ bool TQOpenType::shape(TQShaperItem *item, const unsigned int *properties)
     return true;
 }
 
-bool TQOpenType::positionAndAdd(TQShaperItem *item, bool doLogClusters)
+bool TQOpenType::positionAndAdd(TQShaperItem *item, int availableGlyphs, bool doLogClusters)
 {
     if (gpos) {
 #ifdef TQ_WS_X11
@@ -2444,7 +2444,7 @@ bool TQOpenType::positionAndAdd(TQShaperItem *item, bool doLogClusters)
     }
 
     // make sure we have enough space to write everything back
-    if (item->num_glyphs < (int)otl_buffer->in_length) {
+    if (availableGlyphs < (int)otl_buffer->in_length) {
         item->num_glyphs = otl_buffer->in_length;
         return false;
     }
diff --git a/src/kernel/tqscriptengine.cpp b/src/kernel/tqscriptengine.cpp
index e9431463c..8c8fbe308 100644
--- a/src/kernel/tqscriptengine.cpp
+++ b/src/kernel/tqscriptengine.cpp
@@ -434,13 +434,14 @@ static bool hebrew_shape(TQShaperItem *item)
     if (openType && openType->supportsScript(item->script)) {
         openType->selectScript(item->script, hebrew_features);
 
+        const int availableGlyphs = item->num_glyphs;
         if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances,
                                      &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
             return false;
 
         heuristicSetGlyphAttributes(item);
         openType->shape(item);
-        return openType->positionAndAdd(item);
+        return openType->positionAndAdd(item, availableGlyphs);
     }
 #endif
 
@@ -1580,8 +1581,7 @@ static bool arabicSyriacOpenTypeShape(TQOpenType *openType, TQShaperItem *item,
         *ot_ok = false;
         return false;
     }
-    item->num_glyphs = nglyphs;
-    return openType->positionAndAdd(item);
+    return openType->positionAndAdd(item, nglyphs);
 }
 
 #endif
diff --git a/src/kernel/tqscriptengine_x11.cpp b/src/kernel/tqscriptengine_x11.cpp
index 6d5429cb0..c54f6d6b1 100644
--- a/src/kernel/tqscriptengine_x11.cpp
+++ b/src/kernel/tqscriptengine_x11.cpp
@@ -69,12 +69,13 @@ static bool thaana_shape(TQShaperItem *item)
 
     if (openType && openType->supportsScript(item->script)) {
         openType->selectScript(TQFont::Thaana);
+        const int availableGlyphs = item->num_glyphs;
         if (item->font->stringToCMap(item->string->unicode()+item->from, item->length, item->glyphs, item->advances,
                                      &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
             return false;
         heuristicSetGlyphAttributes(item);
         openType->shape(item);
-        return openType->positionAndAdd(item);
+        return openType->positionAndAdd(item, availableGlyphs);
     }
 #endif
     return basic_shape(item);
@@ -1550,6 +1551,9 @@ static bool indic_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool
                 reph = i;
     }
 
+#ifndef TQT_NO_XFTFREETYPE
+    const int availableGlyphs = item->num_glyphs;
+#endif
     if (item->font->stringToCMap((const TQChar *)reordered.data(), len, item->glyphs, item->advances,
                                  &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
         return false;
@@ -1694,7 +1698,7 @@ static bool indic_shape_syllable(TQOpenType *openType, TQShaperItem *item, bool
             }
         }
 
-        if (!openType->positionAndAdd(item, false))
+        if (!openType->positionAndAdd(item, availableGlyphs, false))
             return false;
 
         if (control) {
@@ -2056,6 +2060,9 @@ static bool tibetan_shape_syllable(TQOpenType *openType, TQShaperItem *item, boo
         str = (TQChar *)reordered.data();
     }
 
+#ifndef TQT_NO_XFTFREETYPE
+    const int availableGlyphs = item->num_glyphs;
+#endif
     if (item->font->stringToCMap(str, len, item->glyphs, item->advances,
                                  &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
         return false;
@@ -2075,7 +2082,7 @@ static bool tibetan_shape_syllable(TQOpenType *openType, TQShaperItem *item, boo
         openType->selectScript(TQFont::Tibetan, tibetan_features);
 
         openType->shape(item);
-        if (!openType->positionAndAdd(item, false))
+        if (!openType->positionAndAdd(item, availableGlyphs, false))
             return false;
     }
 #endif
@@ -2708,6 +2715,9 @@ static bool khmer_shape_syllable(TQOpenType *openType, TQShaperItem *item)
         } // switch
     } // for
 
+#ifndef TQT_NO_XFTFREETYPE
+    const int availableGlyphs = item->num_glyphs;
+#endif
     if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances,
                                  &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
         return false;
@@ -2745,7 +2755,7 @@ static bool khmer_shape_syllable(TQOpenType *openType, TQShaperItem *item)
         }
 
         openType->shape(item, where);
-        if (!openType->positionAndAdd(item, false))
+        if (!openType->positionAndAdd(item, availableGlyphs, false))
             return false;
     } else
 #endif
@@ -3215,6 +3225,9 @@ static bool myanmar_shape_syllable(TQOpenType *openType, TQShaperItem *item, boo
         len += 2;
     }
 
+#ifndef TQT_NO_XFTFREETYPE
+    const int availableGlyphs = item->num_glyphs;
+#endif
     if (item->font->stringToCMap((const TQChar *)reordered, len, item->glyphs, item->advances,
                                  &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
         return false;
@@ -3252,7 +3265,7 @@ static bool myanmar_shape_syllable(TQOpenType *openType, TQShaperItem *item, boo
         }
 
         openType->shape(item, where);
-        if (!openType->positionAndAdd(item, false))
+        if (!openType->positionAndAdd(item, availableGlyphs, false))
             return false;
     } else
 #endif
@@ -3499,6 +3512,9 @@ static bool hangul_shape_syllable(TQOpenType *openType, TQShaperItem *item)
         len = 1;
     }
 
+#ifndef TQT_NO_XFTFREETYPE
+    const int availableGlyphs = item->num_glyphs;
+#endif
     if (item->font->stringToCMap(ch, len, item->glyphs, item->advances,
                                  &item->num_glyphs, item->flags & TQTextEngine::RightToLeft) != TQFontEngine::NoError)
         return false;
@@ -3519,7 +3535,7 @@ static bool hangul_shape_syllable(TQOpenType *openType, TQShaperItem *item)
         item->log_clusters = logClusters.data();
 
         openType->shape(item);
-        if (!openType->positionAndAdd(item, false))
+        if (!openType->positionAndAdd(item, availableGlyphs, false))
             return false;
 
     }
-- 
cgit v1.2.3

