Commit 28e7e676 for tesseract

commit 28e7e6768dcc9b292a2dc6baf0e871d05665c161
Author: Stefan Weil <sw@weilnetz.de>
Date:   Fri Nov 13 17:30:08 2026 +0100

    textord: avoid divisions by zero for three integer parameters

    textord_noise_sizefraction, edges_children_per_grandchild and
    textord_spline_medianwin are used as divisors without any check, so a
    value of 0 from a config file ended the process with SIGFPE.
    textord_spline_medianwin is also used as the size of a median window,
    and a value below 1 caused a read out of bounds in segment_baseline().

    - clean_noise_from_row() and clean_noise_from_words() use the blob
      size as the threshold if textord_noise_sizefraction is not positive.
    - OL_BUCKETS::count_children() counts no grandchildren if
      edges_children_per_grandchild is not positive.
    - segment_baseline() falls back to a straight baseline if
      textord_spline_medianwin is not positive.

    Nothing changes for positive values.

    This is not a complete fix for all parameters: there are more
    parameters which are used as divisors in floating point calculations
    without a check.

    Fix proposed by the Anthropic OSS Scanner (finding ANT-2026-I7UIR1ID).

    Assisted-by: OpenCode / Claude Fable 5.2 (Anthropic)
    Signed-off-by: Stefan Weil <sw@weilnetz.de>

diff --git a/src/textord/edgblob.cpp b/src/textord/edgblob.cpp
index e9a327e0..8d7b2fa4 100644
--- a/src/textord/edgblob.cpp
+++ b/src/textord/edgblob.cpp
@@ -231,8 +231,12 @@ int32_t OL_BUCKETS::count_children( // recursive count
         if (child != outline && *child < *outline) {
           child_count++;
           if (child_count <= max_count) {
+            // Avoid an integer division by zero if the parameter is not
+            // positive.
             int max_grand =
-                (max_count - child_count) / edges_children_per_grandchild;
+                edges_children_per_grandchild > 0
+                    ? (max_count - child_count) / edges_children_per_grandchild
+                    : 0;
             if (max_grand > 0) {
               grandchild_count += count_children(child, max_grand) *
                                   edges_children_per_grandchild;
diff --git a/src/textord/makerow.cpp b/src/textord/makerow.cpp
index 692c646e..d5d98022 100644
--- a/src/textord/makerow.cpp
+++ b/src/textord/makerow.cpp
@@ -2103,7 +2103,10 @@ bool segment_baseline( // split baseline
   if (textord_oldbl_debug) {
     tprintf("Segmenting baseline of %d blobs at (%d,%d)\n", blobcount, box.left(), box.bottom());
   }
-  if (blobcount <= textord_spline_medianwin || blobcount < textord_spline_minblobs) {
+  // A window size which is not positive cannot be used for the median below
+  // nor as a divisor in linear_spline_baseline.
+  if (textord_spline_medianwin < 1 || blobcount <= textord_spline_medianwin ||
+      blobcount < textord_spline_minblobs) {
     blob_it.move_to_last();
     box = blob_it.data()->bounding_box();
     xstarts[1] = box.right();
diff --git a/src/textord/tordmain.cpp b/src/textord/tordmain.cpp
index e59528da..69222cca 100644
--- a/src/textord/tordmain.cpp
+++ b/src/textord/tordmain.cpp
@@ -515,7 +515,9 @@ bool Textord::clean_noise_from_row( // remove empties
       blob_size = blob_box.width() > blob_box.height() ? blob_box.width() : blob_box.height();
       if (blob_size >= textord_noise_sizelimit * row->x_height() &&
           blob_size < row->x_height() * 2) {
-        trans_threshold = blob_size / textord_noise_sizefraction;
+        // Avoid an integer division by zero if the parameter is not positive.
+        trans_threshold = textord_noise_sizefraction > 0 ? blob_size / textord_noise_sizefraction
+                                                         : blob_size;
         trans_count = blob->count_transitions(trans_threshold);
         if (trans_count < textord_noise_translimit) {
           norm_count++;
@@ -612,7 +614,9 @@ void Textord::clean_noise_from_words( // remove empties
       blob_size = blob_box.width() > blob_box.height() ? blob_box.width() : blob_box.height();
       if (blob_size >= textord_noise_sizelimit * row->x_height() &&
           blob_size < row->x_height() * 2) {
-        trans_threshold = blob_size / textord_noise_sizefraction;
+        // Avoid an integer division by zero if the parameter is not positive.
+        trans_threshold = textord_noise_sizefraction > 0 ? blob_size / textord_noise_sizefraction
+                                                         : blob_size;
         trans_count = blob->count_transitions(trans_threshold);
         if (trans_count < textord_noise_translimit) {
           norm_count++;