diff --git a/tesseract.spec b/tesseract.spec index 0439cf9..13e6841 100644 --- a/tesseract.spec +++ b/tesseract.spec @@ -2,7 +2,7 @@ Name: tesseract Version: 4.1.1 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Raw OCR Engine License: ASL 2.0 @@ -13,6 +13,8 @@ Source1: https://github.com/tesseract-ocr/tessdata/archive/%{tessdata_vers # Tweak location of tessdata folder Patch0: tesseract_datadir.patch +Patch1: upstream_2f4d2f4bf45c363785d7bf1da29b6628f8939a72.patch + BuildRequires: gcc-c++ BuildRequires: make BuildRequires: libtiff-devel @@ -267,6 +269,7 @@ trained models for the Tesseract Open Source OCR Engine.\ %prep %setup -q -n %{name}-%{version} -a1 %patch0 -p1 +%patch1 -p1 %build @@ -332,6 +335,9 @@ cp -av tessdata-%{tessdata_version}/* %{buildroot}%{_datadir}/%{name}/tessdata %changelog +* Tue Aug 25 2026 Pavol Sloboda - 4.1.1-3 +- Resolves: CVE-2026-73066 + * Fri Aug 06 2021 Jiri Kucera - 4.1.1-2 - Fix subpackages deps Related: #1826085 diff --git a/upstream_2f4d2f4bf45c363785d7bf1da29b6628f8939a72.patch b/upstream_2f4d2f4bf45c363785d7bf1da29b6628f8939a72.patch new file mode 100644 index 0000000..4ad66d1 --- /dev/null +++ b/upstream_2f4d2f4bf45c363785d7bf1da29b6628f8939a72.patch @@ -0,0 +1,141 @@ +From 2f4d2f4bf45c363785d7bf1da29b6628f8939a72 Mon Sep 17 00:00:00 2001 +From: Stefan Weil +Date: Thu, 23 Jul 2026 18:05:39 +0200 +Subject: [PATCH] Fix integer overflow in LSTM Convolve and Reconfig + deserialization (#4588) + +Add range and overflow validation in Convolve::DeSerialize and +Reconfig::DeSerialize to prevent a crafted .traineddata file from +triggering a heap out-of-bounds write via unchecked signed integer +multiplication when computing the output-channel count. + +Validate ni/no/num_weights in Network::CreateFromFile. + +Add defense-in-depth bounds assertions in NetworkIO::Randomize and +NetworkIO::CopyTimeStepGeneral. + +Reported-by: Eunho Kim +Signed-off-by: Stefan Weil +Assisted-by: OpenCode / big-pickle (opencode) +Tested-by: Eunho Kim +--- + src/lstm/convolve.cpp | 24 +++++++++++++++++++++++- + src/lstm/network.cpp | 6 ++++++ + src/lstm/networkio.cpp | 2 ++ + src/lstm/reconfig.cpp | 20 +++++++++++++++++++- + 4 files changed, 50 insertions(+), 2 deletions(-) + +diff -Naur tesseract-4.1.1/src/lstm/convolve.cpp tesseract-4.1.1_patched/src/lstm/convolve.cpp +--- tesseract-4.1.1/src/lstm/convolve.cpp 2019-12-26 15:21:51.000000000 +0100 ++++ tesseract-4.1.1_patched/src/lstm/convolve.cpp 2026-08-25 14:47:24.313114215 +0200 +@@ -20,8 +20,11 @@ + + #include "convolve.h" + ++#include ++ + #include "networkscratch.h" + #include "serialis.h" ++#include "tprintf.h" + + namespace tesseract { + +@@ -41,7 +44,26 @@ + bool Convolve::DeSerialize(TFile* fp) { + if (!fp->DeSerialize(&half_x_)) return false; + if (!fp->DeSerialize(&half_y_)) return false; +- no_ = ni_ * (2*half_x_ + 1) * (2*half_y_ + 1); ++ if (half_x_ < 0 || half_y_ < 0 || ni_ <= 0) { ++ tprintf("Error: invalid Convolve parameters: ni=%d half_x=%d half_y=%d\n", ni_, half_x_, ++ half_y_); ++ return false; ++ } ++ int64_t kx = 2LL * half_x_ + 1; ++ int64_t ky = 2LL * half_y_ + 1; ++ // Stepwise overflow check: ni_ * kx * ky must fit in int. ++ if (kx > INT_MAX / ky) { ++ tprintf("Error: Convolve output-channel count overflows: ni=%d half_x=%d half_y=%d\n", ni_, ++ half_x_, half_y_); ++ return false; ++ } ++ int64_t kxky = kx * ky; ++ if (static_cast(ni_) > INT_MAX / kxky) { ++ tprintf("Error: Convolve output-channel count overflows: ni=%d half_x=%d half_y=%d\n", ni_, ++ half_x_, half_y_); ++ return false; ++ } ++ no_ = static_cast(static_cast(ni_) * kxky); + return true; + } + +diff -Naur tesseract-4.1.1/src/lstm/network.cpp tesseract-4.1.1_patched/src/lstm/network.cpp +--- tesseract-4.1.1/src/lstm/network.cpp 2019-12-26 15:21:51.000000000 +0100 ++++ tesseract-4.1.1_patched/src/lstm/network.cpp 2026-08-25 14:54:20.292420396 +0200 +@@ -205,6 +205,11 @@ + if (!fp->DeSerialize(&no)) return nullptr; + if (!fp->DeSerialize(&num_weights)) return nullptr; + if (!name.DeSerialize(fp)) return nullptr; ++ if (ni < 0 || no < 0 || num_weights < 0) { ++ tprintf("Error: invalid network layer parameters: type=%d ni=%d no=%d num_weights=%d\n", type, ++ ni, no, num_weights); ++ return nullptr; ++ } + + switch (type) { + case NT_CONVOLVE: +diff -Naur tesseract-4.1.1/src/lstm/networkio.cpp tesseract-4.1.1_patched/src/lstm/networkio.cpp +--- tesseract-4.1.1/src/lstm/networkio.cpp 2019-12-26 15:21:51.000000000 +0100 ++++ tesseract-4.1.1_patched/src/lstm/networkio.cpp 2026-08-25 14:56:16.484956294 +0200 +@@ -394,6 +394,7 @@ + int num_features, const NetworkIO& src, + int src_t, int src_offset) { + ASSERT_HOST(int_mode_ == src.int_mode_); ++ ASSERT_HOST(dest_offset + num_features <= NumFeatures()); + if (int_mode_) { + memcpy(i_[dest_t] + dest_offset, src.i_[src_t] + src_offset, + num_features * sizeof(i_[0][0])); +@@ -415,6 +416,7 @@ + // Sets the given range to random values. + void NetworkIO::Randomize(int t, int offset, int num_features, + TRand* randomizer) { ++ ASSERT_HOST(offset + num_features <= NumFeatures()); + if (int_mode_) { + int8_t* line = i_[t] + offset; + for (int i = 0; i < num_features; ++i) +diff -Naur tesseract-4.1.1/src/lstm/reconfig.cpp tesseract-4.1.1_patched/src/lstm/reconfig.cpp +--- tesseract-4.1.1/src/lstm/reconfig.cpp 2019-12-26 15:21:51.000000000 +0100 ++++ tesseract-4.1.1_patched/src/lstm/reconfig.cpp 2026-08-25 14:58:17.673474891 +0200 +@@ -18,6 +18,10 @@ + + #include "reconfig.h" + ++#include ++ ++#include "tprintf.h" ++ + namespace tesseract { + + Reconfig::Reconfig(const STRING& name, int ni, int x_scale, int y_scale) +@@ -57,7 +61,21 @@ + bool Reconfig::DeSerialize(TFile* fp) { + if (!fp->DeSerialize(&x_scale_)) return false; + if (!fp->DeSerialize(&y_scale_)) return false; +- no_ = ni_ * x_scale_ * y_scale_; ++ if (x_scale_ <= 0 || y_scale_ <= 0 || ni_ <= 0) { ++ tprintf("Error: invalid Reconfig parameters: ni=%d x_scale=%d y_scale=%d\n", ni_, x_scale_, ++ y_scale_); ++ return false; ++ } ++ int64_t xs = x_scale_; ++ int64_t ys = y_scale_; ++ // Stepwise overflow check: ni_ * x_scale_ * y_scale_ must fit in int. ++ int64_t xsys = xs * ys; ++ if (static_cast(ni_) > INT_MAX / xsys) { ++ tprintf("Error: Reconfig output-channel count overflows: ni=%d x_scale=%d y_scale=%d\n", ni_, ++ x_scale_, y_scale_); ++ return false; ++ } ++ no_ = static_cast(static_cast(ni_) * xsys); + return true; + } +