Commit 71515c4d for tesseract

commit 71515c4dd2cdcb5be92beeb0dd3ea673b44b3975
Author: Stefan Weil <sw@weilnetz.de>
Date:   Fri Nov 13 17:31:00 2026 +0100

    equationdetect: fix the comparators which are used for std::sort

    SortCPByTopReverse(), SortCPByBottom() and SortCPByHeight() were
    written for qsort: they get pointers to the elements and return an int
    difference. Since commit 1f94d79c8 they are used with std::sort on a
    std::vector<ColPartition *>, which passes the elements themselves and
    expects a bool. Each function therefore used the first field of a
    ColPartition as a pointer to a ColPartition and failed its own
    ASSERT_HOST, so the page segmentation aborted whenever
    textord_equation_detect was set and two text partitions had to be
    sorted.

    Take ColPartition pointers and return the result of a strict
    comparison which gives the same order as before.

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

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

diff --git a/src/ccmain/equationdetect.cpp b/src/ccmain/equationdetect.cpp
index 6cfa5dcf..772377ce 100644
--- a/src/ccmain/equationdetect.cpp
+++ b/src/ccmain/equationdetect.cpp
@@ -50,28 +50,24 @@ static BOOL_VAR(equationdetect_save_merged_image, false, "Save the merged image"
 ///////////////////////////////////////////////////////////////////////////
 // Utility ColPartition sort functions.
 ///////////////////////////////////////////////////////////////////////////
-static int SortCPByTopReverse(const void *p1, const void *p2) {
-  const ColPartition *cp1 = *static_cast<ColPartition *const *>(p1);
-  const ColPartition *cp2 = *static_cast<ColPartition *const *>(p2);
+// These are std::sort comparators: they receive the ColPartition pointers
+// held in the vector, not pointers to the elements as qsort would pass.
+static bool SortCPByTopReverse(const ColPartition *cp1, const ColPartition *cp2) {
   ASSERT_HOST(cp1 != nullptr && cp2 != nullptr);
   const TBOX &box1(cp1->bounding_box()), &box2(cp2->bounding_box());
-  return box2.top() - box1.top();
+  return box1.top() > box2.top();
 }

-static int SortCPByBottom(const void *p1, const void *p2) {
-  const ColPartition *cp1 = *static_cast<ColPartition *const *>(p1);
-  const ColPartition *cp2 = *static_cast<ColPartition *const *>(p2);
+static bool SortCPByBottom(const ColPartition *cp1, const ColPartition *cp2) {
   ASSERT_HOST(cp1 != nullptr && cp2 != nullptr);
   const TBOX &box1(cp1->bounding_box()), &box2(cp2->bounding_box());
-  return box1.bottom() - box2.bottom();
+  return box1.bottom() < box2.bottom();
 }

-static int SortCPByHeight(const void *p1, const void *p2) {
-  const ColPartition *cp1 = *static_cast<ColPartition *const *>(p1);
-  const ColPartition *cp2 = *static_cast<ColPartition *const *>(p2);
+static bool SortCPByHeight(const ColPartition *cp1, const ColPartition *cp2) {
   ASSERT_HOST(cp1 != nullptr && cp2 != nullptr);
   const TBOX &box1(cp1->bounding_box()), &box2(cp2->bounding_box());
-  return box1.height() - box2.height();
+  return box1.height() < box2.height();
 }

 // TODO(joeliu): we may want to parameterize these constants.