[meta-oe][wrynose][PATCH] thrift: fix CVE-2026-55969

"Adarsh Jagadish Kamini" <[email protected]>
Newsgroups org.openembedded.lists.openembedded-devel
Message-ID <[email protected]>
Backport patch to fix CVE-2026-55969.

References:
  https://nvd.nist.gov/vuln/detail/CVE-2026-55969

Upstream fix:
  https://github.com/apache/thrift/commit/983c813c9a1a2302d9a3ae23d7368beceaac2d0a

Signed-off-by: Adarsh Jagadish Kamini <[email protected]>
---
 .../thrift/thrift/CVE-2026-55969.patch        | 307 ++++++++++++++++++
 .../thrift/thrift_0.22.0.bb                   |   1 +
 2 files changed, 308 insertions(+)
 create mode 100644 meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55969.patch

diff --git a/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55969.patch b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55969.patch
new file mode 100644
index 0000000000..736984d077
--- /dev/null
+++ b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55969.patch
@@ -0,0 +1,307 @@
+From 09f72e9ba64c551602f69abb6ea161b7020948be Mon Sep 17 00:00:00 2001
+From: dxbjavid <[email protected]>
+Date: Tue, 9 Jun 2026 16:35:58 +0530
+Subject: [PATCH] Widen multiplication operands in container size prechecks to
+ prevent arithmetic overflow on LLP64 platforms Client: cpp,c_glib Patch:
+ Javid Khan
+
+This closes #3590
+
+Backport notes: applied only the container-size widening (gint64/int64_t
+casts on the multiplication operands) onto thrift 0.22.0. Dropped the
+unrelated string_limit/container_limit changes from thrift_binary_protocol.c,
+which depend on infrastructure not present in 0.22.0.
+
+Assisted-by: kiro:claude-sonnet-5
+
+Changes from upstream commit 983c813c9a1a:
+  - lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c: adapted from upstream
+  - lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c: adapted from upstream
+  - lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c: adapted from upstream
+  - lib/cpp/src/thrift/protocol/TProtocol.h: adapted from upstream
+  - lib/cpp/src/thrift/transport/TTransport.h: adapted from upstream
+  - lib/cpp/test/ThrifttReadCheckTests.cpp: adapted from upstream
+
+CVE: CVE-2026-55969
+Upstream-Status: Backport [https://github.com/apache/thrift/commit/983c813c9a1a2302d9a3ae23d7368beceaac2d0a]
+
+Signed-off-by: Adarsh Jagadish Kamini <[email protected]>
+---
+ .../c_glib/protocol/thrift_binary_protocol.c  | 10 ++--
+ .../c_glib/protocol/thrift_compact_protocol.c | 10 ++--
+ .../c_glib/transport/thrift_transport.c       |  2 +-
+ .../c_glib/transport/thrift_transport.h       |  2 +-
+ lib/cpp/src/thrift/protocol/TBinaryProtocol.h |  6 +--
+ .../src/thrift/protocol/TCompactProtocol.h    |  6 +--
+ lib/cpp/src/thrift/protocol/TJSONProtocol.h   |  6 +--
+ lib/cpp/src/thrift/protocol/TProtocol.h       |  6 +--
+ lib/cpp/src/thrift/transport/TTransport.h     |  3 +-
+ lib/cpp/test/ThrifttReadCheckTests.cpp        | 48 +++++++++++++++++++
+ 10 files changed, 74 insertions(+), 25 deletions(-)
+
+diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
+index 9e80e107c..c3b00b028 100644
+--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
++++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_binary_protocol.c
+@@ -561,9 +561,9 @@ thrift_binary_protocol_read_map_begin (ThriftProtocol *protocol,
+     return -1;
+   }
+ 
+-  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport), 
+-                                    sizei * thrift_binary_protocol_get_min_serialized_size(protocol, k, error) + 
+-                                    sizei * thrift_binary_protocol_get_min_serialized_size(protocol, v, error),
++  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
++                                    (gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, k, error) +
++                                    (gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, v, error),
+                                     error))
+   {
+     return -1;
+@@ -618,8 +618,8 @@ thrift_binary_protocol_read_list_begin (ThriftProtocol *protocol,
+     return -1;
+   }
+ 
+-  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport), 
+-                                    (sizei * thrift_binary_protocol_get_min_serialized_size(protocol, e, error)),
++  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT(tp->transport),
++                                    ((gint64) sizei * thrift_binary_protocol_get_min_serialized_size(protocol, e, error)),
+                                     error))
+   {
+     return -1;
+diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
+index 0aa9a6fe6..f6ad36b36 100644
+--- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
++++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_compact_protocol.c
+@@ -1108,9 +1108,9 @@ thrift_compact_protocol_read_map_begin (ThriftProtocol *protocol,
+     return -1;
+   }
+ 
+-  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport), 
+-                                    msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) + 
+-                                    msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error),
++  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
++                                    (gint64) msize * thrift_protocol_get_min_serialized_size (protocol, *key_type, error) +
++                                    (gint64) msize * thrift_protocol_get_min_serialized_size (protocol, *value_type, error),
+                                     error))
+   {
+     return -1;
+@@ -1183,8 +1183,8 @@ thrift_compact_protocol_read_list_begin (ThriftProtocol *protocol,
+   *element_type = ret;
+   *size = (guint32) lsize;
+ 
+-  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport), 
+-                                    (lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)),
++  if(!ttc->checkReadBytesAvailable (THRIFT_TRANSPORT (tp->transport),
++                                    ((gint64) lsize * thrift_protocol_get_min_serialized_size (protocol, *element_type, error)),
+                                     error))
+   {
+     return -1;
+diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
+index 9d3f25e75..7e18f712a 100644
+--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
++++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.c
+@@ -160,7 +160,7 @@ thrift_transport_updateKnownMessageSize(ThriftTransport *transport, glong size,
+ }
+ 
+ gboolean
+-thrift_transport_checkReadBytesAvailable(ThriftTransport *transport, glong numBytes, GError **error)
++thrift_transport_checkReadBytesAvailable(ThriftTransport *transport, gint64 numBytes, GError **error)
+ {
+   gboolean boolean = TRUE;
+   ThriftTransport *tt = THRIFT_TRANSPORT (transport);
+diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
+index 83fb5da19..01365ba7f 100644
+--- a/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
++++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_transport.h
+@@ -83,7 +83,7 @@ struct _ThriftTransportClass
+   gint32 (*read_all) (ThriftTransport *transport, gpointer buf,
+                       guint32 len, GError **error);
+   gboolean (*updateKnownMessageSize) (ThriftTransport *transport, glong size, GError **error);
+-  gboolean (*checkReadBytesAvailable) (ThriftTransport *transport, glong numBytes, GError **error);
++  gboolean (*checkReadBytesAvailable) (ThriftTransport *transport, gint64 numBytes, GError **error);
+   gboolean (*resetConsumedMessageSize) (ThriftTransport *transport, glong newSize, GError **error);
+   gboolean (*countConsumedMessageBytes) (ThriftTransport *transport, glong numBytes, GError **error);
+ };
+diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
+index cba6e6948..1a7410c86 100644
+--- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
++++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h
+@@ -174,18 +174,18 @@ public:
+ 
+   void checkReadBytesAvailable(TSet& set) override
+   {
+-      trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TList& list) override
+   {
+-      trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TMap& map) override
+   {
+       int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
+-      trans_->checkReadBytesAvailable(map.size_ * elmSize);
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
+   }
+ 
+ protected:
+diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.h b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
+index c7d81eea6..97ca460a7 100644
+--- a/lib/cpp/src/thrift/protocol/TCompactProtocol.h
++++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.h
+@@ -146,18 +146,18 @@ public:
+ 
+   void checkReadBytesAvailable(TSet& set) override
+   {
+-      trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TList& list) override
+   {
+-      trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TMap& map) override
+   {
+       int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
+-      trans_->checkReadBytesAvailable(map.size_ * elmSize);
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
+   }
+ 
+   /**
+diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
+index 09eb6eab1..265b33922 100644
+--- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h
++++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h
+@@ -253,18 +253,18 @@ public:
+ 
+   void checkReadBytesAvailable(TSet& set) override
+   {
+-      trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TList& list) override
+   {
+-      trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
+   }
+ 
+   void checkReadBytesAvailable(TMap& map) override
+   {
+       int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
+-      trans_->checkReadBytesAvailable(map.size_ * elmSize);
++      trans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
+   }
+ 
+   class LookaheadReader {
+diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h
+index 37b0db711..4eedc5e82 100644
+--- a/lib/cpp/src/thrift/protocol/TProtocol.h
++++ b/lib/cpp/src/thrift/protocol/TProtocol.h
+@@ -604,18 +604,18 @@ protected:
+ 
+   virtual void checkReadBytesAvailable(TSet& set)
+   {
+-      ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_));
++      ptrans_->checkReadBytesAvailable(static_cast<int64_t>(set.size_) * getMinSerializedSize(set.elemType_));
+   }
+ 
+   virtual void checkReadBytesAvailable(TList& list)
+   {
+-      ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_));
++      ptrans_->checkReadBytesAvailable(static_cast<int64_t>(list.size_) * getMinSerializedSize(list.elemType_));
+   }
+ 
+   virtual void checkReadBytesAvailable(TMap& map)
+   {
+       int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_);
+-      ptrans_->checkReadBytesAvailable(map.size_ * elmSize);
++      ptrans_->checkReadBytesAvailable(static_cast<int64_t>(map.size_) * elmSize);
+   }
+ 
+   std::shared_ptr<TTransport> ptrans_;
+diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h
+index 52b3a0a4d..1269593ac 100644
+--- a/lib/cpp/src/thrift/transport/TTransport.h
++++ b/lib/cpp/src/thrift/transport/TTransport.h
+@@ -23,6 +23,7 @@
+ #include <thrift/Thrift.h>
+ #include <thrift/TConfiguration.h>
+ #include <thrift/transport/TTransportException.h>
++#include <cstdint>
+ #include <memory>
+ #include <string>
+ 
+@@ -272,7 +273,7 @@ public:
+    *
+    * @param numBytes  numBytes bytes of data
+    */
+-  void checkReadBytesAvailable(long int numBytes)
++  void checkReadBytesAvailable(int64_t numBytes)
+   {
+     if (remainingMessageSize_ < numBytes)
+       throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached");
+diff --git a/lib/cpp/test/ThrifttReadCheckTests.cpp b/lib/cpp/test/ThrifttReadCheckTests.cpp
+index 963286100..72e798bc1 100644
+--- a/lib/cpp/test/ThrifttReadCheckTests.cpp
++++ b/lib/cpp/test/ThrifttReadCheckTests.cpp
+@@ -243,6 +243,54 @@ BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_read_check_pass) {
+   BOOST_CHECK_NO_THROW(protocol->readString(eleven));
+ }
+ 
++BOOST_AUTO_TEST_CASE(test_tthriftbinaryprotocol_container_size_overflow) {
++  std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
++  std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
++  std::shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
++
++  uint32_t val = 0;
++  TType elemType = apache::thrift::protocol::T_STOP;
++  // 0x40000000 elements of min size 4 require 4 GiB; the product wraps to 0 in
++  // 32-bit math and used to slip past the MaxMessageSize check.
++  TList list(T_I32, 0x40000000);
++  protocol->writeListBegin(list.elemType_, list.size_);
++  protocol->writeListEnd();
++  BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
++  protocol->readListEnd();
++}
++
++BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_container_size_overflow) {
++  std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
++  std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
++  std::shared_ptr<TCompactProtocol> protocol(new TCompactProtocol(transport));
++
++  uint32_t val = 0;
++  TType elemType = apache::thrift::protocol::T_STOP;
++  // 0x10000000 elements of min size 16 (UUID) require 4 GiB; the product wraps
++  // to 0 in 32-bit math and used to slip past the MaxMessageSize check.
++  TList list(T_UUID, 0x10000000);
++  protocol->writeListBegin(list.elemType_, list.size_);
++  protocol->writeListEnd();
++  BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
++  protocol->readListEnd();
++}
++
++BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_container_size_overflow) {
++  std::shared_ptr<TConfiguration> config (new TConfiguration(1024));
++  std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
++  std::shared_ptr<TJSONProtocol> protocol(new TJSONProtocol(transport));
++
++  uint32_t val = 0;
++  TType elemType = apache::thrift::protocol::T_STOP;
++  // 0x10000000 elements of min size 16 (UUID) require 4 GiB; the product wraps
++  // to 0 in 32-bit math and used to slip past the MaxMessageSize check.
++  TList list(T_UUID, 0x10000000);
++  protocol->writeListBegin(list.elemType_, list.size_);
++  protocol->writeListEnd();
++  BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException);
++  protocol->readListEnd();
++}
++
+ BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_read_check_exception) {
+   std::shared_ptr<TConfiguration> config (new TConfiguration(MAX_MESSAGE_SIZE));
+   std::shared_ptr<TMemoryBuffer> transport(new TMemoryBuffer(config));
diff --git a/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb b/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
index 0128de8519..3717302086 100644
--- a/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
+++ b/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
@@ -17,6 +17,7 @@ SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \
            file://CVE-2026-58023.patch \
            file://CVE-2026-48144.patch \
            file://CVE-2026-58389.patch \
+           file://CVE-2026-55969.patch \
            "
 SRC_URI[sha256sum] = "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59dc64a00df8a1e5"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.