This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository e16.

View the commit online.

commit 46691a336bf69ffb9fb1ab6dcef9313124462dd6
Author: Kim Woelders <k...@woelders.dk>
AuthorDate: Wed Jul 23 20:16:13 2025 +0200

    text: Avoid lockup (endless loop) in TextFit functions
    
    Commit 4f617c77bfed9221b8ccab527839ae3742746054 "text: Converge faster
    in TextFit functions" introduced the possibility of triggering an
    endless loop when dealing with strings containing glyphs with very
    different widths.
    
    The new algoritm may be a bit slower or faster or less accurate
    depending on the particlar string, but should never lock up.
    
    Reported by Thanatermesis.
---
 src/text.c | 46 ++++++++++++++--------------------------------
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/src/text.c b/src/text.c
index da1e4d35..6522d1ca 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
- * Copyright (C) 2004-2023 Kim Woelders
+ * Copyright (C) 2004-2025 Kim Woelders
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -237,9 +237,9 @@ static void
 TextstateTextFit1(TextState *ts, char **ptext, int *pw, int textwidth_limit)
 {
     char           *text = *ptext;
-    int             width, hh, ascent;
+    int             width, hh, ascent, dw;
     char           *new_line;
-    int             nuke_count, nc2, len_n, cw;
+    int             i, nuke_count, nc2;
     int             len;
 
     len = strlen(text);
@@ -251,11 +251,9 @@ TextstateTextFit1(TextState *ts, char **ptext, int *pw, int textwidth_limit)
         return;
 
     width = *pw;
-    nuke_count = ((width - textwidth_limit) * len) / width;
-    if (nuke_count < 2)
-        nuke_count = 2;
+    nuke_count = ((width - textwidth_limit) * len) / width + 3;
 
-    for (;;)
+    for (i = 0; i < 10; i++, nuke_count++)
     {
         if (nuke_count >= len - 1)
         {
@@ -269,20 +267,13 @@ TextstateTextFit1(TextState *ts, char **ptext, int *pw, int textwidth_limit)
         memcpy(new_line, text, nc2);
         memcpy(new_line + nc2, "...", 3);
         strcpy(new_line + nc2 + 3, text + nc2 + nuke_count);
-        len_n = len - nuke_count + 3;
 
         ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent);
 
         width = *pw;
-        nc2 = textwidth_limit - width;
-        cw = width / len_n;
-
-        if (nc2 >= 0 && nc2 < 3 * cw)
+        dw = textwidth_limit - width;
+        if (dw >= 0)
             break;
-        if (nc2 > 0)
-            nuke_count -= (nc2 <= 2 * cw) ? 1 : (nc2 + cw / 2) / cw;
-        else
-            nuke_count += (-nc2 <= 2 * cw) ? 1 : (-nc2 + cw / 2) / cw;
     }
 
     Efree(text);
@@ -293,12 +284,12 @@ static void
 TextstateTextFitMB(TextState *ts, char **ptext, int *pw, int textwidth_limit)
 {
     char           *text = *ptext;
-    int             width, hh, ascent, cw;
+    int             width, hh, ascent, dw;
     char           *new_line;
-    int             nuke_count, nc2;
+    int             i, nuke_count, nc2;
     int             len, len_mb;
     wchar_t        *wc_line = NULL;
-    int             wc_len, len_n;
+    int             wc_len;
 
     if (EwcOpen(ts->need_utf8 || Mode.locale.utf8_int))
         return;
@@ -320,11 +311,9 @@ TextstateTextFitMB(TextState *ts, char **ptext, int *pw, int textwidth_limit)
         goto done;
 
     width = *pw;
-    nuke_count = ((width - textwidth_limit) * wc_len) / width;
-    if (nuke_count < 2)
-        nuke_count = 2;
+    nuke_count = ((width - textwidth_limit) * wc_len) / width + 3;
 
-    for (;;)
+    for (i = 0; i < 10; i++, nuke_count++)
     {
         if (nuke_count >= wc_len - 1)
         {
@@ -345,20 +334,13 @@ TextstateTextFitMB(TextState *ts, char **ptext, int *pw, int textwidth_limit)
                               wc_len - nc2 - nuke_count,
                               new_line + len_mb, len + 10 - len_mb);
         new_line[len_mb] = '\0';
-        len_n = wc_len - nuke_count + 3;
 
         ts->ops->TextSize(ts, new_line, 0, pw, &hh, &ascent);
 
         width = *pw;
-        nc2 = textwidth_limit - width;
-        cw = width / len_n;
-
-        if (nc2 >= 0 && nc2 < 3 * cw)
+        dw = textwidth_limit - width;
+        if (dw >= 0)
             break;
-        if (nc2 > 0)
-            nuke_count -= (nc2 <= 2 * cw) ? 1 : (nc2 + cw / 2) / cw;
-        else
-            nuke_count += (-nc2 <= 2 * cw) ? 1 : (-nc2 + cw / 2) / cw;
     }
 
     Efree(text);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to