pizheng / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

DeserializeWithLengthPrefix misbehaves with NetworkStream sources #155

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
NetworkStream is backed by a Socket and calling NetworkStream.Receive 
requesting 0 bytes on an open connection will not return immediately but will 
instead block until another byte is available.

If the read loop in ProtoReader.Ensure was reworked to never request a 0 byte 
read from `source' the issue would go away.

Code that causes an issue:
listener = new Socket (AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp);
listener.Bind (new IPEndPoint (IPAddress.Any, 8500));
listener.Listen (5);
async = listener.BeginAccept (null, null);
sender = new Socket (AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp);
sender.Connect (new IPEndPoint (IPAddress.Loopback, 8500));
send = new NetworkStream (sender);
receiver = listener.EndAccept (async);
receive = new NetworkStream (receiver);
Serializer.SerializeWithLengthPrefix<endpoint_info> (send, obj_in, 
PrefixStyle.Base128);
obj_out = Serializer.DeserializeWithLengthPrefix<endpoint_info> (receive, 
PrefixStyle.Base128);

Code that works around the issue:
listener = new Socket (AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp);
listener.Bind (new IPEndPoint (IPAddress.Any, 8500));
listener.Listen (5);
async = listener.BeginAccept (null, null);
sender = new Socket (AddressFamily.InterNetwork, SocketType.Stream, 
ProtocolType.Tcp);
sender.Connect (new IPEndPoint (IPAddress.Loopback, 8500));
send = new NetworkStream (sender);
receiver = listener.EndAccept (async);
receive = new NetworkStream (receiver);
Serializer.SerializeWithLengthPrefix<endpoint_info> (send, obj_in, 
PrefixStyle.Base128);
send.WriteByte (0);
obj_out = Serializer.DeserializeWithLengthPrefix<endpoint_info> (receive, 
PrefixStyle.Base128);
receive.ReadByte ();

Notice that simply putting another byte in the stream fixes the deadlock.

Original issue reported on code.google.com by clemah...@gmail.com on 9 Feb 2011 at 7:24

GoogleCodeExporter commented 9 years ago
I'm a little confused here; it should already not attempt to read past the 
expected length; I'll take a look... from the ProtoReader, it sounds like this 
is v2 code, yes?

Original comment by marc.gravell on 9 Feb 2011 at 9:08

GoogleCodeExporter commented 9 years ago
Yes, that is definitely a bug; reproduced

Original comment by marc.gravell on 9 Feb 2011 at 9:12

GoogleCodeExporter commented 9 years ago
Patch is line 189:

while (count > 0 && canRead > 0 && (bytesRead = source.Read(ioBuffer, writePos, 
canRead)) > 0)

Original comment by marc.gravell on 9 Feb 2011 at 9:22