This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]