diff options
| author | Chen Qi <Qi.Chen@windriver.com> | 2025-06-24 11:05:59 +0800 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2025-07-06 19:46:40 -0400 |
| commit | 7c3e7a6d5ddca67cddb1c493620c38a32dc36463 (patch) | |
| tree | 850448e9f24a2ff1a3c8450d81cf94d1831ecd36 /meta-oe/recipes-devtools | |
| parent | 727811eaf256b88fd135be99559f2cbf14c82fce (diff) | |
| download | meta-openembedded-7c3e7a6d5ddca67cddb1c493620c38a32dc36463.tar.gz | |
protobuf: upgrade from 4.25.3 to 4.25.8
0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch is
dropped because it has been in new version.
This upgrade also fixes CVE-2025-4565. The fix commit is as below:
d31100c91 Manually backport recursion limit enforcement to 25.x
Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Diffstat (limited to 'meta-oe/recipes-devtools')
| -rw-r--r-- | meta-oe/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch | 794 | ||||
| -rw-r--r-- | meta-oe/recipes-devtools/protobuf/protobuf_4.25.8.bb (renamed from meta-oe/recipes-devtools/protobuf/protobuf_4.25.3.bb) | 3 |
2 files changed, 1 insertions, 796 deletions
diff --git a/meta-oe/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch b/meta-oe/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch deleted file mode 100644 index 2f14620b4a..0000000000 --- a/meta-oe/recipes-devtools/protobuf/protobuf/0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch +++ /dev/null | |||
| @@ -1,794 +0,0 @@ | |||
| 1 | From 9f182ae260cc60e8cc5417abbe9481821642afa0 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Protobuf Team Bot <protobuf-github-bot@google.com> | ||
| 3 | Date: Tue, 17 Sep 2024 12:03:36 -0700 | ||
| 4 | Subject: [PATCH] Add recursion check when parsing unknown fields in Java. | ||
| 5 | |||
| 6 | PiperOrigin-RevId: 675657198 | ||
| 7 | |||
| 8 | CVE: CVE-2024-7254 | ||
| 9 | |||
| 10 | Upstream-Status: Backport [ac9fb5b4c71b0dd80985b27684e265d1f03abf46] | ||
| 11 | |||
| 12 | The original patch is adjusted to fit for the current version. | ||
| 13 | |||
| 14 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
| 15 | --- | ||
| 16 | .../com/google/protobuf/ArrayDecoders.java | 28 +++ | ||
| 17 | .../com/google/protobuf/CodedInputStream.java | 72 +++++- | ||
| 18 | .../com/google/protobuf/MessageSchema.java | 9 +- | ||
| 19 | .../com/google/protobuf/MessageSetSchema.java | 2 +- | ||
| 20 | .../google/protobuf/UnknownFieldSchema.java | 28 ++- | ||
| 21 | .../google/protobuf/CodedInputStreamTest.java | 159 ++++++++++++ | ||
| 22 | .../java/com/google/protobuf/LiteTest.java | 232 ++++++++++++++++++ | ||
| 23 | 7 files changed, 514 insertions(+), 16 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java | ||
| 26 | index f3241de50..0f3d7de0d 100644 | ||
| 27 | --- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java | ||
| 28 | +++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java | ||
| 29 | @@ -26,6 +26,10 @@ final class ArrayDecoders { | ||
| 30 | |||
| 31 | private ArrayDecoders() { | ||
| 32 | } | ||
| 33 | + static final int DEFAULT_RECURSION_LIMIT = 100; | ||
| 34 | + | ||
| 35 | + @SuppressWarnings("NonFinalStaticField") | ||
| 36 | + private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT; | ||
| 37 | |||
| 38 | /** | ||
| 39 | * A helper used to return multiple values in a Java function. Java doesn't natively support | ||
| 40 | @@ -38,6 +42,7 @@ final class ArrayDecoders { | ||
| 41 | public long long1; | ||
| 42 | public Object object1; | ||
| 43 | public final ExtensionRegistryLite extensionRegistry; | ||
| 44 | + public int recursionDepth; | ||
| 45 | |||
| 46 | Registers() { | ||
| 47 | this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry(); | ||
| 48 | @@ -245,7 +250,10 @@ final class ArrayDecoders { | ||
| 49 | if (length < 0 || length > limit - position) { | ||
| 50 | throw InvalidProtocolBufferException.truncatedMessage(); | ||
| 51 | } | ||
| 52 | + registers.recursionDepth++; | ||
| 53 | + checkRecursionLimit(registers.recursionDepth); | ||
| 54 | schema.mergeFrom(msg, data, position, position + length, registers); | ||
| 55 | + registers.recursionDepth--; | ||
| 56 | registers.object1 = msg; | ||
| 57 | return position + length; | ||
| 58 | } | ||
| 59 | @@ -263,8 +271,11 @@ final class ArrayDecoders { | ||
| 60 | // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema | ||
| 61 | // and it can't be used in group fields). | ||
| 62 | final MessageSchema messageSchema = (MessageSchema) schema; | ||
| 63 | + registers.recursionDepth++; | ||
| 64 | + checkRecursionLimit(registers.recursionDepth); | ||
| 65 | final int endPosition = | ||
| 66 | messageSchema.parseMessage(msg, data, position, limit, endGroup, registers); | ||
| 67 | + registers.recursionDepth--; | ||
| 68 | registers.object1 = msg; | ||
| 69 | return endPosition; | ||
| 70 | } | ||
| 71 | @@ -1025,6 +1036,8 @@ final class ArrayDecoders { | ||
| 72 | final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance(); | ||
| 73 | final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; | ||
| 74 | int lastTag = 0; | ||
| 75 | + registers.recursionDepth++; | ||
| 76 | + checkRecursionLimit(registers.recursionDepth); | ||
| 77 | while (position < limit) { | ||
| 78 | position = decodeVarint32(data, position, registers); | ||
| 79 | lastTag = registers.int1; | ||
| 80 | @@ -1033,6 +1046,7 @@ final class ArrayDecoders { | ||
| 81 | } | ||
| 82 | position = decodeUnknownField(lastTag, data, position, limit, child, registers); | ||
| 83 | } | ||
| 84 | + registers.recursionDepth--; | ||
| 85 | if (position > limit || lastTag != endGroup) { | ||
| 86 | throw InvalidProtocolBufferException.parseFailure(); | ||
| 87 | } | ||
| 88 | @@ -1079,4 +1093,18 @@ final class ArrayDecoders { | ||
| 89 | throw InvalidProtocolBufferException.invalidTag(); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if | ||
| 95 | + * the depth of the message exceeds this limit. | ||
| 96 | + */ | ||
| 97 | + public static void setRecursionLimit(int limit) { | ||
| 98 | + recursionLimit = limit; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + private static void checkRecursionLimit(int depth) throws InvalidProtocolBufferException { | ||
| 102 | + if (depth >= recursionLimit) { | ||
| 103 | + throw InvalidProtocolBufferException.recursionLimitExceeded(); | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | } | ||
| 107 | diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java | ||
| 108 | index 8f1ac736d..29256b4b3 100644 | ||
| 109 | --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java | ||
| 110 | +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java | ||
| 111 | @@ -703,7 +703,14 @@ public abstract class CodedInputStream { | ||
| 112 | public void skipMessage() throws IOException { | ||
| 113 | while (true) { | ||
| 114 | final int tag = readTag(); | ||
| 115 | - if (tag == 0 || !skipField(tag)) { | ||
| 116 | + if (tag == 0) { | ||
| 117 | + return; | ||
| 118 | + } | ||
| 119 | + checkRecursionLimit(); | ||
| 120 | + ++recursionDepth; | ||
| 121 | + boolean fieldSkipped = skipField(tag); | ||
| 122 | + --recursionDepth; | ||
| 123 | + if (!fieldSkipped) { | ||
| 124 | return; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | @@ -713,7 +720,14 @@ public abstract class CodedInputStream { | ||
| 128 | public void skipMessage(CodedOutputStream output) throws IOException { | ||
| 129 | while (true) { | ||
| 130 | final int tag = readTag(); | ||
| 131 | - if (tag == 0 || !skipField(tag, output)) { | ||
| 132 | + if (tag == 0) { | ||
| 133 | + return; | ||
| 134 | + } | ||
| 135 | + checkRecursionLimit(); | ||
| 136 | + ++recursionDepth; | ||
| 137 | + boolean fieldSkipped = skipField(tag, output); | ||
| 138 | + --recursionDepth; | ||
| 139 | + if (!fieldSkipped) { | ||
| 140 | return; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | @@ -1415,7 +1429,14 @@ public abstract class CodedInputStream { | ||
| 144 | public void skipMessage() throws IOException { | ||
| 145 | while (true) { | ||
| 146 | final int tag = readTag(); | ||
| 147 | - if (tag == 0 || !skipField(tag)) { | ||
| 148 | + if (tag == 0) { | ||
| 149 | + return; | ||
| 150 | + } | ||
| 151 | + checkRecursionLimit(); | ||
| 152 | + ++recursionDepth; | ||
| 153 | + boolean fieldSkipped = skipField(tag); | ||
| 154 | + --recursionDepth; | ||
| 155 | + if (!fieldSkipped) { | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | @@ -1425,7 +1446,14 @@ public abstract class CodedInputStream { | ||
| 160 | public void skipMessage(CodedOutputStream output) throws IOException { | ||
| 161 | while (true) { | ||
| 162 | final int tag = readTag(); | ||
| 163 | - if (tag == 0 || !skipField(tag, output)) { | ||
| 164 | + if (tag == 0) { | ||
| 165 | + return; | ||
| 166 | + } | ||
| 167 | + checkRecursionLimit(); | ||
| 168 | + ++recursionDepth; | ||
| 169 | + boolean fieldSkipped = skipField(tag, output); | ||
| 170 | + --recursionDepth; | ||
| 171 | + if (!fieldSkipped) { | ||
| 172 | return; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | @@ -2180,7 +2208,14 @@ public abstract class CodedInputStream { | ||
| 176 | public void skipMessage() throws IOException { | ||
| 177 | while (true) { | ||
| 178 | final int tag = readTag(); | ||
| 179 | - if (tag == 0 || !skipField(tag)) { | ||
| 180 | + if (tag == 0) { | ||
| 181 | + return; | ||
| 182 | + } | ||
| 183 | + checkRecursionLimit(); | ||
| 184 | + ++recursionDepth; | ||
| 185 | + boolean fieldSkipped = skipField(tag); | ||
| 186 | + --recursionDepth; | ||
| 187 | + if (!fieldSkipped) { | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | @@ -2190,7 +2225,14 @@ public abstract class CodedInputStream { | ||
| 192 | public void skipMessage(CodedOutputStream output) throws IOException { | ||
| 193 | while (true) { | ||
| 194 | final int tag = readTag(); | ||
| 195 | - if (tag == 0 || !skipField(tag, output)) { | ||
| 196 | + if (tag == 0) { | ||
| 197 | + return; | ||
| 198 | + } | ||
| 199 | + checkRecursionLimit(); | ||
| 200 | + ++recursionDepth; | ||
| 201 | + boolean fieldSkipped = skipField(tag, output); | ||
| 202 | + --recursionDepth; | ||
| 203 | + if (!fieldSkipped) { | ||
| 204 | return; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | @@ -3298,7 +3340,14 @@ public abstract class CodedInputStream { | ||
| 208 | public void skipMessage() throws IOException { | ||
| 209 | while (true) { | ||
| 210 | final int tag = readTag(); | ||
| 211 | - if (tag == 0 || !skipField(tag)) { | ||
| 212 | + if (tag == 0) { | ||
| 213 | + return; | ||
| 214 | + } | ||
| 215 | + checkRecursionLimit(); | ||
| 216 | + ++recursionDepth; | ||
| 217 | + boolean fieldSkipped = skipField(tag); | ||
| 218 | + --recursionDepth; | ||
| 219 | + if (!fieldSkipped) { | ||
| 220 | return; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | @@ -3308,7 +3357,14 @@ public abstract class CodedInputStream { | ||
| 224 | public void skipMessage(CodedOutputStream output) throws IOException { | ||
| 225 | while (true) { | ||
| 226 | final int tag = readTag(); | ||
| 227 | - if (tag == 0 || !skipField(tag, output)) { | ||
| 228 | + if (tag == 0) { | ||
| 229 | + return; | ||
| 230 | + } | ||
| 231 | + checkRecursionLimit(); | ||
| 232 | + ++recursionDepth; | ||
| 233 | + boolean fieldSkipped = skipField(tag, output); | ||
| 234 | + --recursionDepth; | ||
| 235 | + if (!fieldSkipped) { | ||
| 236 | return; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java | ||
| 240 | index de3890f70..5ad6762b0 100644 | ||
| 241 | --- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java | ||
| 242 | +++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java | ||
| 243 | @@ -3006,7 +3006,8 @@ final class MessageSchema<T> implements Schema<T> { | ||
| 244 | unknownFields = unknownFieldSchema.getBuilderFromMessage(message); | ||
| 245 | } | ||
| 246 | // Unknown field. | ||
| 247 | - if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { | ||
| 248 | + if (unknownFieldSchema.mergeOneFieldFrom( | ||
| 249 | + unknownFields, reader, /* currentDepth= */ 0)) { | ||
| 250 | continue; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | @@ -3381,7 +3382,8 @@ final class MessageSchema<T> implements Schema<T> { | ||
| 254 | if (unknownFields == null) { | ||
| 255 | unknownFields = unknownFieldSchema.getBuilderFromMessage(message); | ||
| 256 | } | ||
| 257 | - if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { | ||
| 258 | + if (!unknownFieldSchema.mergeOneFieldFrom( | ||
| 259 | + unknownFields, reader, /* currentDepth= */ 0)) { | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | break; | ||
| 263 | @@ -3397,7 +3399,8 @@ final class MessageSchema<T> implements Schema<T> { | ||
| 264 | if (unknownFields == null) { | ||
| 265 | unknownFields = unknownFieldSchema.getBuilderFromMessage(message); | ||
| 266 | } | ||
| 267 | - if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { | ||
| 268 | + if (!unknownFieldSchema.mergeOneFieldFrom( | ||
| 269 | + unknownFields, reader, /* currentDepth= */ 0)) { | ||
| 270 | return; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java | ||
| 274 | index eec3acd35..ec37d41f9 100644 | ||
| 275 | --- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java | ||
| 276 | +++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java | ||
| 277 | @@ -278,7 +278,7 @@ final class MessageSetSchema<T> implements Schema<T> { | ||
| 278 | reader, extension, extensionRegistry, extensions); | ||
| 279 | return true; | ||
| 280 | } else { | ||
| 281 | - return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader); | ||
| 282 | + return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader, /* currentDepth= */ 0); | ||
| 283 | } | ||
| 284 | } else { | ||
| 285 | return reader.skipField(); | ||
| 286 | diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java | ||
| 287 | index c4ec645bf..0cdecd30e 100644 | ||
| 288 | --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java | ||
| 289 | +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java | ||
| 290 | @@ -13,6 +13,11 @@ import java.io.IOException; | ||
| 291 | @CheckReturnValue | ||
| 292 | abstract class UnknownFieldSchema<T, B> { | ||
| 293 | |||
| 294 | + static final int DEFAULT_RECURSION_LIMIT = 100; | ||
| 295 | + | ||
| 296 | + @SuppressWarnings("NonFinalStaticField") | ||
| 297 | + private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT; | ||
| 298 | + | ||
| 299 | /** Whether unknown fields should be dropped. */ | ||
| 300 | abstract boolean shouldDiscardUnknownFields(Reader reader); | ||
| 301 | |||
| 302 | @@ -56,7 +61,8 @@ abstract class UnknownFieldSchema<T, B> { | ||
| 303 | abstract void makeImmutable(Object message); | ||
| 304 | |||
| 305 | /** Merges one field into the unknown fields. */ | ||
| 306 | - final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException { | ||
| 307 | + final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth) | ||
| 308 | + throws IOException { | ||
| 309 | int tag = reader.getTag(); | ||
| 310 | int fieldNumber = WireFormat.getTagFieldNumber(tag); | ||
| 311 | switch (WireFormat.getTagWireType(tag)) { | ||
| 312 | @@ -75,7 +81,12 @@ abstract class UnknownFieldSchema<T, B> { | ||
| 313 | case WireFormat.WIRETYPE_START_GROUP: | ||
| 314 | final B subFields = newBuilder(); | ||
| 315 | int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); | ||
| 316 | - mergeFrom(subFields, reader); | ||
| 317 | + currentDepth++; | ||
| 318 | + if (currentDepth >= recursionLimit) { | ||
| 319 | + throw InvalidProtocolBufferException.recursionLimitExceeded(); | ||
| 320 | + } | ||
| 321 | + mergeFrom(subFields, reader, currentDepth); | ||
| 322 | + currentDepth--; | ||
| 323 | if (endGroupTag != reader.getTag()) { | ||
| 324 | throw InvalidProtocolBufferException.invalidEndTag(); | ||
| 325 | } | ||
| 326 | @@ -88,10 +99,11 @@ abstract class UnknownFieldSchema<T, B> { | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | - final void mergeFrom(B unknownFields, Reader reader) throws IOException { | ||
| 331 | + final void mergeFrom(B unknownFields, Reader reader, int currentDepth) | ||
| 332 | + throws IOException { | ||
| 333 | while (true) { | ||
| 334 | if (reader.getFieldNumber() == Reader.READ_DONE | ||
| 335 | - || !mergeOneFieldFrom(unknownFields, reader)) { | ||
| 336 | + || !mergeOneFieldFrom(unknownFields, reader, currentDepth)) { | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | @@ -108,4 +120,12 @@ abstract class UnknownFieldSchema<T, B> { | ||
| 341 | abstract int getSerializedSizeAsMessageSet(T message); | ||
| 342 | |||
| 343 | abstract int getSerializedSize(T unknowns); | ||
| 344 | + | ||
| 345 | + /** | ||
| 346 | + * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if | ||
| 347 | + * the depth of the message exceeds this limit. | ||
| 348 | + */ | ||
| 349 | + public void setRecursionLimit(int limit) { | ||
| 350 | + recursionLimit = limit; | ||
| 351 | + } | ||
| 352 | } | ||
| 353 | diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java | ||
| 354 | index 2de3273e3..19a6b669d 100644 | ||
| 355 | --- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java | ||
| 356 | +++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java | ||
| 357 | @@ -10,6 +10,10 @@ package com.google.protobuf; | ||
| 358 | import static com.google.common.truth.Truth.assertThat; | ||
| 359 | import static com.google.common.truth.Truth.assertWithMessage; | ||
| 360 | import static org.junit.Assert.assertArrayEquals; | ||
| 361 | +import static org.junit.Assert.assertThrows; | ||
| 362 | + | ||
| 363 | +import com.google.common.primitives.Bytes; | ||
| 364 | +import map_test.MapTestProto.MapContainer; | ||
| 365 | import protobuf_unittest.UnittestProto.BoolMessage; | ||
| 366 | import protobuf_unittest.UnittestProto.Int32Message; | ||
| 367 | import protobuf_unittest.UnittestProto.Int64Message; | ||
| 368 | @@ -34,6 +38,13 @@ public class CodedInputStreamTest { | ||
| 369 | |||
| 370 | private static final int DEFAULT_BLOCK_SIZE = 4096; | ||
| 371 | |||
| 372 | + private static final int GROUP_TAP = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP); | ||
| 373 | + | ||
| 374 | + private static final byte[] NESTING_SGROUP = generateSGroupTags(); | ||
| 375 | + | ||
| 376 | + private static final byte[] NESTING_SGROUP_WITH_INITIAL_BYTES = generateSGroupTagsForMapField(); | ||
| 377 | + | ||
| 378 | + | ||
| 379 | private enum InputType { | ||
| 380 | ARRAY { | ||
| 381 | @Override | ||
| 382 | @@ -116,6 +127,17 @@ public class CodedInputStreamTest { | ||
| 383 | return bytes; | ||
| 384 | } | ||
| 385 | |||
| 386 | + private static byte[] generateSGroupTags() { | ||
| 387 | + byte[] bytes = new byte[100000]; | ||
| 388 | + Arrays.fill(bytes, (byte) GROUP_TAP); | ||
| 389 | + return bytes; | ||
| 390 | + } | ||
| 391 | + | ||
| 392 | + private static byte[] generateSGroupTagsForMapField() { | ||
| 393 | + byte[] initialBytes = {18, 1, 75, 26, (byte) 198, (byte) 154, 12}; | ||
| 394 | + return Bytes.concat(initialBytes, NESTING_SGROUP); | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | /** | ||
| 398 | * An InputStream which limits the number of bytes it reads at a time. We use this to make sure | ||
| 399 | * that CodedInputStream doesn't screw up when reading in small blocks. | ||
| 400 | @@ -659,6 +681,143 @@ public class CodedInputStreamTest { | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | + @Test | ||
| 405 | + public void testMaliciousRecursion_unknownFields() throws Exception { | ||
| 406 | + Throwable thrown = | ||
| 407 | + assertThrows( | ||
| 408 | + InvalidProtocolBufferException.class, | ||
| 409 | + () -> TestRecursiveMessage.parseFrom(NESTING_SGROUP)); | ||
| 410 | + | ||
| 411 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 412 | + } | ||
| 413 | + | ||
| 414 | + @Test | ||
| 415 | + public void testMaliciousRecursion_skippingUnknownField() throws Exception { | ||
| 416 | + Throwable thrown = | ||
| 417 | + assertThrows( | ||
| 418 | + InvalidProtocolBufferException.class, | ||
| 419 | + () -> | ||
| 420 | + DiscardUnknownFieldsParser.wrap(TestRecursiveMessage.parser()) | ||
| 421 | + .parseFrom(NESTING_SGROUP)); | ||
| 422 | + | ||
| 423 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 424 | + } | ||
| 425 | + | ||
| 426 | + @Test | ||
| 427 | + public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception { | ||
| 428 | + Throwable parseFromThrown = | ||
| 429 | + assertThrows( | ||
| 430 | + InvalidProtocolBufferException.class, | ||
| 431 | + () -> | ||
| 432 | + MapContainer.parseFrom( | ||
| 433 | + new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES))); | ||
| 434 | + Throwable mergeFromThrown = | ||
| 435 | + assertThrows( | ||
| 436 | + InvalidProtocolBufferException.class, | ||
| 437 | + () -> | ||
| 438 | + MapContainer.newBuilder() | ||
| 439 | + .mergeFrom(new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES))); | ||
| 440 | + | ||
| 441 | + assertThat(parseFromThrown) | ||
| 442 | + .hasMessageThat() | ||
| 443 | + .contains("Protocol message had too many levels of nesting"); | ||
| 444 | + assertThat(mergeFromThrown) | ||
| 445 | + .hasMessageThat() | ||
| 446 | + .contains("Protocol message had too many levels of nesting"); | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + @Test | ||
| 450 | + public void testMaliciousSGroupTags_inputStream_skipMessage() throws Exception { | ||
| 451 | + ByteArrayInputStream inputSteam = new ByteArrayInputStream(NESTING_SGROUP); | ||
| 452 | + CodedInputStream input = CodedInputStream.newInstance(inputSteam); | ||
| 453 | + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); | ||
| 454 | + | ||
| 455 | + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); | ||
| 456 | + Throwable thrown2 = | ||
| 457 | + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); | ||
| 458 | + | ||
| 459 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 460 | + assertThat(thrown2) | ||
| 461 | + .hasMessageThat() | ||
| 462 | + .contains("Protocol message had too many levels of nesting"); | ||
| 463 | + } | ||
| 464 | + | ||
| 465 | + @Test | ||
| 466 | + public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception { | ||
| 467 | + Throwable parseFromThrown = | ||
| 468 | + assertThrows( | ||
| 469 | + InvalidProtocolBufferException.class, | ||
| 470 | + () -> MapContainer.parseFrom(NESTING_SGROUP_WITH_INITIAL_BYTES)); | ||
| 471 | + Throwable mergeFromThrown = | ||
| 472 | + assertThrows( | ||
| 473 | + InvalidProtocolBufferException.class, | ||
| 474 | + () -> MapContainer.newBuilder().mergeFrom(NESTING_SGROUP_WITH_INITIAL_BYTES)); | ||
| 475 | + | ||
| 476 | + assertThat(parseFromThrown) | ||
| 477 | + .hasMessageThat() | ||
| 478 | + .contains("the input ended unexpectedly in the middle of a field"); | ||
| 479 | + assertThat(mergeFromThrown) | ||
| 480 | + .hasMessageThat() | ||
| 481 | + .contains("the input ended unexpectedly in the middle of a field"); | ||
| 482 | + } | ||
| 483 | + | ||
| 484 | + @Test | ||
| 485 | + public void testMaliciousSGroupTags_arrayDecoder_skipMessage() throws Exception { | ||
| 486 | + CodedInputStream input = CodedInputStream.newInstance(NESTING_SGROUP); | ||
| 487 | + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); | ||
| 488 | + | ||
| 489 | + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); | ||
| 490 | + Throwable thrown2 = | ||
| 491 | + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); | ||
| 492 | + | ||
| 493 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 494 | + assertThat(thrown2) | ||
| 495 | + .hasMessageThat() | ||
| 496 | + .contains("Protocol message had too many levels of nesting"); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + @Test | ||
| 500 | + public void testMaliciousSGroupTagsWithMapField_fromByteBuffer() throws Exception { | ||
| 501 | + Throwable thrown = | ||
| 502 | + assertThrows( | ||
| 503 | + InvalidProtocolBufferException.class, | ||
| 504 | + () -> MapContainer.parseFrom(ByteBuffer.wrap(NESTING_SGROUP_WITH_INITIAL_BYTES))); | ||
| 505 | + | ||
| 506 | + assertThat(thrown) | ||
| 507 | + .hasMessageThat() | ||
| 508 | + .contains("the input ended unexpectedly in the middle of a field"); | ||
| 509 | + } | ||
| 510 | + | ||
| 511 | + @Test | ||
| 512 | + public void testMaliciousSGroupTags_byteBuffer_skipMessage() throws Exception { | ||
| 513 | + CodedInputStream input = InputType.NIO_DIRECT.newDecoder(NESTING_SGROUP); | ||
| 514 | + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); | ||
| 515 | + | ||
| 516 | + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); | ||
| 517 | + Throwable thrown2 = | ||
| 518 | + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); | ||
| 519 | + | ||
| 520 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 521 | + assertThat(thrown2) | ||
| 522 | + .hasMessageThat() | ||
| 523 | + .contains("Protocol message had too many levels of nesting"); | ||
| 524 | + } | ||
| 525 | + | ||
| 526 | + @Test | ||
| 527 | + public void testMaliciousSGroupTags_iterableByteBuffer() throws Exception { | ||
| 528 | + CodedInputStream input = InputType.ITER_DIRECT.newDecoder(NESTING_SGROUP); | ||
| 529 | + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); | ||
| 530 | + | ||
| 531 | + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); | ||
| 532 | + Throwable thrown2 = | ||
| 533 | + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); | ||
| 534 | + | ||
| 535 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 536 | + assertThat(thrown2) | ||
| 537 | + .hasMessageThat() | ||
| 538 | + .contains("Protocol message had too many levels of nesting"); | ||
| 539 | + } | ||
| 540 | + | ||
| 541 | private void checkSizeLimitExceeded(InvalidProtocolBufferException e) { | ||
| 542 | assertThat(e) | ||
| 543 | .hasMessageThat() | ||
| 544 | diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java | ||
| 545 | index 754ed7d5f..81be90bfd 100644 | ||
| 546 | --- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java | ||
| 547 | +++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java | ||
| 548 | @@ -2459,6 +2459,211 @@ public class LiteTest { | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | + @Test | ||
| 553 | + public void testParseFromInputStream_concurrent_nestingUnknownGroups() throws Exception { | ||
| 554 | + int numThreads = 200; | ||
| 555 | + ArrayList<Thread> threads = new ArrayList<>(); | ||
| 556 | + | ||
| 557 | + ByteString byteString = generateNestingGroups(99); | ||
| 558 | + AtomicBoolean thrown = new AtomicBoolean(false); | ||
| 559 | + | ||
| 560 | + for (int i = 0; i < numThreads; i++) { | ||
| 561 | + Thread thread = | ||
| 562 | + new Thread( | ||
| 563 | + () -> { | ||
| 564 | + try { | ||
| 565 | + TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString); | ||
| 566 | + } catch (IOException e) { | ||
| 567 | + if (e.getMessage().contains("Protocol message had too many levels of nesting")) { | ||
| 568 | + thrown.set(true); | ||
| 569 | + } | ||
| 570 | + } | ||
| 571 | + }); | ||
| 572 | + thread.start(); | ||
| 573 | + threads.add(thread); | ||
| 574 | + } | ||
| 575 | + | ||
| 576 | + for (Thread thread : threads) { | ||
| 577 | + thread.join(); | ||
| 578 | + } | ||
| 579 | + | ||
| 580 | + assertThat(thrown.get()).isFalse(); | ||
| 581 | + } | ||
| 582 | + | ||
| 583 | + @Test | ||
| 584 | + public void testParseFromInputStream_nestingUnknownGroups() throws IOException { | ||
| 585 | + ByteString byteString = generateNestingGroups(99); | ||
| 586 | + | ||
| 587 | + Throwable thrown = | ||
| 588 | + assertThrows( | ||
| 589 | + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); | ||
| 590 | + assertThat(thrown) | ||
| 591 | + .hasMessageThat() | ||
| 592 | + .doesNotContain("Protocol message had too many levels of nesting"); | ||
| 593 | + } | ||
| 594 | + | ||
| 595 | + @Test | ||
| 596 | + public void testParseFromInputStream_nestingUnknownGroups_exception() throws IOException { | ||
| 597 | + ByteString byteString = generateNestingGroups(100); | ||
| 598 | + | ||
| 599 | + Throwable thrown = | ||
| 600 | + assertThrows( | ||
| 601 | + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); | ||
| 602 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + @Test | ||
| 606 | + public void testParseFromInputStream_setRecursionLimit_exception() throws IOException { | ||
| 607 | + ByteString byteString = generateNestingGroups(199); | ||
| 608 | + UnknownFieldSchema<?, ?> schema = SchemaUtil.unknownFieldSetLiteSchema(); | ||
| 609 | + schema.setRecursionLimit(200); | ||
| 610 | + | ||
| 611 | + Throwable thrown = | ||
| 612 | + assertThrows( | ||
| 613 | + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); | ||
| 614 | + assertThat(thrown) | ||
| 615 | + .hasMessageThat() | ||
| 616 | + .doesNotContain("Protocol message had too many levels of nesting"); | ||
| 617 | + schema.setRecursionLimit(UnknownFieldSchema.DEFAULT_RECURSION_LIMIT); | ||
| 618 | + } | ||
| 619 | + | ||
| 620 | + @Test | ||
| 621 | + public void testParseFromBytes_concurrent_nestingUnknownGroups() throws Exception { | ||
| 622 | + int numThreads = 200; | ||
| 623 | + ArrayList<Thread> threads = new ArrayList<>(); | ||
| 624 | + | ||
| 625 | + ByteString byteString = generateNestingGroups(99); | ||
| 626 | + AtomicBoolean thrown = new AtomicBoolean(false); | ||
| 627 | + | ||
| 628 | + for (int i = 0; i < numThreads; i++) { | ||
| 629 | + Thread thread = | ||
| 630 | + new Thread( | ||
| 631 | + () -> { | ||
| 632 | + try { | ||
| 633 | + // Should pass in byte[] instead of ByteString to go into ArrayDecoders. | ||
| 634 | + TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString.toByteArray()); | ||
| 635 | + } catch (InvalidProtocolBufferException e) { | ||
| 636 | + if (e.getMessage().contains("Protocol message had too many levels of nesting")) { | ||
| 637 | + thrown.set(true); | ||
| 638 | + } | ||
| 639 | + } | ||
| 640 | + }); | ||
| 641 | + thread.start(); | ||
| 642 | + threads.add(thread); | ||
| 643 | + } | ||
| 644 | + | ||
| 645 | + for (Thread thread : threads) { | ||
| 646 | + thread.join(); | ||
| 647 | + } | ||
| 648 | + | ||
| 649 | + assertThat(thrown.get()).isFalse(); | ||
| 650 | + } | ||
| 651 | + | ||
| 652 | + @Test | ||
| 653 | + public void testParseFromBytes_nestingUnknownGroups() throws IOException { | ||
| 654 | + ByteString byteString = generateNestingGroups(99); | ||
| 655 | + | ||
| 656 | + Throwable thrown = | ||
| 657 | + assertThrows( | ||
| 658 | + InvalidProtocolBufferException.class, | ||
| 659 | + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); | ||
| 660 | + assertThat(thrown) | ||
| 661 | + .hasMessageThat() | ||
| 662 | + .doesNotContain("Protocol message had too many levels of nesting"); | ||
| 663 | + } | ||
| 664 | + | ||
| 665 | + @Test | ||
| 666 | + public void testParseFromBytes_nestingUnknownGroups_exception() throws IOException { | ||
| 667 | + ByteString byteString = generateNestingGroups(100); | ||
| 668 | + | ||
| 669 | + Throwable thrown = | ||
| 670 | + assertThrows( | ||
| 671 | + InvalidProtocolBufferException.class, | ||
| 672 | + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); | ||
| 673 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 674 | + } | ||
| 675 | + | ||
| 676 | + @Test | ||
| 677 | + public void testParseFromBytes_setRecursionLimit_exception() throws IOException { | ||
| 678 | + ByteString byteString = generateNestingGroups(199); | ||
| 679 | + ArrayDecoders.setRecursionLimit(200); | ||
| 680 | + | ||
| 681 | + Throwable thrown = | ||
| 682 | + assertThrows( | ||
| 683 | + InvalidProtocolBufferException.class, | ||
| 684 | + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); | ||
| 685 | + assertThat(thrown) | ||
| 686 | + .hasMessageThat() | ||
| 687 | + .doesNotContain("Protocol message had too many levels of nesting"); | ||
| 688 | + ArrayDecoders.setRecursionLimit(ArrayDecoders.DEFAULT_RECURSION_LIMIT); | ||
| 689 | + } | ||
| 690 | + | ||
| 691 | + @Test | ||
| 692 | + public void testParseFromBytes_recursiveMessages() throws Exception { | ||
| 693 | + byte[] data99 = makeRecursiveMessage(99).toByteArray(); | ||
| 694 | + byte[] data100 = makeRecursiveMessage(100).toByteArray(); | ||
| 695 | + | ||
| 696 | + RecursiveMessage unused = RecursiveMessage.parseFrom(data99); | ||
| 697 | + Throwable thrown = | ||
| 698 | + assertThrows( | ||
| 699 | + InvalidProtocolBufferException.class, () -> RecursiveMessage.parseFrom(data100)); | ||
| 700 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 701 | + } | ||
| 702 | + | ||
| 703 | + @Test | ||
| 704 | + public void testParseFromBytes_recursiveKnownGroups() throws Exception { | ||
| 705 | + byte[] data99 = makeRecursiveGroup(99).toByteArray(); | ||
| 706 | + byte[] data100 = makeRecursiveGroup(100).toByteArray(); | ||
| 707 | + | ||
| 708 | + RecursiveGroup unused = RecursiveGroup.parseFrom(data99); | ||
| 709 | + Throwable thrown = | ||
| 710 | + assertThrows(InvalidProtocolBufferException.class, () -> RecursiveGroup.parseFrom(data100)); | ||
| 711 | + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); | ||
| 712 | + } | ||
| 713 | + | ||
| 714 | + @Test | ||
| 715 | + @SuppressWarnings("ProtoParseFromByteString") | ||
| 716 | + public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception { | ||
| 717 | + ByteString byteString = generateNestingGroups(102); | ||
| 718 | + | ||
| 719 | + Throwable parseFromThrown = | ||
| 720 | + assertThrows( | ||
| 721 | + InvalidProtocolBufferException.class, | ||
| 722 | + () -> MapContainer.parseFrom(byteString.toByteArray())); | ||
| 723 | + Throwable mergeFromThrown = | ||
| 724 | + assertThrows( | ||
| 725 | + InvalidProtocolBufferException.class, | ||
| 726 | + () -> MapContainer.newBuilder().mergeFrom(byteString.toByteArray())); | ||
| 727 | + | ||
| 728 | + assertThat(parseFromThrown) | ||
| 729 | + .hasMessageThat() | ||
| 730 | + .contains("Protocol message had too many levels of nesting"); | ||
| 731 | + assertThat(mergeFromThrown) | ||
| 732 | + .hasMessageThat() | ||
| 733 | + .contains("Protocol message had too many levels of nesting"); | ||
| 734 | + } | ||
| 735 | + | ||
| 736 | + @Test | ||
| 737 | + public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception { | ||
| 738 | + byte[] bytes = generateNestingGroups(101).toByteArray(); | ||
| 739 | + | ||
| 740 | + Throwable parseFromThrown = | ||
| 741 | + assertThrows( | ||
| 742 | + InvalidProtocolBufferException.class, | ||
| 743 | + () -> MapContainer.parseFrom(new ByteArrayInputStream(bytes))); | ||
| 744 | + Throwable mergeFromThrown = | ||
| 745 | + assertThrows( | ||
| 746 | + InvalidProtocolBufferException.class, | ||
| 747 | + () -> MapContainer.newBuilder().mergeFrom(new ByteArrayInputStream(bytes))); | ||
| 748 | + | ||
| 749 | + assertThat(parseFromThrown) | ||
| 750 | + .hasMessageThat() | ||
| 751 | + .contains("Protocol message had too many levels of nesting"); | ||
| 752 | + assertThat(mergeFromThrown) | ||
| 753 | + .hasMessageThat() | ||
| 754 | + .contains("Protocol message had too many levels of nesting"); | ||
| 755 | + } | ||
| 756 | + | ||
| 757 | @Test | ||
| 758 | public void testParseFromByteBuffer_extensions() throws Exception { | ||
| 759 | TestAllExtensionsLite message = | ||
| 760 | @@ -2815,4 +3020,31 @@ public class LiteTest { | ||
| 761 | } | ||
| 762 | return false; | ||
| 763 | } | ||
| 764 | + | ||
| 765 | + private static ByteString generateNestingGroups(int num) throws IOException { | ||
| 766 | + int groupTap = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP); | ||
| 767 | + ByteString.Output byteStringOutput = ByteString.newOutput(); | ||
| 768 | + CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput); | ||
| 769 | + for (int i = 0; i < num; i++) { | ||
| 770 | + codedOutput.writeInt32NoTag(groupTap); | ||
| 771 | + } | ||
| 772 | + codedOutput.flush(); | ||
| 773 | + return byteStringOutput.toByteString(); | ||
| 774 | + } | ||
| 775 | + | ||
| 776 | + private static RecursiveMessage makeRecursiveMessage(int num) { | ||
| 777 | + if (num == 0) { | ||
| 778 | + return RecursiveMessage.getDefaultInstance(); | ||
| 779 | + } else { | ||
| 780 | + return RecursiveMessage.newBuilder().setRecurse(makeRecursiveMessage(num - 1)).build(); | ||
| 781 | + } | ||
| 782 | + } | ||
| 783 | + | ||
| 784 | + private static RecursiveGroup makeRecursiveGroup(int num) { | ||
| 785 | + if (num == 0) { | ||
| 786 | + return RecursiveGroup.getDefaultInstance(); | ||
| 787 | + } else { | ||
| 788 | + return RecursiveGroup.newBuilder().setRecurse(makeRecursiveGroup(num - 1)).build(); | ||
| 789 | + } | ||
| 790 | + } | ||
| 791 | } | ||
| 792 | -- | ||
| 793 | 2.25.1 | ||
| 794 | |||
diff --git a/meta-oe/recipes-devtools/protobuf/protobuf_4.25.3.bb b/meta-oe/recipes-devtools/protobuf/protobuf_4.25.8.bb index acc35db4a5..949a3b207b 100644 --- a/meta-oe/recipes-devtools/protobuf/protobuf_4.25.3.bb +++ b/meta-oe/recipes-devtools/protobuf/protobuf_4.25.8.bb | |||
| @@ -10,12 +10,11 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=37b5762e07f0af8c74ce80a8bda4266b" | |||
| 10 | DEPENDS = "zlib abseil-cpp" | 10 | DEPENDS = "zlib abseil-cpp" |
| 11 | DEPENDS:append:class-target = " protobuf-native" | 11 | DEPENDS:append:class-target = " protobuf-native" |
| 12 | 12 | ||
| 13 | SRCREV = "4a2aef570deb2bfb8927426558701e8bfc26f2a4" | 13 | SRCREV = "a4cbdd3ed0042e8f9b9c30e8b0634096d9532809" |
| 14 | 14 | ||
| 15 | SRC_URI = "gitsm://github.com/protocolbuffers/protobuf.git;branch=25.x;protocol=https \ | 15 | SRC_URI = "gitsm://github.com/protocolbuffers/protobuf.git;branch=25.x;protocol=https \ |
| 16 | file://run-ptest \ | 16 | file://run-ptest \ |
| 17 | file://0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch \ | 17 | file://0001-examples-Makefile-respect-CXX-LDFLAGS-variables-fix-.patch \ |
| 18 | file://0001-Add-recursion-check-when-parsing-unknown-fields-in-J.patch \ | ||
| 19 | " | 18 | " |
| 20 | SRC_URI:append:mips:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch " | 19 | SRC_URI:append:mips:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch " |
| 21 | SRC_URI:append:mipsel:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch " | 20 | SRC_URI:append:mipsel:toolchain-clang = " file://0001-Fix-build-on-mips-clang.patch " |
