aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAri Parkkila <ari.parkkila@qt.io>2025-08-19 12:22:16 +0300
committerAri Parkkila <ari.parkkila@qt.io>2025-08-20 10:47:19 +0300
commite24900fa2dc599f390ac89118834d7e13261c1d4 (patch)
tree7cc86015d63da43e8c019c77d9e9040c7b038e76
parentdf86e9d3670b3ed6a5c7f420bb9edc4815c05de7 (diff)
Add protobuf 4.25.3 as workaround
The meta-openembbeded layer updated protobuf to 4.25.8 but qcom-sensors-core has binary dependency to version 4.25.3 so add that as workaround until fixed upstream. Fixes: QTBUG-139276 Change-Id: I6e51b7d91d74f6aa083ade1511a5dfaa480fd7c8 Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
-rw-r--r--recipes-devtools/protobuf/protobuf-c/0001-Makefile.am-do-not-compile-the-code-which-was-genera.patch106
-rw-r--r--recipes-devtools/protobuf/protobuf-c_1.5.0.bb38
-rw-r--r--recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch794
-rw-r--r--recipes-devtools/protobuf/protobuf/0001-Fix-build-on-mips-clang.patch26
-rw-r--r--recipes-devtools/protobuf/protobuf/0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch61
-rw-r--r--recipes-devtools/protobuf/protobuf/run-ptest38
-rw-r--r--recipes-devtools/protobuf/protobuf_4.25.3.bb119
-rw-r--r--recipes-devtools/python/python3-protobuf_4.25.3.bb45
8 files changed, 1227 insertions, 0 deletions
diff --git a/recipes-devtools/protobuf/protobuf-c/0001-Makefile.am-do-not-compile-the-code-which-was-genera.patch b/recipes-devtools/protobuf/protobuf-c/0001-Makefile.am-do-not-compile-the-code-which-was-genera.patch
new file mode 100644
index 0000000..896a568
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf-c/0001-Makefile.am-do-not-compile-the-code-which-was-genera.patch
@@ -0,0 +1,106 @@
+From 62b2fd0a150133b6439f6537cb1762d35f5790ee Mon Sep 17 00:00:00 2001
+From: Xiangyu Chen <xiangyu.chen@windriver.com>
+Date: Fri, 31 Mar 2023 16:02:50 +0800
+Subject: [PATCH] Makefile.am: do not compile the code which was generated from
+ test-full.proto in protobuf-c-native
+
+Those code was auto generated by protoc command with test-full.proto, those code are not compatible
+with protobuf 4.22.x, so temporarily disable compile those code until protobuf-c upstream adapt
+the test-full.proto with latest version protobuf.
+
+Upstream-Status: Inappropriate [oe specific]
+
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+---
+ Makefile.am | 75 -----------------------------------------------------
+ 1 file changed, 75 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index ff12664..7412aef 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -136,81 +136,6 @@ else
+
+ LOG_COMPILER = $(VALGRIND)
+
+-check_PROGRAMS += \
+- t/generated-code/test-generated-code \
+- t/generated-code2/test-generated-code2 \
+- t/generated-code3/test-generated-code3 \
+- t/version/version
+-
+-TESTS += \
+- t/generated-code/test-generated-code \
+- t/generated-code2/test-generated-code2 \
+- t/generated-code3/test-generated-code3 \
+- t/version/version
+-
+-t_generated_code_test_generated_code_SOURCES = \
+- t/generated-code/test-generated-code.c \
+- t/test.pb-c.c
+-t_generated_code_test_generated_code_LDADD = \
+- protobuf-c/libprotobuf-c.la
+-
+-t_generated_code2_test_generated_code2_SOURCES = \
+- t/generated-code2/test-generated-code2.c \
+- t/test-full.pb-c.c \
+- t/test-optimized.pb-c.c
+-t_generated_code2_test_generated_code2_LDADD = \
+- protobuf-c/libprotobuf-c.la
+-
+-t_generated_code3_test_generated_code3_CPPFLAGS = \
+- -DPROTO3
+-
+-t_generated_code3_test_generated_code3_SOURCES = \
+- t/generated-code/test-generated-code.c \
+- t/test-proto3.pb-c.c
+-
+-t_generated_code3_test_generated_code3_LDADD = \
+- protobuf-c/libprotobuf-c.la
+-
+-noinst_PROGRAMS += \
+- t/generated-code2/cxx-generate-packed-data
+-
+-t_generated_code2_cxx_generate_packed_data_SOURCES = \
+- t/generated-code2/cxx-generate-packed-data.cc \
+- t/test-full.pb.cc \
+- protobuf-c/protobuf-c.pb.cc
+-$(t_generated_code2_cxx_generate_packed_data_OBJECTS): t/test-full.pb.h
+-t_generated_code2_cxx_generate_packed_data_CXXFLAGS = \
+- $(AM_CXXFLAGS) \
+- $(protobuf_CFLAGS)
+-t_generated_code2_cxx_generate_packed_data_LDADD = \
+- $(protobuf_LIBS)
+-
+-t/test.pb-c.c t/test.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test.proto
+- $(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test.proto
+-
+-t/test-optimized.pb-c.c t/test-optimized.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-optimized.proto
+- $(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-optimized.proto
+-
+-t/test-full.pb-c.c t/test-full.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-full.proto
+- $(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-full.proto
+-
+-t/test-full.pb.cc t/test-full.pb.h: @PROTOC@ $(top_srcdir)/t/test-full.proto
+- $(AM_V_GEN)@PROTOC@ -I$(top_srcdir) --cpp_out=$(top_builddir) $(top_srcdir)/t/test-full.proto
+-
+-t/test-proto3.pb-c.c t/test-proto3.pb-c.h: $(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) $(top_srcdir)/t/test-proto3.proto
+- $(AM_V_GEN)@PROTOC@ --plugin=protoc-gen-c=$(top_builddir)/protoc-c/protoc-gen-c$(EXEEXT) -I$(top_srcdir) --c_out=$(top_builddir) $(top_srcdir)/t/test-proto3.proto
+-
+-t/generated-code2/test-full-cxx-output.inc: t/generated-code2/cxx-generate-packed-data$(EXEEXT)
+- $(AM_V_GEN)$(top_builddir)/t/generated-code2/cxx-generate-packed-data$(EXEEXT) > $(top_builddir)/t/generated-code2/test-full-cxx-output.inc
+-
+-BUILT_SOURCES += \
+- t/test.pb-c.c t/test.pb-c.h \
+- t/test-full.pb-c.c t/test-full.pb-c.h \
+- t/test-optimized.pb-c.c t/test-optimized.pb-c.h \
+- t/test-full.pb.cc t/test-full.pb.h \
+- t/test-proto3.pb-c.c t/test-proto3.pb-c.h \
+- t/generated-code2/test-full-cxx-output.inc
+-
+ t_version_version_SOURCES = \
+ t/version/version.c
+ t_version_version_LDADD = \
+--
+2.34.1
+
diff --git a/recipes-devtools/protobuf/protobuf-c_1.5.0.bb b/recipes-devtools/protobuf/protobuf-c_1.5.0.bb
new file mode 100644
index 0000000..24de6b8
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf-c_1.5.0.bb
@@ -0,0 +1,38 @@
+SUMMARY = "Protocol Buffers - structured data serialisation mechanism"
+DESCRIPTION = "This is protobuf-c, a C implementation of the Google Protocol Buffers data \
+serialization format. It includes libprotobuf-c, a pure C library that \
+implements protobuf encoding and decoding, and protoc-c, a code generator that \
+converts Protocol Buffer .proto files to C descriptor code, based on the \
+original protoc. protobuf-c formerly included an RPC implementation; that code \
+has been split out into the protobuf-c-rpc project."
+HOMEPAGE = "https://github.com/protobuf-c/protobuf-c"
+SECTION = "console/tools"
+LICENSE = "BSD-2-Clause"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=d11077c6a2b5d2e64b9f32b61a9b78ba"
+
+DEPENDS = "protobuf-native protobuf"
+
+SRC_URI = "git://github.com/protobuf-c/protobuf-c.git;branch=master;protocol=https"
+SRC_URI:append:class-native = " file://0001-Makefile.am-do-not-compile-the-code-which-was-genera.patch"
+
+SRCREV = "8c201f6e47a53feaab773922a743091eb6c8972a"
+
+S = "${WORKDIR}/git"
+
+inherit autotools pkgconfig
+
+export PROTOC = "${STAGING_BINDIR_NATIVE}/protoc"
+
+# After several fix attempts there is still a race between generating
+# t.test-full.pb.h and compiling cxx_generate_packed_data.c despite
+# BUILT_SOURCES and explicit dependencies.
+PARALLEL_MAKE = ""
+
+PACKAGE_BEFORE_PN = "${PN}-compiler"
+
+FILES:${PN}-compiler = "${bindir}"
+
+RDEPENDS:${PN}-compiler = "protobuf-compiler"
+RDEPENDS:${PN}-dev += "${PN}-compiler"
+
+BBCLASSEXTEND = "native nativesdk"
diff --git a/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch b/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch
new file mode 100644
index 0000000..2f14620
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch
@@ -0,0 +1,794 @@
+From 9f182ae260cc60e8cc5417abbe9481821642afa0 Mon Sep 17 00:00:00 2001
+From: Protobuf Team Bot <protobuf-github-bot@google.com>
+Date: Tue, 17 Sep 2024 12:03:36 -0700
+Subject: [PATCH] Add recursion check when parsing unknown fields in Java.
+
+PiperOrigin-RevId: 675657198
+
+CVE: CVE-2024-7254
+
+Upstream-Status: Backport [ac9fb5b4c71b0dd80985b27684e265d1f03abf46]
+
+The original patch is adjusted to fit for the current version.
+
+Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
+---
+ .../com/google/protobuf/ArrayDecoders.java | 28 +++
+ .../com/google/protobuf/CodedInputStream.java | 72 +++++-
+ .../com/google/protobuf/MessageSchema.java | 9 +-
+ .../com/google/protobuf/MessageSetSchema.java | 2 +-
+ .../google/protobuf/UnknownFieldSchema.java | 28 ++-
+ .../google/protobuf/CodedInputStreamTest.java | 159 ++++++++++++
+ .../java/com/google/protobuf/LiteTest.java | 232 ++++++++++++++++++
+ 7 files changed, 514 insertions(+), 16 deletions(-)
+
+diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
+index f3241de50..0f3d7de0d 100644
+--- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
++++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
+@@ -26,6 +26,10 @@ final class ArrayDecoders {
+
+ private ArrayDecoders() {
+ }
++ static final int DEFAULT_RECURSION_LIMIT = 100;
++
++ @SuppressWarnings("NonFinalStaticField")
++ private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT;
+
+ /**
+ * A helper used to return multiple values in a Java function. Java doesn't natively support
+@@ -38,6 +42,7 @@ final class ArrayDecoders {
+ public long long1;
+ public Object object1;
+ public final ExtensionRegistryLite extensionRegistry;
++ public int recursionDepth;
+
+ Registers() {
+ this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry();
+@@ -245,7 +250,10 @@ final class ArrayDecoders {
+ if (length < 0 || length > limit - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
++ registers.recursionDepth++;
++ checkRecursionLimit(registers.recursionDepth);
+ schema.mergeFrom(msg, data, position, position + length, registers);
++ registers.recursionDepth--;
+ registers.object1 = msg;
+ return position + length;
+ }
+@@ -263,8 +271,11 @@ final class ArrayDecoders {
+ // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema
+ // and it can't be used in group fields).
+ final MessageSchema messageSchema = (MessageSchema) schema;
++ registers.recursionDepth++;
++ checkRecursionLimit(registers.recursionDepth);
+ final int endPosition =
+ messageSchema.parseMessage(msg, data, position, limit, endGroup, registers);
++ registers.recursionDepth--;
+ registers.object1 = msg;
+ return endPosition;
+ }
+@@ -1025,6 +1036,8 @@ final class ArrayDecoders {
+ final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance();
+ final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
+ int lastTag = 0;
++ registers.recursionDepth++;
++ checkRecursionLimit(registers.recursionDepth);
+ while (position < limit) {
+ position = decodeVarint32(data, position, registers);
+ lastTag = registers.int1;
+@@ -1033,6 +1046,7 @@ final class ArrayDecoders {
+ }
+ position = decodeUnknownField(lastTag, data, position, limit, child, registers);
+ }
++ registers.recursionDepth--;
+ if (position > limit || lastTag != endGroup) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+@@ -1079,4 +1093,18 @@ final class ArrayDecoders {
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ }
++
++ /**
++ * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if
++ * the depth of the message exceeds this limit.
++ */
++ public static void setRecursionLimit(int limit) {
++ recursionLimit = limit;
++ }
++
++ private static void checkRecursionLimit(int depth) throws InvalidProtocolBufferException {
++ if (depth >= recursionLimit) {
++ throw InvalidProtocolBufferException.recursionLimitExceeded();
++ }
++ }
+ }
+diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+index 8f1ac736d..29256b4b3 100644
+--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
++++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+@@ -703,7 +703,14 @@ public abstract class CodedInputStream {
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -713,7 +720,14 @@ public abstract class CodedInputStream {
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag, output)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag, output);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -1415,7 +1429,14 @@ public abstract class CodedInputStream {
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -1425,7 +1446,14 @@ public abstract class CodedInputStream {
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag, output)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag, output);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -2180,7 +2208,14 @@ public abstract class CodedInputStream {
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -2190,7 +2225,14 @@ public abstract class CodedInputStream {
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag, output)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag, output);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -3298,7 +3340,14 @@ public abstract class CodedInputStream {
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+@@ -3308,7 +3357,14 @@ public abstract class CodedInputStream {
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+- if (tag == 0 || !skipField(tag, output)) {
++ if (tag == 0) {
++ return;
++ }
++ checkRecursionLimit();
++ ++recursionDepth;
++ boolean fieldSkipped = skipField(tag, output);
++ --recursionDepth;
++ if (!fieldSkipped) {
+ return;
+ }
+ }
+diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+index de3890f70..5ad6762b0 100644
+--- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java
++++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+@@ -3006,7 +3006,8 @@ final class MessageSchema<T> implements Schema<T> {
+ unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ }
+ // Unknown field.
+- if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
++ if (unknownFieldSchema.mergeOneFieldFrom(
++ unknownFields, reader, /* currentDepth= */ 0)) {
+ continue;
+ }
+ }
+@@ -3381,7 +3382,8 @@ final class MessageSchema<T> implements Schema<T> {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ }
+- if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
++ if (!unknownFieldSchema.mergeOneFieldFrom(
++ unknownFields, reader, /* currentDepth= */ 0)) {
+ return;
+ }
+ break;
+@@ -3397,7 +3399,8 @@ final class MessageSchema<T> implements Schema<T> {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ }
+- if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
++ if (!unknownFieldSchema.mergeOneFieldFrom(
++ unknownFields, reader, /* currentDepth= */ 0)) {
+ return;
+ }
+ }
+diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
+index eec3acd35..ec37d41f9 100644
+--- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
++++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
+@@ -278,7 +278,7 @@ final class MessageSetSchema<T> implements Schema<T> {
+ reader, extension, extensionRegistry, extensions);
+ return true;
+ } else {
+- return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader);
++ return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader, /* currentDepth= */ 0);
+ }
+ } else {
+ return reader.skipField();
+diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
+index c4ec645bf..0cdecd30e 100644
+--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
++++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
+@@ -13,6 +13,11 @@ import java.io.IOException;
+ @CheckReturnValue
+ abstract class UnknownFieldSchema<T, B> {
+
++ static final int DEFAULT_RECURSION_LIMIT = 100;
++
++ @SuppressWarnings("NonFinalStaticField")
++ private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT;
++
+ /** Whether unknown fields should be dropped. */
+ abstract boolean shouldDiscardUnknownFields(Reader reader);
+
+@@ -56,7 +61,8 @@ abstract class UnknownFieldSchema<T, B> {
+ abstract void makeImmutable(Object message);
+
+ /** Merges one field into the unknown fields. */
+- final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException {
++ final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth)
++ throws IOException {
+ int tag = reader.getTag();
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+@@ -75,7 +81,12 @@ abstract class UnknownFieldSchema<T, B> {
+ case WireFormat.WIRETYPE_START_GROUP:
+ final B subFields = newBuilder();
+ int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+- mergeFrom(subFields, reader);
++ currentDepth++;
++ if (currentDepth >= recursionLimit) {
++ throw InvalidProtocolBufferException.recursionLimitExceeded();
++ }
++ mergeFrom(subFields, reader, currentDepth);
++ currentDepth--;
+ if (endGroupTag != reader.getTag()) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+@@ -88,10 +99,11 @@ abstract class UnknownFieldSchema<T, B> {
+ }
+ }
+
+- final void mergeFrom(B unknownFields, Reader reader) throws IOException {
++ final void mergeFrom(B unknownFields, Reader reader, int currentDepth)
++ throws IOException {
+ while (true) {
+ if (reader.getFieldNumber() == Reader.READ_DONE
+- || !mergeOneFieldFrom(unknownFields, reader)) {
++ || !mergeOneFieldFrom(unknownFields, reader, currentDepth)) {
+ break;
+ }
+ }
+@@ -108,4 +120,12 @@ abstract class UnknownFieldSchema<T, B> {
+ abstract int getSerializedSizeAsMessageSet(T message);
+
+ abstract int getSerializedSize(T unknowns);
++
++ /**
++ * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if
++ * the depth of the message exceeds this limit.
++ */
++ public void setRecursionLimit(int limit) {
++ recursionLimit = limit;
++ }
+ }
+diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+index 2de3273e3..19a6b669d 100644
+--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
++++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+@@ -10,6 +10,10 @@ package com.google.protobuf;
+ import static com.google.common.truth.Truth.assertThat;
+ import static com.google.common.truth.Truth.assertWithMessage;
+ import static org.junit.Assert.assertArrayEquals;
++import static org.junit.Assert.assertThrows;
++
++import com.google.common.primitives.Bytes;
++import map_test.MapTestProto.MapContainer;
+ import protobuf_unittest.UnittestProto.BoolMessage;
+ import protobuf_unittest.UnittestProto.Int32Message;
+ import protobuf_unittest.UnittestProto.Int64Message;
+@@ -34,6 +38,13 @@ public class CodedInputStreamTest {
+
+ private static final int DEFAULT_BLOCK_SIZE = 4096;
+
++ private static final int GROUP_TAP = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP);
++
++ private static final byte[] NESTING_SGROUP = generateSGroupTags();
++
++ private static final byte[] NESTING_SGROUP_WITH_INITIAL_BYTES = generateSGroupTagsForMapField();
++
++
+ private enum InputType {
+ ARRAY {
+ @Override
+@@ -116,6 +127,17 @@ public class CodedInputStreamTest {
+ return bytes;
+ }
+
++ private static byte[] generateSGroupTags() {
++ byte[] bytes = new byte[100000];
++ Arrays.fill(bytes, (byte) GROUP_TAP);
++ return bytes;
++ }
++
++ private static byte[] generateSGroupTagsForMapField() {
++ byte[] initialBytes = {18, 1, 75, 26, (byte) 198, (byte) 154, 12};
++ return Bytes.concat(initialBytes, NESTING_SGROUP);
++ }
++
+ /**
+ * An InputStream which limits the number of bytes it reads at a time. We use this to make sure
+ * that CodedInputStream doesn't screw up when reading in small blocks.
+@@ -659,6 +681,143 @@ public class CodedInputStreamTest {
+ }
+ }
+
++ @Test
++ public void testMaliciousRecursion_unknownFields() throws Exception {
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> TestRecursiveMessage.parseFrom(NESTING_SGROUP));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousRecursion_skippingUnknownField() throws Exception {
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () ->
++ DiscardUnknownFieldsParser.wrap(TestRecursiveMessage.parser())
++ .parseFrom(NESTING_SGROUP));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception {
++ Throwable parseFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () ->
++ MapContainer.parseFrom(
++ new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES)));
++ Throwable mergeFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () ->
++ MapContainer.newBuilder()
++ .mergeFrom(new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES)));
++
++ assertThat(parseFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ assertThat(mergeFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTags_inputStream_skipMessage() throws Exception {
++ ByteArrayInputStream inputSteam = new ByteArrayInputStream(NESTING_SGROUP);
++ CodedInputStream input = CodedInputStream.newInstance(inputSteam);
++ CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]);
++
++ Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage);
++ Throwable thrown2 =
++ assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ assertThat(thrown2)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception {
++ Throwable parseFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.parseFrom(NESTING_SGROUP_WITH_INITIAL_BYTES));
++ Throwable mergeFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.newBuilder().mergeFrom(NESTING_SGROUP_WITH_INITIAL_BYTES));
++
++ assertThat(parseFromThrown)
++ .hasMessageThat()
++ .contains("the input ended unexpectedly in the middle of a field");
++ assertThat(mergeFromThrown)
++ .hasMessageThat()
++ .contains("the input ended unexpectedly in the middle of a field");
++ }
++
++ @Test
++ public void testMaliciousSGroupTags_arrayDecoder_skipMessage() throws Exception {
++ CodedInputStream input = CodedInputStream.newInstance(NESTING_SGROUP);
++ CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]);
++
++ Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage);
++ Throwable thrown2 =
++ assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ assertThat(thrown2)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTagsWithMapField_fromByteBuffer() throws Exception {
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.parseFrom(ByteBuffer.wrap(NESTING_SGROUP_WITH_INITIAL_BYTES)));
++
++ assertThat(thrown)
++ .hasMessageThat()
++ .contains("the input ended unexpectedly in the middle of a field");
++ }
++
++ @Test
++ public void testMaliciousSGroupTags_byteBuffer_skipMessage() throws Exception {
++ CodedInputStream input = InputType.NIO_DIRECT.newDecoder(NESTING_SGROUP);
++ CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]);
++
++ Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage);
++ Throwable thrown2 =
++ assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ assertThat(thrown2)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTags_iterableByteBuffer() throws Exception {
++ CodedInputStream input = InputType.ITER_DIRECT.newDecoder(NESTING_SGROUP);
++ CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]);
++
++ Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage);
++ Throwable thrown2 =
++ assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output));
++
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ assertThat(thrown2)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
+ private void checkSizeLimitExceeded(InvalidProtocolBufferException e) {
+ assertThat(e)
+ .hasMessageThat()
+diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+index 754ed7d5f..81be90bfd 100644
+--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
++++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+@@ -2459,6 +2459,211 @@ public class LiteTest {
+ }
+ }
+
++ @Test
++ public void testParseFromInputStream_concurrent_nestingUnknownGroups() throws Exception {
++ int numThreads = 200;
++ ArrayList<Thread> threads = new ArrayList<>();
++
++ ByteString byteString = generateNestingGroups(99);
++ AtomicBoolean thrown = new AtomicBoolean(false);
++
++ for (int i = 0; i < numThreads; i++) {
++ Thread thread =
++ new Thread(
++ () -> {
++ try {
++ TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString);
++ } catch (IOException e) {
++ if (e.getMessage().contains("Protocol message had too many levels of nesting")) {
++ thrown.set(true);
++ }
++ }
++ });
++ thread.start();
++ threads.add(thread);
++ }
++
++ for (Thread thread : threads) {
++ thread.join();
++ }
++
++ assertThat(thrown.get()).isFalse();
++ }
++
++ @Test
++ public void testParseFromInputStream_nestingUnknownGroups() throws IOException {
++ ByteString byteString = generateNestingGroups(99);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString));
++ assertThat(thrown)
++ .hasMessageThat()
++ .doesNotContain("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testParseFromInputStream_nestingUnknownGroups_exception() throws IOException {
++ ByteString byteString = generateNestingGroups(100);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString));
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testParseFromInputStream_setRecursionLimit_exception() throws IOException {
++ ByteString byteString = generateNestingGroups(199);
++ UnknownFieldSchema<?, ?> schema = SchemaUtil.unknownFieldSetLiteSchema();
++ schema.setRecursionLimit(200);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString));
++ assertThat(thrown)
++ .hasMessageThat()
++ .doesNotContain("Protocol message had too many levels of nesting");
++ schema.setRecursionLimit(UnknownFieldSchema.DEFAULT_RECURSION_LIMIT);
++ }
++
++ @Test
++ public void testParseFromBytes_concurrent_nestingUnknownGroups() throws Exception {
++ int numThreads = 200;
++ ArrayList<Thread> threads = new ArrayList<>();
++
++ ByteString byteString = generateNestingGroups(99);
++ AtomicBoolean thrown = new AtomicBoolean(false);
++
++ for (int i = 0; i < numThreads; i++) {
++ Thread thread =
++ new Thread(
++ () -> {
++ try {
++ // Should pass in byte[] instead of ByteString to go into ArrayDecoders.
++ TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString.toByteArray());
++ } catch (InvalidProtocolBufferException e) {
++ if (e.getMessage().contains("Protocol message had too many levels of nesting")) {
++ thrown.set(true);
++ }
++ }
++ });
++ thread.start();
++ threads.add(thread);
++ }
++
++ for (Thread thread : threads) {
++ thread.join();
++ }
++
++ assertThat(thrown.get()).isFalse();
++ }
++
++ @Test
++ public void testParseFromBytes_nestingUnknownGroups() throws IOException {
++ ByteString byteString = generateNestingGroups(99);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> TestAllTypesLite.parseFrom(byteString.toByteArray()));
++ assertThat(thrown)
++ .hasMessageThat()
++ .doesNotContain("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testParseFromBytes_nestingUnknownGroups_exception() throws IOException {
++ ByteString byteString = generateNestingGroups(100);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> TestAllTypesLite.parseFrom(byteString.toByteArray()));
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testParseFromBytes_setRecursionLimit_exception() throws IOException {
++ ByteString byteString = generateNestingGroups(199);
++ ArrayDecoders.setRecursionLimit(200);
++
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> TestAllTypesLite.parseFrom(byteString.toByteArray()));
++ assertThat(thrown)
++ .hasMessageThat()
++ .doesNotContain("Protocol message had too many levels of nesting");
++ ArrayDecoders.setRecursionLimit(ArrayDecoders.DEFAULT_RECURSION_LIMIT);
++ }
++
++ @Test
++ public void testParseFromBytes_recursiveMessages() throws Exception {
++ byte[] data99 = makeRecursiveMessage(99).toByteArray();
++ byte[] data100 = makeRecursiveMessage(100).toByteArray();
++
++ RecursiveMessage unused = RecursiveMessage.parseFrom(data99);
++ Throwable thrown =
++ assertThrows(
++ InvalidProtocolBufferException.class, () -> RecursiveMessage.parseFrom(data100));
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testParseFromBytes_recursiveKnownGroups() throws Exception {
++ byte[] data99 = makeRecursiveGroup(99).toByteArray();
++ byte[] data100 = makeRecursiveGroup(100).toByteArray();
++
++ RecursiveGroup unused = RecursiveGroup.parseFrom(data99);
++ Throwable thrown =
++ assertThrows(InvalidProtocolBufferException.class, () -> RecursiveGroup.parseFrom(data100));
++ assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ @SuppressWarnings("ProtoParseFromByteString")
++ public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception {
++ ByteString byteString = generateNestingGroups(102);
++
++ Throwable parseFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.parseFrom(byteString.toByteArray()));
++ Throwable mergeFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.newBuilder().mergeFrom(byteString.toByteArray()));
++
++ assertThat(parseFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ assertThat(mergeFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
++ @Test
++ public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception {
++ byte[] bytes = generateNestingGroups(101).toByteArray();
++
++ Throwable parseFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.parseFrom(new ByteArrayInputStream(bytes)));
++ Throwable mergeFromThrown =
++ assertThrows(
++ InvalidProtocolBufferException.class,
++ () -> MapContainer.newBuilder().mergeFrom(new ByteArrayInputStream(bytes)));
++
++ assertThat(parseFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ assertThat(mergeFromThrown)
++ .hasMessageThat()
++ .contains("Protocol message had too many levels of nesting");
++ }
++
+ @Test
+ public void testParseFromByteBuffer_extensions() throws Exception {
+ TestAllExtensionsLite message =
+@@ -2815,4 +3020,31 @@ public class LiteTest {
+ }
+ return false;
+ }
++
++ private static ByteString generateNestingGroups(int num) throws IOException {
++ int groupTap = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP);
++ ByteString.Output byteStringOutput = ByteString.newOutput();
++ CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput);
++ for (int i = 0; i < num; i++) {
++ codedOutput.writeInt32NoTag(groupTap);
++ }
++ codedOutput.flush();
++ return byteStringOutput.toByteString();
++ }
++
++ private static RecursiveMessage makeRecursiveMessage(int num) {
++ if (num == 0) {
++ return RecursiveMessage.getDefaultInstance();
++ } else {
++ return RecursiveMessage.newBuilder().setRecurse(makeRecursiveMessage(num - 1)).build();
++ }
++ }
++
++ private static RecursiveGroup makeRecursiveGroup(int num) {
++ if (num == 0) {
++ return RecursiveGroup.getDefaultInstance();
++ } else {
++ return RecursiveGroup.newBuilder().setRecurse(makeRecursiveGroup(num - 1)).build();
++ }
++ }
+ }
+--
+2.25.1
+
diff --git a/recipes-devtools/protobuf/protobuf/0001-Fix-build-on-mips-clang.patch b/recipes-devtools/protobuf/protobuf/0001-Fix-build-on-mips-clang.patch
new file mode 100644
index 0000000..9f6116c
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf/0001-Fix-build-on-mips-clang.patch
@@ -0,0 +1,26 @@
+From 08e46feb6553af670754e65d94c3bb6fcd4e0cf9 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sun, 31 Oct 2021 23:39:44 -0700
+Subject: [PATCH] Fix build on mips/clang
+
+clang13 crashes on mips, until its fixed upstream disable tailcall on
+mips
+
+https://bugs.llvm.org/show_bug.cgi?id=52367
+
+Upstream-Status: Inappropriate [Clang workaround]
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ src/google/protobuf/port_def.inc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/src/google/protobuf/port_def.inc
++++ b/src/google/protobuf/port_def.inc
+@@ -255,6 +255,7 @@
+ #error PROTOBUF_TAILCALL was previously defined
+ #endif
+ #if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \
++ !defined(__mips__) && \
+ !defined(_ARCH_PPC) && !defined(__wasm__) && \
+ !(defined(_MSC_VER) && defined(_M_IX86)) && \
+ !(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24)
diff --git a/recipes-devtools/protobuf/protobuf/0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch b/recipes-devtools/protobuf/protobuf/0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch
new file mode 100644
index 0000000..7c4bf26
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf/0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch
@@ -0,0 +1,61 @@
+From e3fa241637ab5a7fa78c0d474802134cff75f91e Mon Sep 17 00:00:00 2001
+From: Martin Jansa <Martin.Jansa@gmail.com>
+Date: Fri, 28 Jun 2019 13:50:52 +0000
+Subject: [PATCH] examples/Makefile: respect CXX,LDFLAGS variables, fix build
+ with gold
+
+* move pkg-config call to separate variable, so that the final version
+ of the whole command so it's shown in log.do_compile_ptest_base
+* add ../src/google/protobuf/.libs/timestamp.pb.o when linking
+ add_person_cpp otherwise it fails to link with gold:
+ i686-oe-linux-g++ -m32 -march=core2 -mtune=core2 -msse3 -mfpmath=sse --sysroot=core2-32-oe-linux/protobuf/3.8.0-r0/recipe-sysroot -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
+ /tmp/cccjSJQs.o:addressbook.pb.cc:scc_info_Person_addressbook_2eproto: error: undefined reference to 'scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto'
+ /tmp/cccjSJQs.o:addressbook.pb.cc:descriptor_table_addressbook_2eproto_deps: error: undefined reference to 'descriptor_table_google_2fprotobuf_2ftimestamp_2eproto'
+ collect2: error: ld returned 1 exit status
+ Makefile:43: recipe for target 'add_person_cpp' failed
+
+* and the same with list_people_cpp this time with pkg-config already through the variable:
+ i686-oe-linux-g++ -m32 -march=core2 -mtune=core2 -msse3 -mfpmath=sse --sysroot=core2-32-oe-linux/protobuf/3.8.0-r0/recipe-sysroot -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -pthread -Icore2-32-oe-linux/protobuf/3.8.0-r0/git/src -Lcore2-32-oe-linux/protobuf/3.8.0-r0/git/src/.libs -Lcore2-32-oe-linux/protobuf/3.8.0-r0/recipe-sysroot/usr/lib -lprotobuf list_people.cc addressbook.pb.cc -o list_people_cpp
+ /tmp/ccpaI5Su.o:addressbook.pb.cc:scc_info_Person_addressbook_2eproto: error: undefined reference to 'scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto'
+ /tmp/ccpaI5Su.o:addressbook.pb.cc:descriptor_table_addressbook_2eproto_deps: error: undefined reference to 'descriptor_table_google_2fprotobuf_2ftimestamp_2eproto'
+ collect2: error: ld returned 1 exit status
+ Makefile:49: recipe for target 'list_people_cpp' failed
+
+Upstream-Status: Pending
+Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
+Signed-off-by: Leon Anavi <leon.anavi@konsulko.com>
+
+---
+ examples/Makefile | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/examples/Makefile b/examples/Makefile
+index ef7a4ef58..7206e14e1 100644
+--- a/examples/Makefile
++++ b/examples/Makefile
+@@ -2,6 +2,8 @@
+
+ .PHONY: all cpp java python clean
+
++PROTOBUF := $(shell pkg-config --cflags --libs protobuf)
++
+ all: cpp java python
+
+ cpp: add_person_cpp list_people_cpp
+@@ -41,11 +43,11 @@ protoc_middleman_dart: addressbook.proto
+
+ add_person_cpp: add_person.cc protoc_middleman
+ pkg-config --cflags protobuf # fails if protobuf is not installed
+- c++ -std=c++14 add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
++ $(CXX) $(CXXFLAGS) $(LDFLAGS) ../src/google/protobuf/.libs/timestamp.pb.o $(PROTOBUF) add_person.cc addressbook.pb.cc -o add_person_cpp #$(CXX) -std=c++17 $(PROTOBUF) add_person.cc addressbook.pb.cc -o add_person_cpp
+
+ list_people_cpp: list_people.cc protoc_middleman
+ pkg-config --cflags protobuf # fails if protobuf is not installed
+- c++ -std=c++14 list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
++ $(CXX) $(CXXFLAGS) $(LDFLAGS) ../src/google/protobuf/.libs/timestamp.pb.o $(PROTOBUF) list_people.cc addressbook.pb.cc -o list_people_cpp #$(CXX) -std=c++17 $(PROTOBUF) list_people.cc addressbook.pb.cc -o list_people_cpp
+
+ add_person_dart: add_person.dart protoc_middleman_dart
+
+--
+2.34.1
+
diff --git a/recipes-devtools/protobuf/protobuf/run-ptest b/recipes-devtools/protobuf/protobuf/run-ptest
new file mode 100644
index 0000000..b3b2278
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf/run-ptest
@@ -0,0 +1,38 @@
+#!/bin/bash
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+TEST_FILE="/tmp/test.data"
+
+RETVAL=0
+# Test every writing test application
+for write_exe_full_path in ${DIR}/add_person_*; do
+ if [ -x "${write_exe_full_path}" ]; then
+ write_exe=`basename ${write_exe_full_path}`
+ echo "Generating new test file using ${write_exe}..."
+ printf "1234\nname\nname@example.com\n" | ${write_exe_full_path} "${TEST_FILE}"
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] || exit $RETVAL
+
+ # Test every reading test application
+ for read_exe_full_path in ${DIR}/list_people_*; do
+ read_exe=`basename ${read_exe_full_path}`
+ echo "Test: Write with ${write_exe}; Read with ${read_exe}..."
+ if [ -x "${read_exe_full_path}" ]; then
+ ${read_exe_full_path} "${TEST_FILE}"
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] || exit $RETVAL
+ fi
+ done
+
+ # Cleanup...
+ if [ -e "${TEST_FILE}" ]; then
+ rm "${TEST_FILE}"
+ fi
+ fi
+done
+
+if [ $RETVAL -eq 0 ] ; then
+ echo "PASS: protobuf"
+else
+ echo "FAIL: protobuf"
+fi
+
diff --git a/recipes-devtools/protobuf/protobuf_4.25.3.bb b/recipes-devtools/protobuf/protobuf_4.25.3.bb
new file mode 100644
index 0000000..acc35db
--- /dev/null
+++ b/recipes-devtools/protobuf/protobuf_4.25.3.bb
@@ -0,0 +1,119 @@
+SUMMARY = "Protocol Buffers - structured data serialisation mechanism"
+DESCRIPTION = "Protocol Buffers are a way of encoding structured data in an \
+efficient yet extensible format. Google uses Protocol Buffers for almost \
+all of its internal RPC protocols and file formats."
+HOMEPAGE = "https://github.com/google/protobuf"
+SECTION = "console/tools"
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b"
+
+DEPENDS = "zlib abseil-cpp"
+DEPENDS:append:class-target = " protobuf-native"
+
+SRCREV = "4a2aef570deb2bfb8927426558701e8bfc26f2a4"
+
+SRC_URI = "gitsm://github.com/protocolbuffers/protobuf.git;branch=25.x;protocol=https \
+ file://run-ptest \
+ file://0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch \
+ file://0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch \
+ "
+SRC_URI:append:mips:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch "
+SRC_URI:append:mipsel:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch "
+
+S = "${WORKDIR}/git"
+
+inherit cmake pkgconfig ptest
+
+PACKAGECONFIG ??= ""
+PACKAGECONFIG:class-native ?= "compiler"
+PACKAGECONFIG:class-nativesdk ?= "compiler"
+PACKAGECONFIG[python] = ",,"
+PACKAGECONFIG[compiler] = "-Dprotobuf_BUILD_PROTOC_BINARIES=ON,-Dprotobuf_BUILD_PROTOC_BINARIES=OFF"
+
+EXTRA_OECMAKE += "\
+ -Dprotobuf_BUILD_SHARED_LIBS=ON \
+ -Dprotobuf_BUILD_LIBPROTOC=ON \
+ -Dprotobuf_BUILD_TESTS=OFF \
+ -Dprotobuf_BUILD_EXAMPLES=OFF \
+ -Dprotobuf_ABSL_PROVIDER="package" \
+"
+
+TEST_SRC_DIR = "examples"
+LANG_SUPPORT = "cpp ${@bb.utils.contains('PACKAGECONFIG', 'python', 'python', '', d)}"
+
+do_compile_ptest() {
+ mkdir -p "${B}/${TEST_SRC_DIR}"
+
+ # Add the location of the cross-compiled header and library files
+ # which haven't been installed yet.
+ cp "${B}/protobuf.pc" "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ cp ${S}/${TEST_SRC_DIR}/*.cc "${B}/${TEST_SRC_DIR}/"
+ cp ${S}/${TEST_SRC_DIR}/*.proto "${B}/${TEST_SRC_DIR}/"
+ cp ${S}/${TEST_SRC_DIR}/*.py "${B}/${TEST_SRC_DIR}/"
+ cp ${S}/${TEST_SRC_DIR}/Makefile "${B}/${TEST_SRC_DIR}/"
+ # Adapt protobuf.pc
+ sed -e 's|libdir=|libdir=${PKG_CONFIG_SYSROOT_DIR}|' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Cflags:|Cflags: -I${S}/src |' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Cflags:|Cflags: -I${WORKDIR}/recipe-sysroot${includedir} |' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Libs:|Libs: -L${B}|' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Libs:|Libs: -L${WORKDIR}/recipe-sysroot/usr/lib |' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Libs:|Libs: -labsl_log_internal_check_op |' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ sed -e 's|Libs:|Libs: -labsl_log_internal_message |' -i "${B}/${TEST_SRC_DIR}/protobuf.pc"
+ # Adapt uf8_range.pc
+ cp "${B}/third_party/utf8_range/utf8_range.pc" "${B}/${TEST_SRC_DIR}/utf8_range.pc"
+ sed -e 's|libdir=|libdir=${PKG_CONFIG_SYSROOT_DIR}|' -i "${B}/${TEST_SRC_DIR}/utf8_range.pc"
+ sed -e 's|Libs:|Libs= -L${B}/third_party/utf8_range |' -i "${B}/${TEST_SRC_DIR}/utf8_range.pc"
+ # Until out-of-tree build of examples is supported, we have to use this approach
+ sed -e 's|../src/google/protobuf/.libs/timestamp.pb.o|${B}/CMakeFiles/libprotobuf.dir/src/google/protobuf/timestamp.pb.cc.o|' -i "${B}/${TEST_SRC_DIR}/Makefile"
+ export PKG_CONFIG_PATH="${B}/${TEST_SRC_DIR}"
+
+ # Save the pkgcfg sysroot variable, and update it to nothing so
+ # that it doesn't append the sysroot to the beginning of paths.
+ # The header and library files aren't installed to the target
+ # system yet. So the absolute paths were specified above.
+ save_pkg_config_sysroot_dir=$PKG_CONFIG_SYSROOT_DIR
+ export PKG_CONFIG_SYSROOT_DIR=
+
+ # Compile the tests
+ for lang in ${LANG_SUPPORT}; do
+ oe_runmake -C "${B}/${TEST_SRC_DIR}" ${lang}
+ done
+
+ # Restore the pkgconfig sysroot variable
+ export PKG_CONFIG_SYSROOT_DIR=$save_pkg_config_sysroot_dir
+}
+
+do_install_ptest() {
+ local olddir=`pwd`
+
+ cd "${S}/${TEST_SRC_DIR}"
+ install -d "${D}/${PTEST_PATH}"
+ for i in add_person* list_people*; do
+ if [ -x "$i" ]; then
+ install "$i" "${D}/${PTEST_PATH}"
+ fi
+ done
+ cp "${B}/${TEST_SRC_DIR}/addressbook_pb2.py" "${D}/${PTEST_PATH}"
+ cd "$olddir"
+}
+
+PACKAGE_BEFORE_PN = "${PN}-compiler ${PN}-lite"
+
+FILES:${PN}-compiler = "${bindir} ${libdir}/libprotoc${SOLIBS}"
+FILES:${PN}-lite = "${libdir}/libprotobuf-lite${SOLIBS}"
+
+# CMake requires protoc binary to exist in sysroot, even if it has wrong architecture.
+SYSROOT_DIRS += "${bindir}"
+
+RDEPENDS:${PN}-compiler = "${PN}"
+RDEPENDS:${PN}-dev += "${PN}-compiler"
+RDEPENDS:${PN}-ptest = "bash ${@bb.utils.contains('PACKAGECONFIG', 'python', 'python3-protobuf', '', d)}"
+
+MIPS_INSTRUCTION_SET = "mips"
+
+BBCLASSEXTEND = "native nativesdk"
+
+LDFLAGS:append:arm = " -latomic"
+LDFLAGS:append:mips = " -latomic"
+LDFLAGS:append:powerpc = " -latomic"
+LDFLAGS:append:mipsel = " -latomic"
diff --git a/recipes-devtools/python/python3-protobuf_4.25.3.bb b/recipes-devtools/python/python3-protobuf_4.25.3.bb
new file mode 100644
index 0000000..c234ce5
--- /dev/null
+++ b/recipes-devtools/python/python3-protobuf_4.25.3.bb
@@ -0,0 +1,45 @@
+DESCRIPTION = "Protocol Buffers"
+HOMEPAGE = "https://developers.google.com/protocol-buffers/"
+SECTION = "devel/python"
+
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://PKG-INFO;beginline=8;endline=8;md5=53dbfa56f61b90215a9f8f0d527c043d"
+
+inherit pypi setuptools3
+SRC_URI[sha256sum] = "25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"
+
+# http://errors.yoctoproject.org/Errors/Details/184715/
+# Can't find required file: ../src/google/protobuf/descriptor.proto
+CLEANBROKEN = "1"
+
+UPSTREAM_CHECK_REGEX = "protobuf/(?P<pver>\d+(\.\d+)+)/"
+
+DEPENDS += "protobuf"
+
+RDEPENDS:${PN} += " \
+ python3-datetime \
+ python3-json \
+ python3-logging \
+ python3-netclient \
+ python3-numbers \
+ python3-pkgutil \
+ python3-unittest \
+"
+
+# For usage in other recipies when compiling protobuf files (e.g. by grpcio-tools)
+BBCLASSEXTEND = "native nativesdk"
+
+DISTUTILS_BUILD_ARGS += "--cpp_implementation"
+DISTUTILS_INSTALL_ARGS += "--cpp_implementation"
+
+do_compile:prepend:class-native () {
+ export KOKORO_BUILD_NUMBER="1"
+}
+
+do_install:append () {
+ # Remove useless and problematic .pth file. python3-protobuf is installed in the standard
+ # location of site packages. No need for such .pth file.
+ # NOTE: do not drop this removal until the following issue in upstream cpython is resolved:
+ # https://github.com/python/cpython/issues/122220
+ rm -f ${D}${PYTHON_SITEPACKAGES_DIR}/protobuf-*-nspkg.pth
+}