From: ankur.tyagi85@gmail.com
To: openembedded-devel@lists.openembedded.org
Cc: Ankur Tyagi <ankur.tyagi85@gmail.com>
Subject: [oe][meta-oe][wrynose][PATCH 21/24] tesseract: patch CVE-2026-88051
Date: Thu, 24 Sep 2026 16:33:11 +1200 [thread overview]
Message-ID: <20260924043315.1663186-21-ankur.tyagi85@gmail.com> (raw)
In-Reply-To: <20260924043315.1663186-1-ankur.tyagi85@gmail.com>
From: Ankur Tyagi <ankur.tyagi85@gmail.com>
Details:
https://nvd.nist.gov/vuln/detail/cve-2026-88051
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
.../tesseract/tesseract/CVE-2026-88051.patch | 185 ++++++++++++++++++
.../tesseract/tesseract_5.5.2.bb | 1 +
2 files changed, 186 insertions(+)
create mode 100644 meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88051.patch
diff --git a/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88051.patch b/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88051.patch
new file mode 100644
index 0000000000..efc204dc04
--- /dev/null
+++ b/meta-oe/recipes-graphics/tesseract/tesseract/CVE-2026-88051.patch
@@ -0,0 +1,185 @@
+From 0ad773414bcb9a4f41e7d86759353d9558ba8cbe Mon Sep 17 00:00:00 2001
+From: Stefan Weil <sw@weilnetz.de>
+Date: Fri, 21 Aug 2026 20:29:37 +0200
+Subject: [PATCH] Validate vector counts in GenericVector::read
+
+The callback form of GenericVector::read read two independent int32
+fields from the file: reserved sized the allocation via reserve(),
+while size_used_ drove the element loop. Neither was capped and no
+size_used_ <= reserved invariant was checked, so a crafted
+.traineddata (e.g. the fontinfo table of a version >= 4 inttemp
+component) performed a heap out-of-bounds write during legacy
+engine initialization.
+
+Key changes:
+- genericvector.h: reject negative or over-limit reserved
+ (matching the 50000000 cap of the DeSerialize overloads) and
+ reject size_used_ < 0 or size_used_ > reserved before entering
+ the read loop. Legit files always satisfy size_used_ <= reserved,
+ as write() persists size_reserved_ first.
+- unittest: add genericvector_test covering size_used_ beyond
+ reserved (on unpatched code the ASan build dies on a
+ heap-buffer-overflow in the read loop), negative counts, and a
+ consistent vector that must still load.
+
+Reported-by: Zhixi "Jace" Sun <g.mygenie@gmail.com>
+Assisted-by: OpenCode / qwen3.8-27b-thinking (Alibaba Cloud)
+Signed-off-by: Stefan Weil <sw@weilnetz.de>
+(cherry picked from commit 56e09ca12e751623fe796ce1554ce704bffd2ef0)
+
+CVE: CVE-2026-88051
+Upstream-Status: Backport [https://github.com/tesseract-ocr/tesseract/commit/56e09ca12e751623fe796ce1554ce704bffd2ef0]
+
+Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
+---
+ Makefile.am | 5 ++
+ src/ccutil/genericvector.h | 10 ++++
+ unittest/genericvector_test.cc | 91 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 106 insertions(+)
+ create mode 100644 unittest/genericvector_test.cc
+
+diff --git a/Makefile.am b/Makefile.am
+index 48e7dcbc..d2b503d4 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1188,6 +1188,7 @@ check_PROGRAMS += equationdetect_test
+ endif # !DISABLED_LEGACY_ENGINE
+ check_PROGRAMS += fileio_test
+ check_PROGRAMS += fullyconnected_test
++check_PROGRAMS += genericvector_test
+ check_PROGRAMS += heap_test
+ check_PROGRAMS += imagedata_test
+ if !DISABLED_LEGACY_ENGINE
+@@ -1327,6 +1328,10 @@ fullyconnected_test_SOURCES = unittest/fullyconnected_test.cc
+ fullyconnected_test_CPPFLAGS = $(unittest_CPPFLAGS)
+ fullyconnected_test_LDADD = $(TESS_LIBS)
+
++genericvector_test_SOURCES = unittest/genericvector_test.cc
++genericvector_test_CPPFLAGS = $(unittest_CPPFLAGS)
++genericvector_test_LDADD = $(TESS_LIBS)
++
+ heap_test_SOURCES = unittest/heap_test.cc
+ heap_test_CPPFLAGS = $(unittest_CPPFLAGS)
+ heap_test_LDADD = $(TESS_LIBS)
+diff --git a/src/ccutil/genericvector.h b/src/ccutil/genericvector.h
+index 4a5bbe12..cbe1e203 100644
+--- a/src/ccutil/genericvector.h
++++ b/src/ccutil/genericvector.h
+@@ -654,10 +654,20 @@ bool GenericVector<T>::read(TFile *f, const std::function<bool(TFile *, T *)> &c
+ if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
+ return false;
+ }
++ // Arbitrarily limit the number of elements to protect against bad data.
++ const uint32_t limit = 50000000;
++ if (reserved < 0 || static_cast<uint32_t>(reserved) > limit) {
++ return false;
++ }
+ reserve(reserved);
+ if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) {
+ return false;
+ }
++ // size_used_ is an independent file field; without this check the reads
++ // below land past the end of the buffer sized from reserved.
++ if (size_used_ < 0 || size_used_ > reserved) {
++ return false;
++ }
+ if (cb != nullptr) {
+ for (int i = 0; i < size_used_; ++i) {
+ if (!cb(f, data_ + i)) {
+diff --git a/unittest/genericvector_test.cc b/unittest/genericvector_test.cc
+new file mode 100644
+index 00000000..269b00f0
+--- /dev/null
++++ b/unittest/genericvector_test.cc
+@@ -0,0 +1,91 @@
++///////////////////////////////////////////////////////////////////////
++// File: genericvector_test.cc
++// Description: Tests that the callback form of GenericVector::read
++// rejects vectors whose size_used_ exceeds reserved (or
++// whose counts are negative). reserved sizes the buffer
++// while size_used_ is an independent file field driving
++// the element loop, so a crafted .traineddata (e.g. the
++// fontinfo table of a version >= 4 inttemp component)
++// performs a heap out-of-bounds write during legacy
++// engine initialization.
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++///////////////////////////////////////////////////////////////////////
++
++#include "include_gunit.h"
++
++#include "genericvector.h"
++#include "serialis.h" // for TFile
++
++#include <cstdint>
++#include <vector>
++
++namespace tesseract {
++namespace {
++
++// Appends raw little-endian values to a byte buffer.
++class ByteWriter {
++public:
++ void PutS32(int32_t v) {
++ uint32_t u = static_cast<uint32_t>(v);
++ for (int i = 0; i < 4; ++i) {
++ data_.push_back(static_cast<char>((u >> (8 * i)) & 0xFF));
++ }
++ }
++ const std::vector<char> &data() const { return data_; }
++
++private:
++ std::vector<char> data_;
++};
++
++// A serialized vector header (reserved, size_used_) followed by the
++// given number of int32 elements.
++std::vector<char> MakeVector(int32_t reserved, int32_t size_used, int32_t num_elements) {
++ ByteWriter w;
++ w.PutS32(reserved);
++ w.PutS32(size_used);
++ for (int32_t i = 0; i < num_elements; ++i) {
++ w.PutS32(i);
++ }
++ return w.data();
++}
++
++// reserved=4 but size_used_=0x10000: on unpatched code the callback
++// loop writes 65536 ints past the 4-int buffer (heap out-of-bounds
++// write).
++TEST(GenericVectorTest, RejectsSizeUsedBeyondReserved) {
++ std::vector<char> bytes = MakeVector(4, 0x10000, 0x10000);
++ TFile fp;
++ ASSERT_TRUE(fp.Open(bytes.data(), bytes.size()));
++ GenericVector<int> v;
++ EXPECT_FALSE(v.read(&fp, [](TFile *f, int *p) { return f->DeSerialize(p); }));
++}
++
++// Negative counts must be rejected; on unpatched code the read
++// "succeeds" and leaves size_used_ negative.
++TEST(GenericVectorTest, RejectsNegativeCounts) {
++ std::vector<char> bytes = MakeVector(-1, -1, 0);
++ TFile fp;
++ ASSERT_TRUE(fp.Open(bytes.data(), bytes.size()));
++ GenericVector<int> v;
++ EXPECT_FALSE(v.read(&fp, [](TFile *f, int *p) { return f->DeSerialize(p); }));
++}
++
++// A consistent vector must still be accepted.
++TEST(GenericVectorTest, AcceptsConsistentVector) {
++ std::vector<char> bytes = MakeVector(4, 2, 2);
++ TFile fp;
++ ASSERT_TRUE(fp.Open(bytes.data(), bytes.size()));
++ GenericVector<int> v;
++ ASSERT_TRUE(v.read(&fp, [](TFile *f, int *p) { return f->DeSerialize(p); }));
++ EXPECT_EQ(v.size(), 2);
++ EXPECT_EQ(v[0], 0);
++ EXPECT_EQ(v[1], 1);
++}
++
++} // namespace
++} // namespace tesseract
diff --git a/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb b/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
index 61cb1f7cad..60b50f16a5 100644
--- a/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
+++ b/meta-oe/recipes-graphics/tesseract/tesseract_5.5.2.bb
@@ -15,6 +15,7 @@ SRC_URI = "git://github.com/${BPN}-ocr/${BPN}.git;branch=main;protocol=https;tag
file://CVE-2026-88049.patch \
file://CVE-2026-88050.patch \
file://CVE-2026-88047.patch \
+ file://CVE-2026-88051.patch \
"
next prev parent reply other threads:[~2026-09-24 4:34 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 4:32 [oe][meta-oe][wrynose][PATCH 1/24] rabbitmq-c: patch CVE-2026-44235 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-oe][wrynose][PATCH 2/24] rabbitmq-c: patch CVE-2026-44236 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-oe][wrynose][PATCH 3/24] redis: patch CVE-2026-81934 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 4/24] sngrep: patch CVE-2026-90558 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 5/24] strongswan: patch CVE-2026-78123 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 6/24] strongswan: patch CVE-2026-78124 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 7/24] strongswan: patch CVE-2026-78126 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 8/24] strongswan: patch CVE-2026-78127 ankur.tyagi85
2026-09-24 4:32 ` [oe][meta-networking][wrynose][PATCH 9/24] strongswan: patch CVE-2026-78129 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 10/24] strongswan: patch CVE-2026-78133 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 11/24] strongswan: patch CVE-2026-78131 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 12/24] strongswan: patch CVE-2026-78130 ankur.tyagi85
2026-10-05 9:49 ` Anuj Mittal
2026-10-06 20:25 ` Ankur Tyagi
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 13/24] strongswan: patch CVE-2026-78132 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 14/24] strongswan: patch CVE-2026-78135 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-networking][wrynose][PATCH 15/24] strongswan: patch CVE-2026-78134 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 16/24] tesseract: patch CVE-2026-88052 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 17/24] tesseract: patch CVE-2026-88048 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 18/24] tesseract: patch CVE-2026-88049 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 19/24] tesseract: patch CVE-2026-88050 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 20/24] tesseract: patch CVE-2026-88047 ankur.tyagi85
2026-09-24 4:33 ` ankur.tyagi85 [this message]
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 22/24] tesseract: patch CVE-2026-88054 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 23/24] valkey: upgrade 9.0.5 -> 9.0.6 ankur.tyagi85
2026-09-24 4:33 ` [oe][meta-oe][wrynose][PATCH 24/24] valkey: mark CVE-2026-86227 fixed ankur.tyagi85
2026-10-06 4:19 ` [oe][meta-oe][wrynose][PATCH 1/24] rabbitmq-c: patch CVE-2026-44235 Anuj Mittal
2026-10-06 20:27 ` Ankur Tyagi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260924043315.1663186-21-ankur.tyagi85@gmail.com \
--to=ankur.tyagi85@gmail.com \
--cc=openembedded-devel@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.