Compare commits

..

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
648bb4fce7
!134 [sync] PR-133: append fix CVE-2024-7254
From: @openeuler-sync-bot 
Reviewed-by: @xuxuepeng 
Signed-off-by: @xuxuepeng
2024-10-08 02:36:11 +00:00
zhangxianting
a60ad72d3c append fix CVE-2024-7254
(cherry picked from commit f79ad42784662453fd8521d56dfde0c0d78f1d34)
2024-09-26 20:26:36 +08:00
openeuler-ci-bot
087caeb169
!132 [sync] PR-128: fix CVE-2024-7254
From: @openeuler-sync-bot 
Reviewed-by: @jianminw 
Signed-off-by: @jianminw
2024-09-25 00:53:02 +00:00
zhangxianting
202c28e2a5 fix CVE-2024-7254
(cherry picked from commit 9a7fc3d97bf25458b652f79a7e2c409b1507777f)
2024-09-24 09:56:38 +08:00
openeuler-ci-bot
b2ab0c49d6
!126 bugfix for devel package packaging file differences
From: @taotao-sauce 
Reviewed-by: @xuxuepeng 
Signed-off-by: @xuxuepeng
2024-08-06 01:19:29 +00:00
zhongtao
efb04135cf bugfix for devel package packaging file differences
Signed-off-by: zhongtao <zhongtao17@huawei.com>
2024-08-05 19:22:21 +08:00
openeuler-ci-bot
1b6950362f
!125 [sync] PR-122: add coverage compile option
From: @openeuler-sync-bot 
Reviewed-by: @xuxuepeng 
Signed-off-by: @xuxuepeng
2024-07-30 03:35:09 +00:00
zhongtao
e959afd2a9 add coverage compile option
Signed-off-by: zhongtao <zhongtao17@huawei.com>
(cherry picked from commit f624b9053e55e9e6c3c91c35b1e14eef86bbb74a)
2024-07-30 10:28:58 +08:00
openeuler-ci-bot
19a8943065
!123 [sync] PR-119: disable java for loongarch64
From: @openeuler-sync-bot 
Reviewed-by: @xuxuepeng 
Signed-off-by: @xuxuepeng
2024-07-29 12:03:45 +00:00
Wenlong Zhang
ea9e56c8fe disable java for loongarch64
(cherry picked from commit af464fc2d7b259bbc4ad75b52f593a61d7043a54)
2024-07-29 14:20:03 +08:00
4 changed files with 916 additions and 12 deletions

View File

@ -0,0 +1,27 @@
From ea6d56c3518dc3af0f326f52a266bc0986d8635c Mon Sep 17 00:00:00 2001
From: zhongtao <zhongtao17@huawei.com>
Date: Thu, 25 Jul 2024 21:42:22 +0800
Subject: [PATCH] protobuf: add coverage compile option
Signed-off-by: zhongtao <zhongtao17@huawei.com>
---
CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d17f09d..0b169f3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,9 @@ cmake_minimum_required(VERSION 3.10...3.26)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-z,now -fstack-check -fPIE")
set(CMAKE_EXE_LINKER_FLAGS "-pie")
+if (ENABLE_CONVERAGE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
# Revert to old behavior for MSVC debug symbols.
if(POLICY CMP0141)
--
2.25.1

View File

@ -0,0 +1,146 @@
From cc8b3483a5584b3301e3d43d17eb59704857ffaa Mon Sep 17 00:00:00 2001
From: Protobuf Team Bot <protobuf-github-bot@google.com>
Date: Thu, 18 Jul 2024 07:41:01 -0700
Subject: [PATCH] Internal change
PiperOrigin-RevId: 653615736
---
.../core/src/main/java/com/google/protobuf/ArrayDecoders.java | 3 +--
.../com/google/protobuf/InvalidProtocolBufferException.java | 2 +-
.../core/src/main/java/com/google/protobuf/MessageSchema.java | 3 +++
.../src/main/java/com/google/protobuf/MessageSetSchema.java | 1 +
.../src/main/java/com/google/protobuf/UnknownFieldSchema.java | 3 +--
java/lite/src/test/java/com/google/protobuf/LiteTest.java | 3 +++
src/google/protobuf/unittest_lite.proto | 4 ++++
7 files changed, 14 insertions(+), 5 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 f3241de..9bf1439 100644
--- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
+++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
@@ -24,8 +24,7 @@ import java.io.IOException;
@CheckReturnValue
final class ArrayDecoders {
- private ArrayDecoders() {
- }
+ private ArrayDecoders() {}
/**
* A helper used to return multiple values in a Java function. Java doesn't natively support
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 5d10e48..dbcb9e8 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -132,7 +132,7 @@ public class InvalidProtocolBufferException extends IOException {
static InvalidProtocolBufferException recursionLimitExceeded() {
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. "
- + "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+ + "Use setRecursionLimit() to increase the recursion depth limit.");
}
static InvalidProtocolBufferException sizeLimitExceeded() {
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 de3890f..f8f79fc 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
@@ -3006,6 +3006,7 @@ final class MessageSchema<T> implements Schema<T> {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
}
// Unknown field.
+
if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
continue;
}
@@ -3381,6 +3382,7 @@ final class MessageSchema<T> implements Schema<T> {
if (unknownFields == null) {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
}
+
if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
return;
}
@@ -3397,6 +3399,7 @@ final class MessageSchema<T> implements Schema<T> {
if (unknownFields == null) {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
}
+
if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
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 eec3acd..a17037e 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
@@ -278,6 +278,7 @@ final class MessageSetSchema<T> implements Schema<T> {
reader, extension, extensionRegistry, extensions);
return true;
} else {
+
return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader);
}
} else {
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 c4ec645..a43bc2a 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
@@ -55,7 +55,6 @@ abstract class UnknownFieldSchema<T, B> {
/** Marks unknown fields as immutable. */
abstract void makeImmutable(Object message);
- /** Merges one field into the unknown fields. */
final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException {
int tag = reader.getTag();
int fieldNumber = WireFormat.getTagFieldNumber(tag);
@@ -88,7 +87,7 @@ abstract class UnknownFieldSchema<T, B> {
}
}
- final void mergeFrom(B unknownFields, Reader reader) throws IOException {
+ private final void mergeFrom(B unknownFields, Reader reader) throws IOException {
while (true) {
if (reader.getFieldNumber() == Reader.READ_DONE
|| !mergeOneFieldFrom(unknownFields, reader)) {
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 754ed7d..b42a4b9 100644
--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -10,12 +10,14 @@ package com.google.protobuf;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertThrows;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.UnittestImportLite.ImportEnumLite;
import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
import com.google.protobuf.UnittestLite.ForeignEnumLite;
import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.RecursiveGroup;
import com.google.protobuf.UnittestLite.RecursiveMessage;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
@@ -50,6 +52,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index 1848a2a..af6febf 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -505,3 +505,7 @@ message RecursiveMessage {
optional RecursiveMessage recurse = 1;
optional bytes payload = 2;
}
+
+message RecursiveGroup {
+ RecursiveGroup recurse = 1 [features.message_encoding = DELIMITED];
+}
--
2.43.0

View File

@ -0,0 +1,696 @@
From 4728531c162f2f9e8c2ca1add713cfee2db6be3b 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
---
.../com/google/protobuf/ArrayDecoders.java | 28 +++
.../com/google/protobuf/CodedInputStream.java | 18 +-
.../com/google/protobuf/MessageSchema.java | 12 +-
.../com/google/protobuf/MessageSetSchema.java | 3 +-
.../google/protobuf/UnknownFieldSchema.java | 29 ++-
.../google/protobuf/CodedInputStreamTest.java | 158 ++++++++++++
.../java/com/google/protobuf/LiteTest.java | 232 ++++++++++++++++++
7 files changed, 466 insertions(+), 14 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 9bf1439..bf5f922 100644
--- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
+++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
@@ -23,6 +23,10 @@ import java.io.IOException;
*/
@CheckReturnValue
final class ArrayDecoders {
+ static final int DEFAULT_RECURSION_LIMIT = 100;
+
+ @SuppressWarnings("NonFinalStaticField")
+ private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT;
private ArrayDecoders() {}
@@ -37,6 +41,7 @@ final class ArrayDecoders {
public long long1;
public Object object1;
public final ExtensionRegistryLite extensionRegistry;
+ public int recursionDepth;
Registers() {
this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry();
@@ -244,7 +249,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;
}
@@ -262,8 +270,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;
}
@@ -1024,6 +1035,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;
@@ -1032,6 +1045,7 @@ final class ArrayDecoders {
}
position = decodeUnknownField(lastTag, data, position, limit, child, registers);
}
+ registers.recursionDepth--;
if (position > limit || lastTag != endGroup) {
throw InvalidProtocolBufferException.parseFailure();
}
@@ -1078,4 +1092,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 8f1ac73..f8df4d3 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -2180,7 +2180,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,9 +2197,16 @@ 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 f8f79fc..5ad6762 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
@@ -3006,8 +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;
}
}
@@ -3382,8 +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;
@@ -3399,8 +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 a17037e..ec37d41 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
@@ -278,8 +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 a43bc2a..80602b1 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);
@@ -55,7 +60,9 @@ abstract class UnknownFieldSchema<T, B> {
/** Marks unknown fields as immutable. */
abstract void makeImmutable(Object message);
- final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException {
+ /** Merges one field into the unknown fields. */
+ final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth)
+ throws IOException {
int tag = reader.getTag();
int fieldNumber = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
@@ -74,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();
}
@@ -87,10 +99,11 @@ abstract class UnknownFieldSchema<T, B> {
}
}
- private final void mergeFrom(B unknownFields, Reader reader) throws IOException {
+ private 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;
}
}
@@ -107,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 2de3273..70525bb 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,9 @@ 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 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 +37,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 +126,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 +680,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 b42a4b9..8fed7cd 100644
--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -2462,6 +2462,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 =
@@ -2818,4 +3023,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.43.0

View File

@ -2,12 +2,16 @@
# Build -python subpackage
%bcond_without python
# Build -java subpackage
%ifarch loongarch64
%bcond_with java
%else
%bcond_without java
%endif
Summary: Protocol Buffers - Google's data interchange format
Name: protobuf
Version: 25.1
Release: 3
Release: 7
License: BSD
URL: https://github.com/protocolbuffers/protobuf
Source: https://github.com/protocolbuffers/protobuf/releases/download/v%{version}%{?rcver}/%{name}-all-%{version}%{?rcver}.tar.gz
@ -16,6 +20,9 @@ Source1: protobuf-init.el
Patch9000: 0001-add-secure-compile-option.patch
Patch9001: 0002-Fix-CC-compiler-support.patch
Patch9002: 0003-protobuf-add-coverage-compile-option.patch
Patch9003: 0004-backport-CVE-2024-7254-1.patch
Patch9004: 0004-backport-CVE-2024-7254-2.patch
BuildRequires: cmake gcc-c++ emacs zlib-devel gmock-devel gtest-devel jsoncpp-devel
BuildRequires: fdupes pkgconfig python-rpm-macros pkgconfig(zlib) ninja-build
@ -339,21 +346,22 @@ install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir}
%doc README.md
%files devel
%doc CONTRIBUTORS.txt README.md
%{_bindir}/protoc*
%{_includedir}/google
%{_includedir}/*.h
%{_libdir}/cmake/protobuf
%{_libdir}/cmake/utf8_range
%{_libdir}/pkgconfig/*
%{_libdir}/libprotobuf-lite.so
%dir %{_includedir}/google
%{_includedir}/google/protobuf/
%{_includedir}/utf8_range.h
%{_includedir}/utf8_validity.h
%{_libdir}/libprotobuf.so
%{_libdir}/libprotoc.so
%{_libdir}/libutf8_range.a
%{_libdir}/libutf8_validity.a
%{_libdir}/pkgconfig/protobuf.pc
%{_libdir}/pkgconfig/utf8_range.pc
%doc examples/add_person.cc examples/addressbook.proto examples/list_people.cc examples/Makefile examples/README.md
%{_libdir}/libprotobuf.a
%{_libdir}/libprotoc.a
%{_datadir}/vim
%{_datadir}/vim/vimfiles/syntax/proto.vim
%{_libdir}/cmake/utf8_range
%{_libdir}/cmake/protobuf
%{_libdir}/libutf8_range.a
%{_libdir}/libutf8_validity.a
%{_includedir}/java/core/src/main/java/com/google/protobuf/java_features.proto
%files lite
@ -397,6 +405,33 @@ install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir}
%endif
%changelog
* Wed Sep 25 2024 zhangxianting <zhangxianting@uniontech.com> - 25.1-7
- Type:bugfix
- ID:NA
- SUG:NA
- DESC: append fix CVE-2024-7254
* Thu Sep 19 2024 zhangxianting <zhangxianting@uniontech.com> - 25.1-6
- Type:bugfix
- ID:NA
- SUG:NA
- DESC: fix CVE-2024-7254
* Mon Aug 05 2024 zhongtao <zhongtao17@huawei.com> - 25.1-5
- Type:bugfix
- ID:NA
- SUG:NA
- DESC: bugfix for devel package packaging file differences
* Thu Jul 25 2024 zhongtao <zhongtao17@huawei.com> - 25.1-4
- Type:bugfix
- ID:NA
- SUG:NA
- DESC: add coverage compile option
* Mon Apr 15 2024 Wenlong Zhang <zhangwenlong@loongson.cn> - 25.1-4
- disable java for loongarch64
* Tue Apr 09 2024 zhongtao <zhongtao17@huawei.com> - 25.1-3
- Type:bugfix
- ID:NA