Fix parsing negative Int32Value that crosses segment boundary
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index 1fb3bb5..0ad286f 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -344,6 +344,25 @@
}
[Test]
+ public void ReadInt32Wrapper_VariableBlockSizes()
+ {
+ byte[] rawBytes = new byte[] { 202, 1, 11, 8, 254, 255, 255, 255, 255, 255, 255, 255, 255, 1 };
+
+ for (int blockSize = 1; blockSize <= rawBytes.Length; blockSize++)
+ {
+ ReadOnlySequence<byte> data = ReadOnlySequenceFactory.CreateWithContent(rawBytes, blockSize);
+ AssertReadFromParseContext(data, (ref ParseContext ctx) =>
+ {
+ ctx.ReadTag();
+
+ var value = ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx);
+
+ Assert.AreEqual(-2, value);
+ }, true);
+ }
+ }
+
+ [Test]
public void ReadHugeBlob()
{
// Allocate and initialize a 1MB blob.
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
index 1263064..629ec32 100644
--- a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
+++ b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
@@ -160,8 +160,11 @@
internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
{
- // length:1 + tag:1 + value:5(varint32-max) = 7 bytes
- if (state.bufferPos + 7 <= state.bufferSize)
+ // field=1, type=varint = tag of 8
+ const int expectedTag = 8;
+ // length:1 + tag:1 + value:10(varint64-max) = 12 bytes
+ // Value can be 64 bits for negative integers
+ if (state.bufferPos + 12 <= state.bufferSize)
{
// The entire wrapper message is already contained in `buffer`.
int pos0 = state.bufferPos;
@@ -177,8 +180,7 @@
return ReadUInt32WrapperSlow(ref buffer, ref state);
}
int finalBufferPos = state.bufferPos + length;
- // field=1, type=varint = tag of 8
- if (buffer[state.bufferPos++] != 8)
+ if (buffer[state.bufferPos++] != expectedTag)
{
state.bufferPos = pos0;
return ReadUInt32WrapperSlow(ref buffer, ref state);