From 62193eb291a15f336c66a3e3eb1f95b94fc0d022 Mon Sep 17 00:00:00 2001 From: CoprDistGit Date: Mon, 22 Sep 2025 12:52:08 +0000 Subject: automatic import of protobuf --- 0001-add-secure-compile-option-in-Makefile.patch | 12 + 0001-add-secure-compile-option.patch | 27 - 0002-Fix-CC-compiler-support.patch | 29 - 0002-add-secure-compile-fs-check-in-Makefile.patch | 26 + 0003-protobuf-add-coverage-compile-option.patch | 27 - ...formance-of-parsing-unknown-fields-in-Jav.patch | 1272 ++++++++++++++++++++ 0007-add-coverage-compile-option.patch | 49 + protobuf.spec | 232 +--- 8 files changed, 1409 insertions(+), 265 deletions(-) create mode 100644 0001-add-secure-compile-option-in-Makefile.patch delete mode 100644 0001-add-secure-compile-option.patch delete mode 100644 0002-Fix-CC-compiler-support.patch create mode 100644 0002-add-secure-compile-fs-check-in-Makefile.patch delete mode 100644 0003-protobuf-add-coverage-compile-option.patch create mode 100644 0004-Improve-performance-of-parsing-unknown-fields-in-Jav.patch create mode 100644 0007-add-coverage-compile-option.patch diff --git a/0001-add-secure-compile-option-in-Makefile.patch b/0001-add-secure-compile-option-in-Makefile.patch new file mode 100644 index 0000000..988ba43 --- /dev/null +++ b/0001-add-secure-compile-option-in-Makefile.patch @@ -0,0 +1,12 @@ +diff --git a/src/Makefile.am b/src/Makefile.am +index f1099d9..9b7053b 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -19,6 +19,7 @@ PTHREAD_DEF = + endif + + PROTOBUF_VERSION = 25:0:0 ++PROTOBUF_OPT_FLAG += -Wl,-z,now + + if GCC + # Turn on all warnings except for sign comparison (we ignore sign comparison diff --git a/0001-add-secure-compile-option.patch b/0001-add-secure-compile-option.patch deleted file mode 100644 index 0594f0e..0000000 --- a/0001-add-secure-compile-option.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 4cf6dc9f628fc2c5b3478d70e15d4fab8a32ae86 Mon Sep 17 00:00:00 2001 -From: zhongtao -Date: Wed, 10 Apr 2024 11:43:51 +0800 -Subject: [PATCH] add secure compile option - -Signed-off-by: zhongtao ---- - CMakeLists.txt | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 4137ce2..d17f09d 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -2,6 +2,9 @@ - # to 3.26. - 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") -+ - # Revert to old behavior for MSVC debug symbols. - if(POLICY CMP0141) - cmake_policy(SET CMP0141 OLD) --- -2.25.1 - diff --git a/0002-Fix-CC-compiler-support.patch b/0002-Fix-CC-compiler-support.patch deleted file mode 100644 index d4f4440..0000000 --- a/0002-Fix-CC-compiler-support.patch +++ /dev/null @@ -1,29 +0,0 @@ -From b62fbe3852ea070f1bfbb048e71dfae70c7c71f0 Mon Sep 17 00:00:00 2001 -From: wangqiang -Date: Tue, 19 Mar 2024 18:54:13 +0800 -Subject: [PATCH] Fix CC compiler support - ---- - third_party/utf8_range/utf8_to_utf16/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/third_party/utf8_range/utf8_to_utf16/Makefile b/third_party/utf8_range/utf8_to_utf16/Makefile -index 853ffa4..30ef021 100644 ---- a/third_party/utf8_range/utf8_to_utf16/Makefile -+++ b/third_party/utf8_range/utf8_to_utf16/Makefile -@@ -1,10 +1,10 @@ --CC = gcc -+CC := ${CC} - CPPFLAGS = -g -O3 -Wall -march=native - - OBJS = main.o iconv.o naive.o - - utf8to16: ${OBJS} -- gcc $^ -o $@ -+ ${CC} $^ -o $@ - - .PHONY: clean - clean: --- -2.33.0 - diff --git a/0002-add-secure-compile-fs-check-in-Makefile.patch b/0002-add-secure-compile-fs-check-in-Makefile.patch new file mode 100644 index 0000000..9a5ff52 --- /dev/null +++ b/0002-add-secure-compile-fs-check-in-Makefile.patch @@ -0,0 +1,26 @@ +From dddceb14106499f9fca17e75cdce458a205b102c Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Sat, 20 Feb 2021 16:52:15 +0800 +Subject: [PATCH] add secure compile fs check in Makefile + +Signed-off-by: haozi007 +--- + src/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/Makefile.am b/src/Makefile.am +index 9b7053b..e447b05 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -19,7 +19,7 @@ PTHREAD_DEF = + endif + + PROTOBUF_VERSION = 25:0:0 +-PROTOBUF_OPT_FLAG += -Wl,-z,now ++PROTOBUF_OPT_FLAG += -Wl,-z,now -fstack-check + + if GCC + # Turn on all warnings except for sign comparison (we ignore sign comparison +-- +2.25.1 + diff --git a/0003-protobuf-add-coverage-compile-option.patch b/0003-protobuf-add-coverage-compile-option.patch deleted file mode 100644 index 7a6aa17..0000000 --- a/0003-protobuf-add-coverage-compile-option.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ea6d56c3518dc3af0f326f52a266bc0986d8635c Mon Sep 17 00:00:00 2001 -From: zhongtao -Date: Thu, 25 Jul 2024 21:42:22 +0800 -Subject: [PATCH] protobuf: add coverage compile option - -Signed-off-by: zhongtao ---- - 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 - diff --git a/0004-Improve-performance-of-parsing-unknown-fields-in-Jav.patch b/0004-Improve-performance-of-parsing-unknown-fields-in-Jav.patch new file mode 100644 index 0000000..a56f88d --- /dev/null +++ b/0004-Improve-performance-of-parsing-unknown-fields-in-Jav.patch @@ -0,0 +1,1272 @@ +From 8890b0a81e2f4b1de4a33cc6d81aba07655bde1a Mon Sep 17 00:00:00 2001 +From: wangxiaochao +Date: Thu, 24 Mar 2022 20:54:36 +0800 +Subject: [PATCH] Improve performance of parsing unknown fields in Java + +Signed-off-by: wangxiaochao + +--- + Makefile.am | 1 + + .../com/google/protobuf/UnknownFieldSet.java | 427 +++++++++--------- + .../UnknownFieldSetPerformanceTest.java | 78 ++++ + .../google/protobuf/UnknownFieldSetTest.java | 171 ++++++- + java/lite/pom.xml | 3 +- + 5 files changed, 466 insertions(+), 214 deletions(-) + create mode 100644 java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java + +diff --git a/Makefile.am b/Makefile.am +index 4fc706b..908c2d2 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -487,6 +487,7 @@ java_EXTRA_DIST= + java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java \ + java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \ + java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \ ++ java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java \ + java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \ + java/core/src/test/java/com/google/protobuf/Utf8Test.java \ + java/core/src/test/java/com/google/protobuf/Utf8Utils.java \ +diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +index ba2f9df..5c482d6 100644 +--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java ++++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +@@ -43,13 +43,13 @@ import java.util.Map; + import java.util.TreeMap; + + /** +- * {@code UnknownFieldSet} is used to keep track of fields which were seen when parsing a protocol ++ * {@code UnknownFieldSet} keeps track of fields which were seen when parsing a protocol + * message but whose field numbers or types are unrecognized. This most frequently occurs when new + * fields are added to a message type and then messages containing those fields are read by old + * software that was compiled before the new types were added. + * + *

Every {@link Message} contains an {@code UnknownFieldSet} (and every {@link Message.Builder} +- * contains an {@link Builder}). ++ * contains a {@link Builder}). + * + *

Most users will never need to use this class. + * +@@ -57,9 +57,13 @@ import java.util.TreeMap; + */ + public final class UnknownFieldSet implements MessageLite { + +- private UnknownFieldSet() { +- fields = null; +- fieldsDescending = null; ++ private final TreeMap fields; ++ ++ /** ++ * Construct an {@code UnknownFieldSet} around the given map. ++ */ ++ UnknownFieldSet(TreeMap fields) { ++ this.fields = fields; + } + + /** Create a new {@link Builder}. */ +@@ -68,7 +72,7 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Create a new {@link Builder} and initialize it to be a copy of {@code copyFrom}. */ +- public static Builder newBuilder(final UnknownFieldSet copyFrom) { ++ public static Builder newBuilder(UnknownFieldSet copyFrom) { + return newBuilder().mergeFrom(copyFrom); + } + +@@ -83,25 +87,11 @@ public final class UnknownFieldSet implements MessageLite { + } + + private static final UnknownFieldSet defaultInstance = +- new UnknownFieldSet( +- Collections.emptyMap(), Collections.emptyMap()); +- +- /** +- * Construct an {@code UnknownFieldSet} around the given map. The map is expected to be immutable. +- */ +- UnknownFieldSet(final Map fields, final Map fieldsDescending) { +- this.fields = fields; +- this.fieldsDescending = fieldsDescending; +- } +- +- private final Map fields; +- +- /** A copy of {@link #fields} who's iterator order is reversed. */ +- private final Map fieldsDescending; ++ new UnknownFieldSet(new TreeMap()); + + + @Override +- public boolean equals(final Object other) { ++ public boolean equals(Object other) { + if (this == other) { + return true; + } +@@ -110,29 +100,33 @@ public final class UnknownFieldSet implements MessageLite { + + @Override + public int hashCode() { ++ if (fields.isEmpty()) { // avoid allocation of iterator. ++ // This optimization may not be helpful but it is needed for the allocation tests to pass. ++ return 0; ++ } + return fields.hashCode(); + } + + /** Get a map of fields in the set by number. */ + public Map asMap() { +- return fields; ++ return (Map) fields.clone(); + } + + /** Check if the given field number is present in the set. */ +- public boolean hasField(final int number) { ++ public boolean hasField(int number) { + return fields.containsKey(number); + } + + /** Get a field by number. Returns an empty field if not present. Never returns {@code null}. */ +- public Field getField(final int number) { +- final Field result = fields.get(number); ++ public Field getField(int number) { ++ Field result = fields.get(number); + return (result == null) ? Field.getDefaultInstance() : result; + } + + /** Serializes the set and writes it to {@code output}. */ + @Override +- public void writeTo(final CodedOutputStream output) throws IOException { +- for (final Map.Entry entry : fields.entrySet()) { ++ public void writeTo(CodedOutputStream output) throws IOException { ++ for (Map.Entry entry : fields.entrySet()) { + Field field = entry.getValue(); + field.writeTo(entry.getKey(), output); + } +@@ -154,10 +148,10 @@ public final class UnknownFieldSet implements MessageLite { + @Override + public ByteString toByteString() { + try { +- final ByteString.CodedBuilder out = ByteString.newCodedBuilder(getSerializedSize()); ++ ByteString.CodedBuilder out = ByteString.newCodedBuilder(getSerializedSize()); + writeTo(out.getCodedOutput()); + return out.build(); +- } catch (final IOException e) { ++ } catch (IOException e) { + throw new RuntimeException( + "Serializing to a ByteString threw an IOException (should never happen).", e); + } +@@ -170,12 +164,12 @@ public final class UnknownFieldSet implements MessageLite { + @Override + public byte[] toByteArray() { + try { +- final byte[] result = new byte[getSerializedSize()]; +- final CodedOutputStream output = CodedOutputStream.newInstance(result); ++ byte[] result = new byte[getSerializedSize()]; ++ CodedOutputStream output = CodedOutputStream.newInstance(result); + writeTo(output); + output.checkNoSpaceLeft(); + return result; +- } catch (final IOException e) { ++ } catch (IOException e) { + throw new RuntimeException( + "Serializing to a byte array threw an IOException (should never happen).", e); + } +@@ -186,16 +180,16 @@ public final class UnknownFieldSet implements MessageLite { + * {@link #writeTo(CodedOutputStream)}. + */ + @Override +- public void writeTo(final OutputStream output) throws IOException { +- final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); ++ public void writeTo(OutputStream output) throws IOException { ++ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); + writeTo(codedOutput); + codedOutput.flush(); + } + + @Override + public void writeDelimitedTo(OutputStream output) throws IOException { +- final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); +- codedOutput.writeRawVarint32(getSerializedSize()); ++ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); ++ codedOutput.writeUInt32NoTag(getSerializedSize()); + writeTo(codedOutput); + codedOutput.flush(); + } +@@ -204,15 +198,17 @@ public final class UnknownFieldSet implements MessageLite { + @Override + public int getSerializedSize() { + int result = 0; +- for (final Map.Entry entry : fields.entrySet()) { +- result += entry.getValue().getSerializedSize(entry.getKey()); ++ if (!fields.isEmpty()) { ++ for (Map.Entry entry : fields.entrySet()) { ++ result += entry.getValue().getSerializedSize(entry.getKey()); ++ } + } + return result; + } + + /** Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. */ +- public void writeAsMessageSetTo(final CodedOutputStream output) throws IOException { +- for (final Map.Entry entry : fields.entrySet()) { ++ public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { ++ for (Map.Entry entry : fields.entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), output); + } + } +@@ -221,7 +217,7 @@ public final class UnknownFieldSet implements MessageLite { + void writeTo(Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write fields in descending order. +- for (Map.Entry entry : fieldsDescending.entrySet()) { ++ for (Map.Entry entry : fields.descendingMap().entrySet()) { + entry.getValue().writeTo(entry.getKey(), writer); + } + } else { +@@ -233,15 +229,15 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */ +- void writeAsMessageSetTo(final Writer writer) throws IOException { ++ void writeAsMessageSetTo(Writer writer) throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write fields in descending order. +- for (final Map.Entry entry : fieldsDescending.entrySet()) { ++ for (Map.Entry entry : fields.descendingMap().entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer); + } + } else { + // Write fields in ascending order. +- for (final Map.Entry entry : fields.entrySet()) { ++ for (Map.Entry entry : fields.entrySet()) { + entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer); + } + } +@@ -250,7 +246,7 @@ public final class UnknownFieldSet implements MessageLite { + /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */ + public int getSerializedSizeAsMessageSet() { + int result = 0; +- for (final Map.Entry entry : fields.entrySet()) { ++ for (Map.Entry entry : fields.entrySet()) { + result += entry.getValue().getSerializedSizeAsMessageSetExtension(entry.getKey()); + } + return result; +@@ -264,23 +260,23 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Parse an {@code UnknownFieldSet} from the given input stream. */ +- public static UnknownFieldSet parseFrom(final CodedInputStream input) throws IOException { ++ public static UnknownFieldSet parseFrom(CodedInputStream input) throws IOException { + return newBuilder().mergeFrom(input).build(); + } + + /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ +- public static UnknownFieldSet parseFrom(final ByteString data) ++ public static UnknownFieldSet parseFrom(ByteString data) + throws InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).build(); + } + + /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ +- public static UnknownFieldSet parseFrom(final byte[] data) throws InvalidProtocolBufferException { ++ public static UnknownFieldSet parseFrom(byte[] data) throws InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).build(); + } + + /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ +- public static UnknownFieldSet parseFrom(final InputStream input) throws IOException { ++ public static UnknownFieldSet parseFrom(InputStream input) throws IOException { + return newBuilder().mergeFrom(input).build(); + } + +@@ -309,64 +305,43 @@ public final class UnknownFieldSet implements MessageLite { + // This constructor should never be called directly (except from 'create'). + private Builder() {} + +- private Map fields; +- +- // Optimization: We keep around a builder for the last field that was +- // modified so that we can efficiently add to it multiple times in a +- // row (important when parsing an unknown repeated field). +- private int lastFieldNumber; +- private Field.Builder lastField; ++ private TreeMap fieldBuilders = new TreeMap<>(); + + private static Builder create() { +- Builder builder = new Builder(); +- builder.reinitialize(); +- return builder; ++ return new Builder(); + } + + /** + * Get a field builder for the given field number which includes any values that already exist. + */ +- private Field.Builder getFieldBuilder(final int number) { +- if (lastField != null) { +- if (number == lastFieldNumber) { +- return lastField; +- } +- // Note: addField() will reset lastField and lastFieldNumber. +- addField(lastFieldNumber, lastField.build()); +- } ++ private Field.Builder getFieldBuilder(int number) { + if (number == 0) { + return null; + } else { +- final Field existing = fields.get(number); +- lastFieldNumber = number; +- lastField = Field.newBuilder(); +- if (existing != null) { +- lastField.mergeFrom(existing); ++ Field.Builder builder = fieldBuilders.get(number); ++ if (builder == null) { ++ builder = Field.newBuilder(); ++ fieldBuilders.put(number, builder); + } +- return lastField; ++ return builder; + } + } + + /** + * Build the {@link UnknownFieldSet} and return it. +- * +- *

Once {@code build()} has been called, the {@code Builder} will no longer be usable. +- * Calling any method after {@code build()} will result in undefined behavior and can cause a +- * {@code NullPointerException} to be thrown. + */ + @Override + public UnknownFieldSet build() { +- getFieldBuilder(0); // Force lastField to be built. +- final UnknownFieldSet result; +- if (fields.isEmpty()) { ++ UnknownFieldSet result; ++ if (fieldBuilders.isEmpty()) { + result = getDefaultInstance(); + } else { +- Map descendingFields = null; +- descendingFields = +- Collections.unmodifiableMap(((TreeMap) fields).descendingMap()); +- result = new UnknownFieldSet(Collections.unmodifiableMap(fields), descendingFields); ++ TreeMap fields = new TreeMap<>(); ++ for (Map.Entry entry : fieldBuilders.entrySet()) { ++ fields.put(entry.getKey(), entry.getValue().build()); ++ } ++ result = new UnknownFieldSet(fields); + } +- fields = null; + return result; + } + +@@ -378,11 +353,13 @@ public final class UnknownFieldSet implements MessageLite { + + @Override + public Builder clone() { +- getFieldBuilder(0); // Force lastField to be built. +- Map descendingFields = null; +- descendingFields = +- Collections.unmodifiableMap(((TreeMap) fields).descendingMap()); +- return UnknownFieldSet.newBuilder().mergeFrom(new UnknownFieldSet(fields, descendingFields)); ++ Builder clone = UnknownFieldSet.newBuilder(); ++ for (Map.Entry entry : fieldBuilders.entrySet()) { ++ Integer key = entry.getKey(); ++ Field.Builder value = entry.getValue(); ++ clone.fieldBuilders.put(key, value.clone()); ++ } ++ return clone; + } + + @Override +@@ -390,31 +367,24 @@ public final class UnknownFieldSet implements MessageLite { + return UnknownFieldSet.getDefaultInstance(); + } + +- private void reinitialize() { +- fields = Collections.emptyMap(); +- lastFieldNumber = 0; +- lastField = null; +- } +- + /** Reset the builder to an empty set. */ + @Override + public Builder clear() { +- reinitialize(); ++ fieldBuilders = new TreeMap<>(); + return this; + } + +- /** Clear fields from the set with a given field number. */ +- public Builder clearField(final int number) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); +- } +- if (lastField != null && lastFieldNumber == number) { +- // Discard this. +- lastField = null; +- lastFieldNumber = 0; ++ /** ++ * Clear fields from the set with a given field number. ++ * ++ * @throws IllegalArgumentException if number is not positive ++ */ ++ public Builder clearField(int number) { ++ if (number <= 0) { ++ throw new IllegalArgumentException(number + " is not a valid field number."); + } +- if (fields.containsKey(number)) { +- fields.remove(number); ++ if (fieldBuilders.containsKey(number)) { ++ fieldBuilders.remove(number); + } + return this; + } +@@ -423,9 +393,9 @@ public final class UnknownFieldSet implements MessageLite { + * Merge the fields from {@code other} into this set. If a field number exists in both sets, + * {@code other}'s values for that field will be appended to the values in this set. + */ +- public Builder mergeFrom(final UnknownFieldSet other) { ++ public Builder mergeFrom(UnknownFieldSet other) { + if (other != getDefaultInstance()) { +- for (final Map.Entry entry : other.fields.entrySet()) { ++ for (Map.Entry entry : other.fields.entrySet()) { + mergeField(entry.getKey(), entry.getValue()); + } + } +@@ -435,10 +405,12 @@ public final class UnknownFieldSet implements MessageLite { + /** + * Add a field to the {@code UnknownFieldSet}. If a field with the same number already exists, + * the two are merged. ++ * ++ * @throws IllegalArgumentException if number is not positive + */ +- public Builder mergeField(final int number, final Field field) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); ++ public Builder mergeField(int number, final Field field) { ++ if (number <= 0) { ++ throw new IllegalArgumentException(number + " is not a valid field number."); + } + if (hasField(number)) { + getFieldBuilder(number).mergeFrom(field); +@@ -454,10 +426,12 @@ public final class UnknownFieldSet implements MessageLite { + /** + * Convenience method for merging a new field containing a single varint value. This is used in + * particular when an unknown enum value is encountered. ++ * ++ * @throws IllegalArgumentException if number is not positive + */ +- public Builder mergeVarintField(final int number, final int value) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); ++ public Builder mergeVarintField(int number, int value) { ++ if (number <= 0) { ++ throw new IllegalArgumentException(number + " is not a valid field number."); + } + getFieldBuilder(number).addVarint(value); + return this; +@@ -467,40 +441,33 @@ public final class UnknownFieldSet implements MessageLite { + * Convenience method for merging a length-delimited field. + * + *

For use by generated code only. ++ * ++ * @throws IllegalArgumentException if number is not positive + */ +- public Builder mergeLengthDelimitedField(final int number, final ByteString value) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); ++ public Builder mergeLengthDelimitedField(int number, ByteString value) { ++ if (number <= 0) { ++ throw new IllegalArgumentException(number + " is not a valid field number."); + } + getFieldBuilder(number).addLengthDelimited(value); + return this; + } + + /** Check if the given field number is present in the set. */ +- public boolean hasField(final int number) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); +- } +- return number == lastFieldNumber || fields.containsKey(number); ++ public boolean hasField(int number) { ++ return fieldBuilders.containsKey(number); + } + + /** + * Add a field to the {@code UnknownFieldSet}. If a field with the same number already exists, + * it is removed. ++ * ++ * @throws IllegalArgumentException if number is not positive + */ +- public Builder addField(final int number, final Field field) { +- if (number == 0) { +- throw new IllegalArgumentException("Zero is not a valid field number."); +- } +- if (lastField != null && lastFieldNumber == number) { +- // Discard this. +- lastField = null; +- lastFieldNumber = 0; ++ public Builder addField(int number, Field field) { ++ if (number <= 0) { ++ throw new IllegalArgumentException(number + " is not a valid field number."); + } +- if (fields.isEmpty()) { +- fields = new TreeMap(); +- } +- fields.put(number, field); ++ fieldBuilders.put(number, Field.newBuilder(field)); + return this; + } + +@@ -509,15 +476,18 @@ public final class UnknownFieldSet implements MessageLite { + * changes may or may not be reflected in this map. + */ + public Map asMap() { +- getFieldBuilder(0); // Force lastField to be built. ++ TreeMap fields = new TreeMap<>(); ++ for (Map.Entry entry : fieldBuilders.entrySet()) { ++ fields.put(entry.getKey(), entry.getValue().build()); ++ } + return Collections.unmodifiableMap(fields); + } + + /** Parse an entire message from {@code input} and merge its fields into this set. */ + @Override +- public Builder mergeFrom(final CodedInputStream input) throws IOException { ++ public Builder mergeFrom(CodedInputStream input) throws IOException { + while (true) { +- final int tag = input.readTag(); ++ int tag = input.readTag(); + if (tag == 0 || !mergeFieldFrom(tag, input)) { + break; + } +@@ -531,8 +501,8 @@ public final class UnknownFieldSet implements MessageLite { + * @param tag The field's tag number, which was already parsed. + * @return {@code false} if the tag is an end group tag. + */ +- public boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException { +- final int number = WireFormat.getTagFieldNumber(tag); ++ public boolean mergeFieldFrom(int tag, CodedInputStream input) throws IOException { ++ int number = WireFormat.getTagFieldNumber(tag); + switch (WireFormat.getTagWireType(tag)) { + case WireFormat.WIRETYPE_VARINT: + getFieldBuilder(number).addVarint(input.readInt64()); +@@ -544,7 +514,7 @@ public final class UnknownFieldSet implements MessageLite { + getFieldBuilder(number).addLengthDelimited(input.readBytes()); + return true; + case WireFormat.WIRETYPE_START_GROUP: +- final Builder subBuilder = newBuilder(); ++ Builder subBuilder = newBuilder(); + input.readGroup(number, subBuilder, ExtensionRegistry.getEmptyRegistry()); + getFieldBuilder(number).addGroup(subBuilder.build()); + return true; +@@ -563,15 +533,15 @@ public final class UnknownFieldSet implements MessageLite { + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. + */ + @Override +- public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException { ++ public Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException { + try { +- final CodedInputStream input = data.newCodedInput(); ++ CodedInputStream input = data.newCodedInput(); + mergeFrom(input); + input.checkLastTagWas(0); + return this; +- } catch (final InvalidProtocolBufferException e) { ++ } catch (InvalidProtocolBufferException e) { + throw e; +- } catch (final IOException e) { ++ } catch (IOException e) { + throw new RuntimeException( + "Reading from a ByteString threw an IOException (should never happen).", e); + } +@@ -582,15 +552,15 @@ public final class UnknownFieldSet implements MessageLite { + * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. + */ + @Override +- public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException { ++ public Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException { + try { +- final CodedInputStream input = CodedInputStream.newInstance(data); ++ CodedInputStream input = CodedInputStream.newInstance(data); + mergeFrom(input); + input.checkLastTagWas(0); + return this; +- } catch (final InvalidProtocolBufferException e) { ++ } catch (InvalidProtocolBufferException e) { + throw e; +- } catch (final IOException e) { ++ } catch (IOException e) { + throw new RuntimeException( + "Reading from a byte array threw an IOException (should never happen).", e); + } +@@ -601,8 +571,8 @@ public final class UnknownFieldSet implements MessageLite { + * This is just a small wrapper around {@link #mergeFrom(CodedInputStream)}. + */ + @Override +- public Builder mergeFrom(final InputStream input) throws IOException { +- final CodedInputStream codedInput = CodedInputStream.newInstance(input); ++ public Builder mergeFrom(InputStream input) throws IOException { ++ CodedInputStream codedInput = CodedInputStream.newInstance(input); + mergeFrom(codedInput); + codedInput.checkLastTagWas(0); + return this; +@@ -610,12 +580,12 @@ public final class UnknownFieldSet implements MessageLite { + + @Override + public boolean mergeDelimitedFrom(InputStream input) throws IOException { +- final int firstByte = input.read(); ++ int firstByte = input.read(); + if (firstByte == -1) { + return false; + } +- final int size = CodedInputStream.readRawVarint32(firstByte, input); +- final InputStream limitedInput = new LimitedInputStream(input, size); ++ int size = CodedInputStream.readRawVarint32(firstByte, input); ++ InputStream limitedInput = new LimitedInputStream(input, size); + mergeFrom(limitedInput); + return true; + } +@@ -644,7 +614,7 @@ public final class UnknownFieldSet implements MessageLite { + @Override + public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException { + try { +- final CodedInputStream input = CodedInputStream.newInstance(data, off, len); ++ CodedInputStream input = CodedInputStream.newInstance(data, off, len); + mergeFrom(input); + input.checkLastTagWas(0); + return this; +@@ -718,7 +688,7 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Construct a new {@link Builder} and initialize it to a copy of {@code copyFrom}. */ +- public static Builder newBuilder(final Field copyFrom) { ++ public static Builder newBuilder(Field copyFrom) { + return newBuilder().mergeFrom(copyFrom); + } + +@@ -758,7 +728,7 @@ public final class UnknownFieldSet implements MessageLite { + } + + @Override +- public boolean equals(final Object other) { ++ public boolean equals(Object other) { + if (this == other) { + return true; + } +@@ -785,7 +755,7 @@ public final class UnknownFieldSet implements MessageLite { + public ByteString toByteString(int fieldNumber) { + try { + // TODO(lukes): consider caching serialized size in a volatile long +- final ByteString.CodedBuilder out = ++ ByteString.CodedBuilder out = + ByteString.newCodedBuilder(getSerializedSize(fieldNumber)); + writeTo(fieldNumber, out.getCodedOutput()); + return out.build(); +@@ -796,40 +766,40 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Serializes the field, including field number, and writes it to {@code output}. */ +- public void writeTo(final int fieldNumber, final CodedOutputStream output) throws IOException { +- for (final long value : varint) { ++ public void writeTo(int fieldNumber, CodedOutputStream output) throws IOException { ++ for (long value : varint) { + output.writeUInt64(fieldNumber, value); + } +- for (final int value : fixed32) { ++ for (int value : fixed32) { + output.writeFixed32(fieldNumber, value); + } +- for (final long value : fixed64) { ++ for (long value : fixed64) { + output.writeFixed64(fieldNumber, value); + } +- for (final ByteString value : lengthDelimited) { ++ for (ByteString value : lengthDelimited) { + output.writeBytes(fieldNumber, value); + } +- for (final UnknownFieldSet value : group) { ++ for (UnknownFieldSet value : group) { + output.writeGroup(fieldNumber, value); + } + } + + /** Get the number of bytes required to encode this field, including field number. */ +- public int getSerializedSize(final int fieldNumber) { ++ public int getSerializedSize(int fieldNumber) { + int result = 0; +- for (final long value : varint) { ++ for (long value : varint) { + result += CodedOutputStream.computeUInt64Size(fieldNumber, value); + } +- for (final int value : fixed32) { ++ for (int value : fixed32) { + result += CodedOutputStream.computeFixed32Size(fieldNumber, value); + } +- for (final long value : fixed64) { ++ for (long value : fixed64) { + result += CodedOutputStream.computeFixed64Size(fieldNumber, value); + } +- for (final ByteString value : lengthDelimited) { ++ for (ByteString value : lengthDelimited) { + result += CodedOutputStream.computeBytesSize(fieldNumber, value); + } +- for (final UnknownFieldSet value : group) { ++ for (UnknownFieldSet value : group) { + result += CodedOutputStream.computeGroupSize(fieldNumber, value); + } + return result; +@@ -839,15 +809,15 @@ public final class UnknownFieldSet implements MessageLite { + * Serializes the field, including field number, and writes it to {@code output}, using {@code + * MessageSet} wire format. + */ +- public void writeAsMessageSetExtensionTo(final int fieldNumber, final CodedOutputStream output) ++ public void writeAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output) + throws IOException { +- for (final ByteString value : lengthDelimited) { ++ for (ByteString value : lengthDelimited) { + output.writeRawMessageSetExtension(fieldNumber, value); + } + } + + /** Serializes the field, including field number, and writes it to {@code writer}. */ +- void writeTo(final int fieldNumber, final Writer writer) throws IOException { ++ void writeTo(int fieldNumber, Writer writer) throws IOException { + writer.writeInt64List(fieldNumber, varint, false); + writer.writeFixed32List(fieldNumber, fixed32, false); + writer.writeFixed64List(fieldNumber, fixed64, false); +@@ -872,7 +842,7 @@ public final class UnknownFieldSet implements MessageLite { + * Serializes the field, including field number, and writes it to {@code writer}, using {@code + * MessageSet} wire format. + */ +- private void writeAsMessageSetExtensionTo(final int fieldNumber, final Writer writer) ++ private void writeAsMessageSetExtensionTo(int fieldNumber, Writer writer) + throws IOException { + if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { + // Write in descending field order. +@@ -882,7 +852,7 @@ public final class UnknownFieldSet implements MessageLite { + } + } else { + // Write in ascending field order. +- for (final ByteString value : lengthDelimited) { ++ for (ByteString value : lengthDelimited) { + writer.writeMessageSetItem(fieldNumber, value); + } + } +@@ -892,9 +862,9 @@ public final class UnknownFieldSet implements MessageLite { + * Get the number of bytes required to encode this field, including field number, using {@code + * MessageSet} wire format. + */ +- public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { ++ public int getSerializedSizeAsMessageSetExtension(int fieldNumber) { + int result = 0; +- for (final ByteString value : lengthDelimited) { ++ for (ByteString value : lengthDelimited) { + result += CodedOutputStream.computeRawMessageSetExtensionSize(fieldNumber, value); + } + return result; +@@ -912,52 +882,85 @@ public final class UnknownFieldSet implements MessageLite { + *

Use {@link Field#newBuilder()} to construct a {@code Builder}. + */ + public static final class Builder { +- // This constructor should never be called directly (except from 'create'). +- private Builder() {} ++ // This constructor should only be called directly from 'create' and 'clone'. ++ private Builder() { ++ result = new Field(); ++ } + + private static Builder create() { + Builder builder = new Builder(); +- builder.result = new Field(); + return builder; + } + + private Field result; + ++ @Override ++ public Builder clone() { ++ Field copy = new Field(); ++ if (result.varint == null) { ++ copy.varint = null; ++ } else { ++ copy.varint = new ArrayList<>(result.varint); ++ } ++ if (result.fixed32 == null) { ++ copy.fixed32 = null; ++ } else { ++ copy.fixed32 = new ArrayList<>(result.fixed32); ++ } ++ if (result.fixed64 == null) { ++ copy.fixed64 = null; ++ } else { ++ copy.fixed64 = new ArrayList<>(result.fixed64); ++ } ++ if (result.lengthDelimited == null) { ++ copy.lengthDelimited = null; ++ } else { ++ copy.lengthDelimited = new ArrayList<>(result.lengthDelimited); ++ } ++ if (result.group == null) { ++ copy.group = null; ++ } else { ++ copy.group = new ArrayList<>(result.group); ++ } ++ ++ Builder clone = new Builder(); ++ clone.result = copy; ++ return clone; ++ } ++ + /** +- * Build the field. After {@code build()} has been called, the {@code Builder} is no longer +- * usable. Calling any other method will result in undefined behavior and can cause a {@code +- * NullPointerException} to be thrown. ++ * Build the field. + */ + public Field build() { ++ Field built = new Field(); + if (result.varint == null) { +- result.varint = Collections.emptyList(); ++ built.varint = Collections.emptyList(); + } else { +- result.varint = Collections.unmodifiableList(result.varint); ++ built.varint = Collections.unmodifiableList(new ArrayList<>(result.varint)); + } + if (result.fixed32 == null) { +- result.fixed32 = Collections.emptyList(); ++ built.fixed32 = Collections.emptyList(); + } else { +- result.fixed32 = Collections.unmodifiableList(result.fixed32); ++ built.fixed32 = Collections.unmodifiableList(new ArrayList<>(result.fixed32)); + } + if (result.fixed64 == null) { +- result.fixed64 = Collections.emptyList(); ++ built.fixed64 = Collections.emptyList(); + } else { +- result.fixed64 = Collections.unmodifiableList(result.fixed64); ++ built.fixed64 = Collections.unmodifiableList(new ArrayList<>(result.fixed64)); + } + if (result.lengthDelimited == null) { +- result.lengthDelimited = Collections.emptyList(); ++ built.lengthDelimited = Collections.emptyList(); + } else { +- result.lengthDelimited = Collections.unmodifiableList(result.lengthDelimited); ++ built.lengthDelimited = Collections.unmodifiableList( ++ new ArrayList<>(result.lengthDelimited)); + } + if (result.group == null) { +- result.group = Collections.emptyList(); ++ built.group = Collections.emptyList(); + } else { +- result.group = Collections.unmodifiableList(result.group); ++ built.group = Collections.unmodifiableList(new ArrayList<>(result.group)); + } + +- final Field returnMe = result; +- result = null; +- return returnMe; ++ return built; + } + + /** Discard the field's contents. */ +@@ -970,7 +973,7 @@ public final class UnknownFieldSet implements MessageLite { + * Merge the values in {@code other} into this field. For each list of values, {@code other}'s + * values are append to the ones in this field. + */ +- public Builder mergeFrom(final Field other) { ++ public Builder mergeFrom(Field other) { + if (!other.varint.isEmpty()) { + if (result.varint == null) { + result.varint = new ArrayList(); +@@ -985,19 +988,19 @@ public final class UnknownFieldSet implements MessageLite { + } + if (!other.fixed64.isEmpty()) { + if (result.fixed64 == null) { +- result.fixed64 = new ArrayList(); ++ result.fixed64 = new ArrayList<>(); + } + result.fixed64.addAll(other.fixed64); + } + if (!other.lengthDelimited.isEmpty()) { + if (result.lengthDelimited == null) { +- result.lengthDelimited = new ArrayList(); ++ result.lengthDelimited = new ArrayList<>(); + } + result.lengthDelimited.addAll(other.lengthDelimited); + } + if (!other.group.isEmpty()) { + if (result.group == null) { +- result.group = new ArrayList(); ++ result.group = new ArrayList<>(); + } + result.group.addAll(other.group); + } +@@ -1005,45 +1008,45 @@ public final class UnknownFieldSet implements MessageLite { + } + + /** Add a varint value. */ +- public Builder addVarint(final long value) { ++ public Builder addVarint(long value) { + if (result.varint == null) { +- result.varint = new ArrayList(); ++ result.varint = new ArrayList<>(); + } + result.varint.add(value); + return this; + } + + /** Add a fixed32 value. */ +- public Builder addFixed32(final int value) { ++ public Builder addFixed32(int value) { + if (result.fixed32 == null) { +- result.fixed32 = new ArrayList(); ++ result.fixed32 = new ArrayList<>(); + } + result.fixed32.add(value); + return this; + } + + /** Add a fixed64 value. */ +- public Builder addFixed64(final long value) { ++ public Builder addFixed64(long value) { + if (result.fixed64 == null) { +- result.fixed64 = new ArrayList(); ++ result.fixed64 = new ArrayList<>(); + } + result.fixed64.add(value); + return this; + } + + /** Add a length-delimited value. */ +- public Builder addLengthDelimited(final ByteString value) { ++ public Builder addLengthDelimited(ByteString value) { + if (result.lengthDelimited == null) { +- result.lengthDelimited = new ArrayList(); ++ result.lengthDelimited = new ArrayList<>(); + } + result.lengthDelimited.add(value); + return this; + } + + /** Add an embedded group. */ +- public Builder addGroup(final UnknownFieldSet value) { ++ public Builder addGroup(UnknownFieldSet value) { + if (result.group == null) { +- result.group = new ArrayList(); ++ result.group = new ArrayList<>(); + } + result.group.add(value); + return this; +diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java +new file mode 100644 +index 0000000..6ce0fc7 +--- /dev/null ++++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java +@@ -0,0 +1,78 @@ ++// Protocol Buffers - Google's data interchange format ++// Copyright 2008 Google Inc. All rights reserved. ++// https://developers.google.com/protocol-buffers/ ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++package com.google.protobuf; ++ ++import static com.google.common.truth.Truth.assertThat; ++ ++import java.io.ByteArrayInputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import org.junit.Test; ++import org.junit.runner.RunWith; ++import org.junit.runners.JUnit4; ++ ++@RunWith(JUnit4.class) ++public final class UnknownFieldSetPerformanceTest { ++ ++ private static byte[] generateBytes(int length) { ++ assertThat(length % 4).isEqualTo(0); ++ byte[] input = new byte[length]; ++ for (int i = 0; i < length; i += 4) { ++ input[i] = (byte) 0x08; // field 1, wiretype 0 ++ input[i + 1] = (byte) 0x08; // field 1, payload 8 ++ input[i + 2] = (byte) 0x20; // field 4, wiretype 0 ++ input[i + 3] = (byte) 0x20; // field 4, payload 32 ++ } ++ return input; ++ } ++ ++ @Test ++ // This is a performance test. Failure here is a timeout. ++ public void testAlternatingFieldNumbers() throws IOException { ++ byte[] input = generateBytes(800000); ++ InputStream in = new ByteArrayInputStream(input); ++ UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder(); ++ CodedInputStream codedInput = CodedInputStream.newInstance(in); ++ builder.mergeFrom(codedInput); ++ } ++ ++ @Test ++ // This is a performance test. Failure here is a timeout. ++ public void testAddField() { ++ UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder(); ++ for (int i = 1; i <= 100000; i++) { ++ UnknownFieldSet.Field field = UnknownFieldSet.Field.newBuilder().addFixed32(i).build(); ++ builder.addField(i, field); ++ } ++ UnknownFieldSet fieldSet = builder.build(); ++ assertThat(fieldSet.getField(100000).getFixed32List().get(0)).isEqualTo(100000); ++ } ++} +diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +index c7eb57c..3e1e928 100644 +--- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java ++++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +@@ -30,6 +30,9 @@ + + package com.google.protobuf; + ++import static com.google.common.truth.Truth.assertThat; ++import static com.google.common.truth.Truth.assertWithMessage; ++ + import protobuf_unittest.UnittestProto; + import protobuf_unittest.UnittestProto.ForeignEnum; + import protobuf_unittest.UnittestProto.TestAllExtensions; +@@ -39,8 +42,10 @@ import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions; + import protobuf_unittest.UnittestProto.TestPackedExtensions; + import protobuf_unittest.UnittestProto.TestPackedTypes; + import proto3_unittest.UnittestProto3; ++import java.util.List; + import java.util.Arrays; + import java.util.Map; ++import org.junit.Assert; + import junit.framework.TestCase; + + /** +@@ -58,7 +63,7 @@ public class UnknownFieldSetTest extends TestCase { + unknownFields = emptyMessage.getUnknownFields(); + } + +- UnknownFieldSet.Field getField(String name) { ++ private UnknownFieldSet.Field getField(String name) { + Descriptors.FieldDescriptor field = descriptor.findFieldByName(name); + assertNotNull(field); + return unknownFields.getField(field.getNumber()); +@@ -97,6 +102,161 @@ public class UnknownFieldSetTest extends TestCase { + + // ================================================================= + ++ public void testFieldBuildersAreReusable() { ++ UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); ++ fieldBuilder.addFixed32(10); ++ UnknownFieldSet.Field first = fieldBuilder.build(); ++ UnknownFieldSet.Field second = fieldBuilder.build(); ++ fieldBuilder.addFixed32(11); ++ UnknownFieldSet.Field third = fieldBuilder.build(); ++ ++ assertThat(first).isEqualTo(second); ++ assertThat(first).isNotEqualTo(third); ++ } ++ ++ public void testClone() { ++ UnknownFieldSet.Builder unknownSetBuilder = UnknownFieldSet.newBuilder(); ++ UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); ++ fieldBuilder.addFixed32(10); ++ unknownSetBuilder.addField(8, fieldBuilder.build()); ++ // necessary to call clone twice to expose the bug ++ UnknownFieldSet.Builder clone1 = unknownSetBuilder.clone(); ++ UnknownFieldSet.Builder clone2 = unknownSetBuilder.clone(); // failure is a NullPointerException ++ assertThat(clone1).isNotSameInstanceAs(clone2); ++ } ++ ++ public void testClone_lengthDelimited() { ++ UnknownFieldSet.Builder destUnknownFieldSet = ++ UnknownFieldSet.newBuilder() ++ .addField(997, UnknownFieldSet.Field.newBuilder().addVarint(99).build()) ++ .addField( ++ 999, ++ UnknownFieldSet.Field.newBuilder() ++ .addLengthDelimited(ByteString.copyFromUtf8("some data")) ++ .addLengthDelimited(ByteString.copyFromUtf8("some more data")) ++ .build()); ++ UnknownFieldSet clone = destUnknownFieldSet.clone().build(); ++ assertThat(clone.getField(997)).isNotNull(); ++ UnknownFieldSet.Field field999 = clone.getField(999); ++ List lengthDelimited = field999.getLengthDelimitedList(); ++ assertThat(lengthDelimited.get(0).toStringUtf8()).isEqualTo("some data"); ++ assertThat(lengthDelimited.get(1).toStringUtf8()).isEqualTo("some more data"); ++ ++ UnknownFieldSet clone2 = destUnknownFieldSet.clone().build(); ++ assertThat(clone2.getField(997)).isNotNull(); ++ UnknownFieldSet.Field secondField = clone2.getField(999); ++ List lengthDelimited2 = secondField.getLengthDelimitedList(); ++ assertThat(lengthDelimited2.get(0).toStringUtf8()).isEqualTo("some data"); ++ assertThat(lengthDelimited2.get(1).toStringUtf8()).isEqualTo("some more data"); ++ } ++ ++ public void testReuse() { ++ UnknownFieldSet.Builder builder = ++ UnknownFieldSet.newBuilder() ++ .addField(997, UnknownFieldSet.Field.newBuilder().addVarint(99).build()) ++ .addField( ++ 999, ++ UnknownFieldSet.Field.newBuilder() ++ .addLengthDelimited(ByteString.copyFromUtf8("some data")) ++ .addLengthDelimited(ByteString.copyFromUtf8("some more data")) ++ .build()); ++ ++ UnknownFieldSet fieldSet1 = builder.build(); ++ UnknownFieldSet fieldSet2 = builder.build(); ++ builder.addField(1000, UnknownFieldSet.Field.newBuilder().addVarint(-90).build()); ++ UnknownFieldSet fieldSet3 = builder.build(); ++ ++ assertThat(fieldSet1).isEqualTo(fieldSet2); ++ assertThat(fieldSet1).isNotEqualTo(fieldSet3); ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testAddField_zero() { ++ UnknownFieldSet.Field field = getField("optional_int32"); ++ try { ++ UnknownFieldSet.newBuilder().addField(0, field); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("0 is not a valid field number."); ++ } ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testAddField_negative() { ++ UnknownFieldSet.Field field = getField("optional_int32"); ++ try { ++ UnknownFieldSet.newBuilder().addField(-2, field); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("-2 is not a valid field number."); ++ } ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testClearField_negative() { ++ try { ++ UnknownFieldSet.newBuilder().clearField(-28); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("-28 is not a valid field number."); ++ } ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testMergeField_negative() { ++ UnknownFieldSet.Field field = getField("optional_int32"); ++ try { ++ UnknownFieldSet.newBuilder().mergeField(-2, field); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("-2 is not a valid field number."); ++ } ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testMergeVarintField_negative() { ++ try { ++ UnknownFieldSet.newBuilder().mergeVarintField(-2, 78); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("-2 is not a valid field number."); ++ } ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testHasField_negative() { ++ assertThat(UnknownFieldSet.newBuilder().hasField(-2)).isFalse(); ++ } ++ ++ @SuppressWarnings("ModifiedButNotUsed") ++ public void testMergeLengthDelimitedField_negative() { ++ ByteString byteString = ByteString.copyFromUtf8("some data"); ++ try { ++ UnknownFieldSet.newBuilder().mergeLengthDelimitedField(-2, byteString); ++ Assert.fail(); ++ } catch (IllegalArgumentException expected) { ++ assertThat(expected).hasMessageThat().isEqualTo("-2 is not a valid field number."); ++ } ++ } ++ ++ public void testAddField() { ++ UnknownFieldSet.Field field = getField("optional_int32"); ++ UnknownFieldSet fieldSet = UnknownFieldSet.newBuilder().addField(1, field).build(); ++ assertThat(fieldSet.getField(1)).isEqualTo(field); ++ } ++ ++ public void testAddField_withReplacement() { ++ UnknownFieldSet.Field first = UnknownFieldSet.Field.newBuilder().addFixed32(56).build(); ++ UnknownFieldSet.Field second = UnknownFieldSet.Field.newBuilder().addFixed32(25).build(); ++ UnknownFieldSet fieldSet = UnknownFieldSet.newBuilder() ++ .addField(1, first) ++ .addField(1, second) ++ .build(); ++ List list = fieldSet.getField(1).getFixed32List(); ++ assertThat(list).hasSize(1); ++ assertThat(list.get(0)).isEqualTo(25); ++ } ++ + public void testVarint() throws Exception { + UnknownFieldSet.Field field = getField("optional_int32"); + assertEquals(1, field.getVarintList().size()); +@@ -173,6 +333,15 @@ public class UnknownFieldSetTest extends TestCase { + assertEquals("1: 1\n2: 2\n3: 3\n3: 4\n", destination.toString()); + } + ++ public void testAsMap() throws Exception { ++ UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder().mergeFrom(unknownFields); ++ Map mapFromBuilder = builder.asMap(); ++ assertThat(mapFromBuilder).isNotEmpty(); ++ UnknownFieldSet fields = builder.build(); ++ Map mapFromFieldSet = fields.asMap(); ++ assertThat(mapFromFieldSet).containsExactlyEntriesIn(mapFromBuilder); ++ } ++ + public void testClear() throws Exception { + UnknownFieldSet fields = UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build(); + assertTrue(fields.asMap().isEmpty()); +diff --git a/java/lite/pom.xml b/java/lite/pom.xml +index 104c5c1..d095483 100644 +--- a/java/lite/pom.xml ++++ b/java/lite/pom.xml +@@ -232,7 +232,8 @@ + TestUtil.java + TypeRegistryTest.java + UnknownEnumValueTest.java +- UnknownFieldSetLiteTest.java ++ UnknownFieldSetLiteTest.java ++ UnknownFieldSetPerformanceTest.java + UnknownFieldSetTest.java + WellKnownTypesTest.java + WireFormatTest.java +-- +2.30.0 + diff --git a/0007-add-coverage-compile-option.patch b/0007-add-coverage-compile-option.patch new file mode 100644 index 0000000..3e423f9 --- /dev/null +++ b/0007-add-coverage-compile-option.patch @@ -0,0 +1,49 @@ +From c87fadf8be81e48697eca3308981ec3a684ecfcc Mon Sep 17 00:00:00 2001 +From: chengzrz +Date: Wed, 16 Nov 2022 17:47:10 +0800 +Subject: [PATCH] protobuf: add coverage compile option + +Type:testcode +reason:add coverage compile option + +Signed-off-by: chengzrz +--- + configure.ac | 7 +++++++ + src/Makefile.am | 4 ++++ + 2 files changed, 11 insertions(+) + +diff --git a/configure.ac b/configure.ac +index eb70a76..2ef1668 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -72,6 +72,13 @@ AC_ARG_WITH([protoc], + [use the given protoc command instead of building a new one when building tests (useful for cross-compiling)])], + [],[with_protoc=no]) + ++AC_ARG_ENABLE([coverage], ++ [AS_HELP_STRING([--enable-coverage], ++ [generate coverage report])], ++ [coverage=yes],[coverage=no]) ++ ++AM_CONDITIONAL([HAVE_COVERAGE], [test "x$coverage" == "xyes"]) ++ + # Checks for programs. + AC_PROG_CC + AC_PROG_CXX +diff --git a/src/Makefile.am b/src/Makefile.am +index 9af3db1..81d1418 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -21,6 +21,10 @@ endif + PROTOBUF_VERSION = 25:0:0 + PROTOBUF_OPT_FLAG += -Wl,-z,now -fstack-check + ++if HAVE_COVERAGE ++PROTOBUF_OPT_FLAG += -fprofile-arcs -ftest-coverage ++endif ++ + if GCC + # Turn on all warnings except for sign comparison (we ignore sign comparison + # in Google so our code base have tons of such warnings). +-- +2.26.3 diff --git a/protobuf.spec b/protobuf.spec index 287ccd9..ea43bab 100644 --- a/protobuf.spec +++ b/protobuf.spec @@ -1,34 +1,25 @@ -#needsrootforbuild -%undefine __cmake_in_source_build - -%define _lto_cflags %{nil} - # Build -python subpackage %bcond_without python # Build -java subpackage -%ifarch loongarch64 -%bcond_with java -%else %bcond_without java -%endif + +#global rcver rc2 Summary: Protocol Buffers - Google's data interchange format Name: protobuf Version: 32.1 Release: 12 -License: BSD-3-Clause +License: BSD URL: https://github.com/protocolbuffers/protobuf Source: https://github.com/protocolbuffers/protobuf/releases/download/v%{version}%{?rcver}/%{name}-%{version}%{?rcver}.tar.gz Source1: protobuf-init.el -%global so_version 32.1 -Patch9000: 0001-add-secure-compile-option.patch -Patch9001: 0002-Fix-CC-compiler-support.patch -Patch9002: 0003-protobuf-add-coverage-compile-option.patch +Patch9000: 0001-add-secure-compile-option-in-Makefile.patch +Patch9001: 0002-add-secure-compile-fs-check-in-Makefile.patch +Patch9003: 0004-Improve-performance-of-parsing-unknown-fields-in-Jav.patch +Patch9006: 0007-add-coverage-compile-option.patch -BuildRequires: cmake gcc-c++ emacs zlib-devel gmock-devel gtest-devel jsoncpp-devel -BuildRequires: fdupes pkgconfig python-rpm-macros pkgconfig(zlib) ninja-build -BuildRequires: abseil-cpp-devel >= 20230802 +BuildRequires: make autoconf automake emacs gcc-c++ libtool pkgconfig zlib-devel %description @@ -53,7 +44,6 @@ Summary: Protocol Buffers C++ headers and libraries Requires: %{name} = %{version}-%{release} Requires: %{name}-compiler = %{version}-%{release} Requires: zlib-devel pkgconfig vim-enhanced -Requires: abseil-cpp-devel >= 20230802 Provides: %{name}-static Provides: %{name}-vim Obsoletes: %{name}-static < %{version} @@ -116,25 +106,15 @@ This package contains Python 3 libraries for Google Protocol Buffers %package java Summary: Java Protocol Buffers runtime library BuildArch: noarch -BuildRequires: java-devel >= 1.6 -BuildRequires: jpackage-utils -BuildRequires: maven-local -BuildRequires: mvn(com.google.code.gson:gson) -BuildRequires: mvn(com.google.guava:guava) -BuildRequires: mvn(junit:junit) -BuildRequires: mvn(org.easymock:easymock) -BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) -BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin) -BuildRequires: mvn(org.apache.maven.plugins:maven-source-plugin) -BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin) -BuildRequires: maven-compiler-plugin -BuildRequires: maven-install-plugin -BuildRequires: maven-jar-plugin -BuildRequires: maven-javadoc-plugin -BuildRequires: maven-release-plugin -BuildRequires: maven-resources-plugin -BuildRequires: maven-surefire-plugin -BuildRequires: maven-antrun-plugin +BuildRequires: maven-local +BuildRequires: mvn(com.google.code.gson:gson) +BuildRequires: mvn(com.google.guava:guava) +BuildRequires: mvn(junit:junit) +BuildRequires: mvn(org.apache.felix:maven-bundle-plugin) +BuildRequires: mvn(org.apache.maven.plugins:maven-antrun-plugin) +BuildRequires: mvn(org.apache.maven.plugins:maven-source-plugin) +BuildRequires: mvn(org.codehaus.mojo:build-helper-maven-plugin) +BuildRequires: mvn(org.easymock:easymock) Obsoletes: %{name}-javanano < 3.6.0 %description java @@ -182,18 +162,14 @@ Protocol Buffer BOM POM. %setup -q -n %{name}-%{version}%{?rcver} %autopatch -p1 find -name \*.cc -o -name \*.h | xargs chmod -x -find examples -type f | xargs chmod 644 +chmod 644 examples/* %if %{with java} #%pom_remove_dep com.google.truth:truth java/pom.xml #%pom_remove_dep org.easymock:easymockclassextension java/pom.xml java/*/pom.xml -#%pom_remove_dep org.easymock:easymockclassextension java/pom.xml java/core/pom.xml java/lite/pom.xml java/util/pom.xml +%pom_remove_dep org.easymock:easymockclassextension java/pom.xml java/core/pom.xml java/lite/pom.xml java/util/pom.xml %pom_remove_dep com.google.truth:truth java/pom.xml java/util/pom.xml java/lite/pom.xml java/core/pom.xml %pom_remove_dep com.google.errorprone:error_prone_annotations java/util/pom.xml %pom_remove_dep com.google.guava:guava-testlib java/pom.xml java/util/pom.xml -%pom_remove_dep com.google.j2objc:j2objc-annotations java/util/pom.xml - -%pom_remove_plugin org.codehaus.mojo:animal-sniffer-maven-plugin java/pom.xml java/util/pom.xml -%pom_remove_dep org.mockito:mockito-core java/pom.xml java/core/pom.xml java/lite/pom.xml java/util/pom.xml # These use easymockclassextension rm java/core/src/test/java/com/google/protobuf/ServiceTest.java @@ -230,63 +206,26 @@ mv java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java \ rm -f src/solaris/libstdc++.la %build -%cmake \ - -B build \ - -Dprotobuf_BUILD_EXAMPLES:BOOL=OFF \ - -Dprotobuf_BUILD_LIBPROTOC:BOOL=ON \ - -Dprotobuf_BUILD_SHARED_LIBS:BOOL=ON \ - -Dprotobuf_USE_EXTERNAL_GTEST:BOOL=ON \ - -Dprotobuf_ABSL_PROVIDER=package \ - -Dprotobuf_BUILD_TESTS:BOOL=OFF \ - -DCMAKE_EXE_LINKER_FLAGS="%{build_ldflags}" \ - -DCMAKE_SHARED_LINKER_FLAGS="%{build_ldflags}" \ - -DCMAKE_CXX_FLAGS="%{build_cxxflags} %{?_ld_as_needed_flags}" \ - -DCMAKE_C_COMPILER=%{__cc} \ - -DCMAKE_CXX_COMPILER=%{__cxx} \ - -DCMAKE_SKIP_RPATH=TRUE \ - -G Ninja - -%ninja_build -C build - -%cmake \ - -B build-static \ - -Dprotobuf_BUILD_EXAMPLES:BOOL=OFF \ - -Dprotobuf_BUILD_LIBPROTOC:BOOL=ON \ - -Dprotobuf_BUILD_SHARED_LIBS:BOOL=OFF \ - -Dprotobuf_USE_EXTERNAL_GTEST:BOOL=ON \ - -Dprotobuf_ABSL_PROVIDER=package \ - -Dprotobuf_BUILD_TESTS:BOOL=OFF \ - -DCMAKE_CXX_FLAGS="-fPIC" \ - -DCMAKE_C_COMPILER=%{__cc} \ - -DCMAKE_CXX_COMPILER=%{__cxx} \ - -DCMAKE_SKIP_RPATH=TRUE \ - -G Ninja - -%ninja_build -C build-static - -# we have to override LD_LIBRARY_PATH because we eliminated rpath -export LD_LIBRARY_PATH="${PWD}/build":$LD_LIBRARY_PATH +iconv -f iso8859-1 -t utf-8 CONTRIBUTORS.txt > CONTRIBUTORS.txt.utf8 +mv CONTRIBUTORS.txt.utf8 CONTRIBUTORS.txt +export PTHREAD_LIBS="-lpthread" +./autogen.sh +%configure +%make_build CXXFLAGS="%{build_cxxflags} -Wno-error=type-limits" %if %{with python} -# Use the just built protoc instead of any -# system version for python and/or java bindings -export PROTOC=../build/protoc pushd python -CXXFLAGS="%{build_cxxflags}" \ -LDFLAGS="-L../%{_vpath_builddir} -L../%{_vpath_builddir}/third_party/utf8_range %{build_ldflags}" \ %py3_build popd %endif %if %{with java} -cp build/protoc ./ -%pom_disable_module kotlin java/pom.xml -%pom_disable_module kotlin-lite java/pom.xml -%mvn_build -s -- -Dmaven.test.skip=true -f java/pom.xml +%mvn_build -s -- -f java/pom.xml %endif %{_emacs_bytecompile} editors/protobuf-mode.el + %check # Java tests fail on s390x %ifarch s390x @@ -294,16 +233,15 @@ fail=0 %else fail=1 %endif +%make_build check CXXFLAGS="%{build_cxxflags} -Wno-error=type-limits" || exit $fail %install -%ninja_install -C build-static -%ninja_install -C build +%make_install %{?_smp_mflags} STRIPBINARIES=no INSTALL="%{__install} -p" CPPROG="cp -p" +find %{buildroot} -type f -name "*.la" -exec rm -f {} \; %if %{with python} pushd python -CXXFLAGS="%{build_cxxflags}" \ -LDFLAGS="-L../%{_vpath_builddir} -L../%{_vpath_builddir}/third_party/utf8_range %{build_ldflags}" \ #python ./setup.py install --root=%{buildroot} --single-version-externally-managed --record=INSTALLED_FILES --optimize=1 %py3_install find %{buildroot}%{python3_sitelib} -name \*.py | @@ -322,40 +260,37 @@ install -p -m 0644 editors/protobuf-mode.elc %{buildroot}%{_emacs_sitelispdir}/% mkdir -p %{buildroot}%{_emacs_sitestartdir} install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir} +%ldconfig_scriptlets +%ldconfig_scriptlets lite +%ldconfig_scriptlets compiler + %files -%doc CONTRIBUTORS.txt README.md +%doc CHANGES.txt CONTRIBUTORS.txt README.md %license LICENSE -%{_libdir}/libprotobuf.so.%{so_version}{,.*} +%{_libdir}/libprotobuf.so.25* %files compiler -%{_bindir}/protoc* -%{_libdir}/libprotoc.so.%{so_version}{,.*} +%{_bindir}/protoc +%{_libdir}/libprotoc.so.25* %{_emacs_sitelispdir}/%{name}/ %{_emacs_sitestartdir}/protobuf-init.el %license LICENSE %doc README.md + %files devel %dir %{_includedir}/google %{_includedir}/google/protobuf/ -%{_includedir}/utf8_range.h -%{_includedir}/utf8_validity.h %{_libdir}/libprotobuf.so %{_libdir}/libprotoc.so %{_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/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 -%{_libdir}/libprotobuf-lite.so.%{so_version}{,.*} +%{_libdir}/libprotobuf-lite.so.25* %files lite-devel %{_libdir}/libprotobuf-lite.so @@ -366,8 +301,8 @@ install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir} %files -n python%{python3_pkgversion}-protobuf %dir %{python3_sitelib}/google %{python3_sitelib}/google/protobuf/ -%{python3_sitelib}/%{name}-*-py3.*.egg-info/ -%{python3_sitelib}/%{name}-*-py3.*-nspkg.pth +%{python3_sitelib}/protobuf-%{version}%{?rcver}-py3.*.egg-info/ +%{python3_sitelib}/protobuf-%{version}%{?rcver}-py3.*-nspkg.pth %doc python/README.md %doc examples/add_person.py examples/list_people.py examples/addressbook.proto %endif @@ -377,7 +312,6 @@ install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir} %doc examples/AddPerson.java examples/ListPeople.java %doc java/README.md %license LICENSE -%{_includedir}/java/core/src/main/java/com/google/protobuf/java_features.proto %files java-util -f .mfiles-protobuf-java-util @@ -401,86 +335,20 @@ install -p -m 0644 %{SOURCE1} %{buildroot}%{_emacs_sitestartdir} - SUG:NA - DESC: update -* Thu June 26 2025 zhongtao - 25.1-12 +* Fri June 27 2025 zhongtao - 3.14.0-9 - Type:bugfix - ID:NA - SUG:NA -- DESC: append fix CVE-2025-4565 +- DESC: fix CVE-2025-4565 -* Wed Jun 11 2025 Dongxing Wang - 25.1-11 -- Type:bugfix -- CVE:NA -- SUG:NA -- DESC: revert:distinguish between statically and dynamically compiled cmake dir to prevent BEP binary differences +* Wed Dec 06 2023 konglidong - 3.14.0-8 +- obsolets protobuf2 for fix install conflict -* Thu May 15 2025 zhongtao - 25.1-10 -- Type:bugfix -- CVE:NA -- SUG:NA -- DESC: distinguish between statically and dynamically compiled cmake dir to prevent BEP binary differences - -* Fri May 09 2025 zhongtao - 25.1-9 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: distinguish between statically and dynamically compiled pc files to prevent BEP binary differences - -* Thu Nov 14 2024 Funda Wang - 25.1-8 -- adopt to new cmake macro - -* Wed Sep 25 2024 zhangxianting - 25.1-7 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: append fix CVE-2024-7254 - -* Thu Sep 19 2024 zhangxianting - 25.1-6 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: fix CVE-2024-7254 - -* Mon Aug 05 2024 zhongtao - 25.1-5 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: bugfix for devel package packaging file differences - -* Thu Jul 25 2024 zhongtao - 25.1-4 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: add coverage compile option - -* Mon Apr 15 2024 Wenlong Zhang - 25.1-4 -- disable java for loongarch64 - -* Tue Apr 09 2024 zhongtao - 25.1-3 -- Type:bugfix -- ID:NA -- SUG:NA -- DESC: add secure complie option and code improve - -* Wed Mar 20 2024 wangqiang - 25.1-2 -- Support package build with clang - -* Wed Jan 10 2024 zhongtao - 25.1-1 -- Type:upgrade -- ID:NA -- SUG:NA -- DESC: update to 25.1 - -* Wed Dec 06 2023 konglidong - 3.19.6-2 +* Mon Nov 21 2022 chengzeruizhi - 3.14.0-7 - Type:enhancement -- ID:NA -- SUG:NA -- DESC: obsolets protobuf2 for fix install conflict - -* Mon Jul 17 2023 zhongtao - 3.19.6-1 -- Type:upgrade -- ID:NA -- SUG:NA -- DESC: update to 3.19.6 +- ID:NA +- SUG:NA +- DESC: add compile option for coverage * Tue Oct 18 2022 chengzeruizhi - 3.14.0-6 - Type:bugfix -- cgit v1.2.3