Commit 2793a90a for tesseract

commit 2793a90a7349e4990edd9b96e35a26d0d4f1df17
Author: Stefan Weil <sw@weilnetz.de>
Date:   Sun Aug 9 15:15:31 2026 +0200

    Fix CID 1660581 (Overflowed return value)

    CPrunerMaskFor could shift a level value larger than the two bits
    available per class in the class pruner word when classify_num_cp_levels
    was raised above its default. Clamp the value to CLASS_PRUNER_CLASS_MASK.

    Assisted-by: OpenCode / big-pickle (opencode)
    Signed-off-by: Stefan Weil <sw@weilnetz.de>

diff --git a/src/classify/intproto.h b/src/classify/intproto.h
index a38d6fe0..5365bee3 100644
--- a/src/classify/intproto.h
+++ b/src/classify/intproto.h
@@ -166,7 +166,11 @@ inline constexpr CLASS_PRUNER_STRUCT *CPrunerFor(INT_TEMPLATES_STRUCT *T, int c)
 inline constexpr int CPrunerWordIndexFor(int c) { return (c % CLASSES_PER_CP) / CLASSES_PER_CP_WERD; }
 inline constexpr int CPrunerBitIndexFor(int c) { return (c % CLASSES_PER_CP) % CLASSES_PER_CP_WERD; }
 inline constexpr uint32_t CPrunerMaskFor(int L, int c) {
-  return (static_cast<uint32_t>(L) + 1) << (CPrunerBitIndexFor(c) * NUM_BITS_PER_CLASS);
+  // The class pruner stores only NUM_BITS_PER_CLASS bits per class,
+  // so clamp the level to the maximum value that fits in the field.
+  const uint32_t value = static_cast<uint32_t>(L) + 1;
+  return (value > CLASS_PRUNER_CLASS_MASK ? CLASS_PRUNER_CLASS_MASK : value)
+         << (CPrunerBitIndexFor(c) * NUM_BITS_PER_CLASS);
 }

 /* DEBUG constants */