Commit afdc743a for tesseract

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

    textord: clamp the trial pitch in compute_pitch_sd

    compute_pitch_sd() fills the cells with a step of
    static_cast<int16_t>(initial_pitch). check_pitch_sync() and
    check_pitch_sync2() clamp their copy of the pitch to at least 3, but
    the caller kept the raw value. With pitsync_linear_version 0 or 1 and
    a large textord_pitch_range, tune_row_pitch() tries pitches below 1.
    The step is 0 then, and the loop allocates cells until the memory is
    used up.

    Apply the same lower bound in compute_pitch_sd(). The default
    (pitsync_linear_version 6) returns via compute_pitch_sd2() before the
    clamp and is not changed.

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

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

diff --git a/src/textord/topitch.cpp b/src/textord/topitch.cpp
index d041ad81..f83abcff 100644
--- a/src/textord/topitch.cpp
+++ b/src/textord/topitch.cpp
@@ -1305,6 +1305,11 @@ float compute_pitch_sd(        // find fp cells
     sp_sd = occupation;
     return word_sync;
   }
+  // check_pitch_sync(2) clamp their copy of the pitch, but the cell filling
+  // loop below steps by initial_pitch and never advances for a pitch below 1.
+  if (initial_pitch < 3) {
+    initial_pitch = 3; // nothing ludicrous
+  }
   mid_cuts = 0;
   cellpos = 0;
   total_count = 0;