This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] ada/35953: Guard against empty buffers and end-of-connection
- From: Samuel Tardieu <sam at rfc1149 dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 16 Apr 2008 18:25:29 +0200
- Subject: [PATCH] ada/35953: Guard against empty buffers and end-of-connection
In Read for Stream_Socket_Stream_Type, if the connection was closed by
the peer before all the requested data has been received, Last was set to
Item'First - 1 (as returned by Receive_Socket) instead of the index of the
latest received byte. This patch fixes this.
It also removes network-related system calls when a Read or Write of length
0 is requested. Although GNAT will not generate such calls while expanding
Read/Write/Input/Output attributes, the user may directly call Read and
Write on sockets stream types through dispatching.
The reason for an unsuccessful Write is also given: either "connection
closed by peer" or "packet too large for datagram".
gcc/ada/
PR ada/35953
* g-socket.adb (Read, Write): Do not send or attempt to receive
empty buffers. Do not set Last to a bogus value if the connection
is closed by the peer during the operation.
Tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu with PolyORB (as
well as other submitted GNAT.Sockets patches). Ok for trunk?
---
gcc/ada/g-socket.adb | 64 +++++++++++++++++++++++++++++---------------------
1 files changed, 37 insertions(+), 27 deletions(-)
diff --git a/gcc/ada/g-socket.adb b/gcc/ada/g-socket.adb
index 18abfa8..97eea82 100644
--- a/gcc/ada/g-socket.adb
+++ b/gcc/ada/g-socket.adb
@@ -1348,11 +1348,17 @@ package body GNAT.Sockets is
Last : out Ada.Streams.Stream_Element_Offset)
is
begin
- Receive_Socket
- (Stream.Socket,
- Item,
- Last,
- Stream.From);
+ if Item'First <= Item'Last then
+ Receive_Socket
+ (Stream.Socket,
+ Item,
+ Last,
+ Stream.From);
+ else
+ -- Do nothing if the receiving buffer is empty
+
+ Last := Item'First - 1;
+ end if;
end Read;
----------
@@ -1367,19 +1373,21 @@ package body GNAT.Sockets is
pragma Warnings (Off, Stream);
First : Ada.Streams.Stream_Element_Offset := Item'First;
- Index : Ada.Streams.Stream_Element_Offset := First - 1;
Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
+ Index : Ada.Streams.Stream_Element_Offset;
begin
- loop
+ Last := First - 1;
+ while First <= Max loop
Receive_Socket (Stream.Socket, Item (First .. Max), Index);
- Last := Index;
- -- Exit when all or zero data received. Zero means that the socket
- -- peer is closed.
+ -- Zero elements means that the peer has closed the connection
- exit when Index < First or else Index = Max;
+ if Index < First then
+ return;
+ end if;
+ Last := Index;
First := Index + 1;
end loop;
end Read;
@@ -2107,14 +2115,16 @@ package body GNAT.Sockets is
Last : Ada.Streams.Stream_Element_Offset;
begin
- Send_Socket
- (Stream.Socket,
- Item,
- Last,
- Stream.To);
+ if Item'First <= Item'Last then
+ Send_Socket
+ (Stream.Socket,
+ Item,
+ Last,
+ Stream.To);
- if Last /= Item'Last then
- raise Socket_Error;
+ if Last /= Item'Last then
+ raise Socket_Error with "packet too large for datagram";
+ end if;
end if;
end Write;
@@ -2129,24 +2139,24 @@ package body GNAT.Sockets is
pragma Warnings (Off, Stream);
First : Ada.Streams.Stream_Element_Offset := Item'First;
- Index : Ada.Streams.Stream_Element_Offset := First - 1;
Max : constant Ada.Streams.Stream_Element_Offset := Item'Last;
+ Index : Ada.Streams.Stream_Element_Offset;
begin
- loop
+ -- Loop until all data has been sent
+
+ while First <= Max loop
Send_Socket (Stream.Socket, Item (First .. Max), Index);
- -- Exit when all or zero data sent. Zero means that the socket has
- -- been closed by peer.
+ -- Zero elements sent means that the peer closed its
+ -- receiving end.
- exit when Index < First or else Index = Max;
+ if Index < First then
+ raise Socket_Error with "connection closed by peer";
+ end if;
First := Index + 1;
end loop;
-
- if Index /= Max then
- raise Socket_Error;
- end if;
end Write;
end GNAT.Sockets;