You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What version of protobuf and what language are you using?
Version: v3.13.0
Language: C#
What operating system (Linux, Windows, ...) and version?
Reproducible on any version
What runtime / compiler are you using (e.g., python version or gcc version)
.NET Core
What did you do?
There is a problem with the deserialization of Int32 field when it contains a negative value. This happens only on very specific circumstances - when the field is serialized across the buffer (span) boundaries (when it starts at the and of one span and continues at the beginning of the next span). Deserialization thinks that the whole field fits to the first span, but this is not true and after deserialization, the buffer pointer is beyond the buffer size.
What did you expect to see
Successful deserialization of the message on the client
What did you see instead?
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Google.Protobuf.ParsingPrimitives.ReadRawByte(ReadOnlySpan1& buffer, ParserInternalState& state) at Google.Protobuf.ParsingPrimitives.ParseRawVarint32SlowPath(ReadOnlySpan1& buffer, ParserInternalState& state)
at Google.Protobuf.ParsingPrimitivesWrappers.ReadUInt32WrapperSlow(ReadOnlySpan1& buffer, ParserInternalState& state) at Google.Protobuf.ParsingPrimitivesWrappers.ReadInt32Wrapper(ReadOnlySpan1& buffer, ParserInternalState& state)
Details
This is the code for int32 serialization. Negative values are serialized as Varint64, it can be 11 bytes long.
public static void WriteInt32(ref Span buffer, ref WriterInternalState state, int value)
{
if (value >= 0)
{
WriteRawVarint32(ref buffer, ref state, (uint)value);
}
else
{
// Must sign-extend.
WriteRawVarint64(ref buffer, ref state, (ulong)value);
}
}
But deserialization do not count with this. ReadUInt32Wrapper function has this condition there:
// length:1 + tag:1 + value:5(varint32-max) = 7 bytes
if (state.bufferPos + 7 <= state.bufferSize)
{
// The entire wrapper message is already contained in buffer.
... which is not true for negative values.
The text was updated successfully, but these errors were encountered:
jtattermusch
changed the title
[CSharp] Wrong deserialization of Int32 for negative values
C#: Wrong deserialization of Int32Value (from wrappers.proto) for negative values when segment boundary is crossed
Nov 13, 2020
What version of protobuf and what language are you using?
Version: v3.13.0
Language: C#
What operating system (Linux, Windows, ...) and version?
Reproducible on any version
What runtime / compiler are you using (e.g., python version or gcc version)
.NET Core
What did you do?
There is a problem with the deserialization of Int32 field when it contains a negative value. This happens only on very specific circumstances - when the field is serialized across the buffer (span) boundaries (when it starts at the and of one span and continues at the beginning of the next span). Deserialization thinks that the whole field fits to the first span, but this is not true and after deserialization, the buffer pointer is beyond the buffer size.
What did you expect to see
Successful deserialization of the message on the client
What did you see instead?
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Google.Protobuf.ParsingPrimitives.ReadRawByte(ReadOnlySpan
1& buffer, ParserInternalState& state) at Google.Protobuf.ParsingPrimitives.ParseRawVarint32SlowPath(ReadOnlySpan
1& buffer, ParserInternalState& state)at Google.Protobuf.ParsingPrimitivesWrappers.ReadUInt32WrapperSlow(ReadOnlySpan
1& buffer, ParserInternalState& state) at Google.Protobuf.ParsingPrimitivesWrappers.ReadInt32Wrapper(ReadOnlySpan
1& buffer, ParserInternalState& state)Details
This is the code for int32 serialization. Negative values are serialized as Varint64, it can be 11 bytes long.
But deserialization do not count with this. ReadUInt32Wrapper function has this condition there:
... which is not true for negative values.
The text was updated successfully, but these errors were encountered: