[meta-oe][wrynose][PATCH 1/4] thrift: fix CVE-2026-55971

"Adarsh Jagadish Kamini" <[email protected]> Mon, 3 Aug 2026 14:59:19 +0200
Newsgroups org.openembedded.lists.openembedded-devel
Message-ID <[email protected]>
From: Adarsh Jagadish Kamini <[email protected]>

Backport patch to fix CVE-2026-55971.

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

Upstream fix:
  https://github.com/apache/thrift/commit/db4a473f3a984eee27273256fe737be5d=
d175595

Testing:
  The backported fix ships with a C++ Boost regression test,
  test_theadertransport_zlib_roundtrip, in
  lib/cpp/test/ThrifttReadCheckTests.cpp. The recipe builds with
  -DBUILD_TESTING=3DOFF, so the C++ test suite is not compiled during a
  normal build. To verify the fix, the suite was built with
  BUILD_TESTING=3DON (using the native thrift compiler for codegen via
  THRIFT_COMPILER) and the resulting UnitTests binary was executed
  against the target sysroot for MACHINE=3Dqemux86-64.

  Result: test_theadertransport_zlib_roundtrip passed. Full C++ UnitTests
  suite: 79 of 80 test cases passed, 107659 of 107660 assertions passed.
  The single failure (ToStringTest/locale_de_DE_floating_point_to_string)
  is unrelated to this fix and is caused by the de_DE locale not being
  present in the minimal test sysroot.

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

diff --git a/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55971.patc=
h b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55971.patch
new file mode 100644
index 0000000000..e13b6464e0
--- /dev/null
+++ b/meta-oe/recipes-connectivity/thrift/thrift/CVE-2026-55971.patch
@@ -0,0 +1,92 @@
+From e5f8281298e4809d57143ed52933487fa90f20e0 Mon Sep 17 00:00:00 2001
+From: Jens Geyer <[email protected]>
+Date: Wed, 17 Jun 2026 23:27:46 +0200
+Subject: [PATCH] Read the zlib transform result directly in THeaderTranspo=
rt
+ untransform Client: cpp
+
+The zlib read path decompressed the frame into the transform buffer and th=
en copied the result back into the receive buffer. Swap the transform buffe=
r in as the receive buffer and read the result directly instead of copying =
it.
+
+Adds a write/read round-trip test through the zlib transform.
+
+Co-Authored-By: Claude Opus 4.8 <[email protected]>
+
+Backport notes:
+  - lib/cpp/src/thrift/transport/THeaderTransport.cpp: taken unchanged
+    from upstream.
+  - lib/cpp/test/ThrifttReadCheckTests.cpp: kept only the new
+    test_theadertransport_zlib_roundtrip test. The upstream
+    test_theadertransport_header_size_exceeds_frame test was dropped
+    because it depends on THRIFT-5854, which is not in 0.22.0. Added the
+    #include <thrift/transport/THeaderTransport.h> that the new test
+    needs (added upstream by THRIFT-5854).
+
+Assisted-by: kiro:claude-sonnet-5
+
+CVE: CVE-2026-55971
+Upstream-Status: Backport [https://github.com/apache/thrift/commit/db4a473=
f3a984eee27273256fe737be5dd175595]
+
+Signed-off-by: Adarsh Jagadish Kamini <[email protected]>
+---
+ .../src/thrift/transport/THeaderTransport.cpp |  8 ++++++-
+ lib/cpp/test/ThrifttReadCheckTests.cpp        | 24 +++++++++++++++++++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.cpp b/lib/cpp/s=
rc/thrift/transport/THeaderTransport.cpp
+index b3b833389..117c8edd5 100644
+--- a/lib/cpp/src/thrift/transport/THeaderTransport.cpp
++++ b/lib/cpp/src/thrift/transport/THeaderTransport.cpp
+@@ -298,7 +298,13 @@ void THeaderTransport::untransform(uint8_t* ptr, uint=
32_t sz) {
+                                     "Error while zlib deflateEnd");
+       }
+=20
+-      memcpy(ptr, tBuf_.get(), sz);
++      // The result now lives in tBuf_ and is typically larger than the s=
ource
++      // section it was read from, so it does not fit back into the recei=
ve
++      // buffer at ptr.  Swap the transform buffer in as the receive buff=
er and
++      // continue from its start instead of copying the result back in pl=
ace.
++      rBuf_.swap(tBuf_);
++      std::swap(rBufSize_, tBufSize_);
++      ptr =3D rBuf_.get();
+     } else {
+       throw TApplicationException(TApplicationException::MISSING_RESULT, =
"Unknown transform");
+     }
+diff --git a/lib/cpp/test/ThrifttReadCheckTests.cpp b/lib/cpp/test/Thriftt=
ReadCheckTests.cpp
+index 09dffe228..963286100 100644
+--- a/lib/cpp/test/ThrifttReadCheckTests.cpp
++++ b/lib/cpp/test/ThrifttReadCheckTests.cpp
+@@ -31,6 +31,7 @@
+ #include <memory>
+ #include <thrift/transport/TTransportUtils.h>
+ #include <thrift/transport/TBufferTransports.h>
++#include <thrift/transport/THeaderTransport.h>
+ #include <thrift/transport/TSimpleFileTransport.h>
+ #include <thrift/transport/TFileTransport.h>
+ #include <thrift/protocol/TEnum.h>
+@@ -269,4 +270,27 @@ BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_read_ch=
eck_exception) {
+   protocol->readMapEnd();
+ }
+=20
++BOOST_AUTO_TEST_CASE(test_theadertransport_zlib_roundtrip) {
++  using apache::thrift::transport::THeaderTransport;
++  // A run of identical bytes compresses to far fewer bytes than it occup=
ies
++  // once expanded again, so the result of the zlib transform is much lar=
ger
++  // than the frame section it is read from.  This drives the full write/=
read
++  // round trip through the zlib transform path.  Keep the payload small =
enough
++  // to stay within the transform buffer the reader sizes from its write =
buffer.
++  const std::size_t N =3D 700;
++  std::vector<uint8_t> payload(N, 0x42);
++
++  std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
++  std::shared_ptr<THeaderTransport> writer(new THeaderTransport(buffer));
++  writer->setTransform(THeaderTransport::ZLIB_TRANSFORM);
++  writer->write(payload.data(), static_cast<uint32_t>(payload.size()));
++  writer->flush();
++
++  std::shared_ptr<THeaderTransport> reader(new THeaderTransport(buffer));
++  std::vector<uint8_t> out(N, 0x00);
++  reader->readAll(out.data(), static_cast<uint32_t>(out.size()));
++
++  BOOST_CHECK(out =3D=3D payload);
++}
++
+ BOOST_AUTO_TEST_SUITE_END()
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 8d885dadc4..26849da0c8 100644
--- a/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
+++ b/meta-oe/recipes-connectivity/thrift/thrift_0.22.0.bb
@@ -13,6 +13,7 @@ SRC_URI =3D "https://downloads.apache.org/${BPN}/${PV}/${=
BP}.tar.gz \
            file://0001-support-reproducible-builds.patch \
            file://CVE-2026-43868.patch \
            file://CVE-2026-43870.patch \
+           file://CVE-2026-55971.patch \
            "
 SRC_URI[sha256sum] =3D "794a0e455787960d9f27ab92c38e34da27e8deeda7a5db0e59=
dc64a00df8a1e5"
=20