Commit 0d4e1a54 for tesseract
commit 0d4e1a54d812c12eb39bf9d3fd886dff2e613bd0
Author: Stefan Weil <sw@weilnetz.de>
Date: Fri Nov 13 17:30:50 2026 +0100
cutil: fix null pointer dereference for the size of an empty LIST
An empty LIST is NIL_LIST (nullptr). Commit 2fa96b765 replaced the
function count(LIST) by the member function list_rec::size(). Calling
it for an empty list is undefined behaviour: clang removes the test
for a null pointer, and the code crashes. That happened in
PrintAdaptedTemplates() and in WriteAdaptedClass() for an adapted
class without temporary protos, for example at the end of a run with
classify_save_adapted_templates.
Restore the function count(), which handles an empty list.
Fix proposed by the Anthropic OSS Scanner (finding ANT-2026-8AGHSUUG).
Assisted-by: OpenCode / Claude Fable 5.2 (Anthropic)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
diff --git a/src/classify/adaptive.cpp b/src/classify/adaptive.cpp
index c371acad..ca47d703 100644
--- a/src/classify/adaptive.cpp
+++ b/src/classify/adaptive.cpp
@@ -183,7 +183,7 @@ void Classify::PrintAdaptedTemplates(FILE *File, ADAPT_TEMPLATES_STRUCT *Templat
if (!IsEmptyAdaptedClass(AClass)) {
fprintf(File, "%5u %s %3d %3d %3d %3zd\n", i, unicharset.id_to_unichar(i), IClass->NumConfigs,
AClass->NumPermConfigs, IClass->NumProtos,
- IClass->NumProtos - AClass->TempProtos->size());
+ IClass->NumProtos - count(AClass->TempProtos));
}
}
fprintf(File, "\n");
@@ -387,7 +387,7 @@ void WriteAdaptedClass(FILE *File, ADAPT_CLASS_STRUCT *Class, int NumConfigs) {
fwrite(Class->PermConfigs, sizeof(uint32_t), WordsInVectorOfSize(MAX_NUM_CONFIGS), File);
/* then write out the list of temporary protos */
- uint32_t NumTempProtos = Class->TempProtos->size();
+ uint32_t NumTempProtos = count(Class->TempProtos);
fwrite(&NumTempProtos, sizeof(NumTempProtos), 1, File);
auto TempProtos = Class->TempProtos;
iterate(TempProtos) {
diff --git a/src/cutil/oldlist.cpp b/src/cutil/oldlist.cpp
index 583dd4b3..12869f8e 100644
--- a/src/cutil/oldlist.cpp
+++ b/src/cutil/oldlist.cpp
@@ -77,6 +77,17 @@ static int is_same(void *item1, void *item2) {
return strcmp(static_cast<char *>(item1), static_cast<char *>(item2)) == 0;
}
+/**********************************************************************
+ * c o u n t
+ *
+ * Count the elements in a list (0 for NIL_LIST). Return the count.
+ **********************************************************************/
+size_t count(LIST var_list) {
+ size_t n = 0;
+ iterate(var_list) n++;
+ return n;
+}
+
/**********************************************************************
* d e l e t e d
*
diff --git a/src/cutil/oldlist.h b/src/cutil/oldlist.h
index 41ef1d05..f7888a7d 100644
--- a/src/cutil/oldlist.h
+++ b/src/cutil/oldlist.h
@@ -111,16 +111,6 @@ struct list_rec {
list_rec *list_rest() {
return next;
}
-
- //********************************************************************
- // Recursively count the elements in a list. Return the count.
- //********************************************************************
- size_t size() {
- auto var_list = this;
- size_t n = 0;
- iterate(var_list) n++;
- return n;
- }
};
using LIST = list_rec *;
@@ -128,6 +118,8 @@ using LIST = list_rec *;
Public Function Prototypes
----------------------------------------------------------------------*/
+size_t count(LIST var_list);
+
LIST delete_d(LIST list, void *key, int_compare is_equal);
TESS_API