Projects
openEuler:24.03:SP1:Everything
protobuf
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:protobuf.spec
Changed
@@ -7,7 +7,7 @@ Summary: Protocol Buffers - Google's data interchange format Name: protobuf Version: 25.1 -Release: 3 +Release: 4 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 +16,8 @@ Patch9000: 0001-add-secure-compile-option.patch Patch9001: 0002-Fix-CC-compiler-support.patch +Patch9002: 0003-backport-CVE-2024-7254-1.patch +Patch9003: 0003-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 @@ -397,6 +399,12 @@ %endif %changelog +* Thu Sep 19 2024 zhangxianting <zhangxianting@uniontech.com> - 25.1-4 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: fix CVE-2024-7254 + * Tue Apr 09 2024 zhongtao <zhongtao17@huawei.com> - 25.1-3 - Type:bugfix - ID:NA
View file
_service:tar_scm:0003-backport-CVE-2024-7254-1.patch
Added
@@ -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
_service:tar_scm:0003-backport-CVE-2024-7254-2.patch
Added
@@ -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 byte100000; ++ 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 byteNESTING_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 byteNESTING_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 byteNESTING_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 byteNESTING_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 +
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2