This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
PATCH: Bounds checking in FD_SET; JDK conformance for java.net.Socket
- From: Jeff Sturm <jsturm at one-point dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Fri, 14 Jun 2002 09:37:07 -0400 (EDT)
- Subject: PATCH: Bounds checking in FD_SET; JDK conformance for java.net.Socket
While debugging servlet code I discovered a socket example that will
sometimes crash libgcj:
Socket s = new Socket("localhost", 80);
InputStream is = s.getInputStream();
s.close();
s.setSoTimeout(100);
is.read();
The read() method sees fnum == -1 and timeout == 100, so tries to FD_SET
with a bad fd. The FD_SET man page warns about undefined behavior for
negative values, or values greather than FD_SETSIZE. Likely
consequences include triggering an exception, aborting the program or
corrupting the stack, etc.
Presumably we should never reach select() in the example above. (The
JDK doesn't, it throws a SocketException in setSoTimeout.) This patch
matches the JDK's behavior on setSoTimeout and adds a safeguard to FD_SET.
(On Solaris FD_SETSIZE defaults to 1024. It's conceivable that some code
could exceed that with a valid fd. I'm not sure if anything better can be
done than just ignoring the timeout in that case.)
Tested on alpha-linux.
2002-06-14 Jeff Sturm <jsturm@one-point.com>
* java/net/natPlainDatagramSocketImpl.cc (receive):
Check bounds of argument to FD_SET.
(setOption): Throw exception if socket is closed.
* java/net/natPlainSocketImpl.cc (accept, read):
Check bounds of argument to FD_SET.
(setOption): Throw exception if socket is closed.
Index: java/net/natPlainDatagramSocketImpl.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/natPlainDatagramSocketImpl.cc,v
retrieving revision 1.37
diff -u -p -r1.37 natPlainDatagramSocketImpl.cc
--- java/net/natPlainDatagramSocketImpl.cc 15 Apr 2002 03:21:00 -0000 1.37
+++ java/net/natPlainDatagramSocketImpl.cc 14 Jun 2002 04:24:05 -0000
@@ -361,7 +361,7 @@ java::net::PlainDatagramSocketImpl::rece
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select since SO_RCVTIMEO is not always available.
- if (timeout > 0)
+ if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rset;
struct timeval tv;
@@ -500,6 +500,9 @@ java::net::PlainDatagramSocketImpl::setO
{
int val;
socklen_t val_len = sizeof (val);
+
+ if (fnum < 0)
+ throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
if (_Jv_IsInstanceOf (value, &BooleanClass))
{
Index: java/net/natPlainSocketImpl.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/natPlainSocketImpl.cc,v
retrieving revision 1.41
diff -u -p -r1.41 natPlainSocketImpl.cc
--- java/net/natPlainSocketImpl.cc 2 May 2002 17:33:59 -0000 1.41
+++ java/net/natPlainSocketImpl.cc 14 Jun 2002 04:24:09 -0000
@@ -369,7 +369,7 @@ java::net::PlainSocketImpl::accept (java
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select since SO_RCVTIMEO is not always available.
- if (timeout > 0)
+ if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rset;
struct timeval tv;
@@ -516,7 +516,7 @@ java::net::PlainSocketImpl::read(void)
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select.
- if (timeout > 0)
+ if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
// Create the file descriptor set.
fd_set read_fds;
@@ -575,7 +575,7 @@ java::net::PlainSocketImpl::read(jbyteAr
// FIXME: implement timeout support for Win32
#ifndef WIN32
// Do timeouts via select.
- if (timeout > 0)
+ if (timeout > 0 && fnum >= 0 && fnum < FD_SETSIZE)
{
// Create the file descriptor set.
fd_set read_fds;
@@ -662,6 +662,7 @@ java::net::PlainSocketImpl::available(vo
#if defined(HAVE_SELECT)
if (! num_set)
+ if (! num_set && fnum >= 0 && fnum < FD_SETSIZE)
{
fd_set rd;
FD_ZERO (&rd);
@@ -688,6 +689,9 @@ java::net::PlainSocketImpl::setOption (j
{
int val;
socklen_t val_len = sizeof (val);
+
+ if (fnum < 0)
+ throw new java::net::SocketException (JvNewStringUTF ("Socket closed"));
if (_Jv_IsInstanceOf (value, &java::lang::Boolean::class$))
{