Commit da03df91 for tesseract
commit da03df91674df117940188f0075c5a614bad53fa
Author: Stefan Weil <sw@weilnetz.de>
Date: Sun Aug 9 15:07:08 2026 +0200
Fix CID 1438664 (Wrapper object use after free)
unichar_string() and unichar_lengths() rebuild their internal
std::string members on every call, so the pointers obtained from
c_str() at the start of one_ell_conflict became dangling as soon
as unichar_string() was called again. Copy the strings into local
variables to keep the pointers valid.
Assisted-by: OpenCode / big-pickle (opencode)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
diff --git a/src/ccmain/reject.cpp b/src/ccmain/reject.cpp
index 6e370f19..f9c8c771 100644
--- a/src/ccmain/reject.cpp
+++ b/src/ccmain/reject.cpp
@@ -285,8 +285,6 @@ void Tesseract::reject_edge_blobs(WERD_RES *word) {
* - A bundle of contextual heuristics!
**********************************************************************/
bool Tesseract::one_ell_conflict(WERD_RES *word_res, bool update_map) {
- const char *word;
- const char *lengths;
int16_t word_len; // its length
int16_t first_alphanum_index_;
int16_t first_alphanum_offset_;
@@ -298,8 +296,12 @@ bool Tesseract::one_ell_conflict(WERD_RES *word_res, bool update_map) {
bool dict_word_ok;
int dict_word_type;
- word = word_res->best_choice->unichar_string().c_str();
- lengths = word_res->best_choice->unichar_lengths().c_str();
+ // unichar_string() and unichar_lengths() rebuild their internal strings,
+ // so copy them here to keep stable pointers for the rest of the function.
+ std::string word_str = word_res->best_choice->unichar_string();
+ std::string lengths_str = word_res->best_choice->unichar_lengths();
+ const char *word = word_str.c_str();
+ const char *lengths = lengths_str.c_str();
word_len = strlen(lengths);
/*
If there are no occurrences of the conflict set characters then the word