From 690ba9cdc7d1803e7929ee704afc7330744dc0a5 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 24 Apr 2014 15:10:35 -0600 Subject: [PATCH] Stop using *Critical functions in throwIOException This was a bug, wherein upon throwing an exception, we would try to allocate memory for the message - all while holding a critical reference to the jbyteArray representing the exception string. This caused an expect to fail in allocate3. --- classpath/java-nio.cpp | 15 ++++++++++----- src/avian/machine.h | 1 + test/Sockets.java | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 test/Sockets.java diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index d75727922e..ab57d80483 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -115,12 +115,17 @@ throwIOException(JNIEnv* e, const char* s) throwNew(e, "java/io/IOException", s); } -void -throwIOException(JNIEnv* e, jbyteArray a) +void throwIOException(JNIEnv* e, jbyteArray a) { - jbyte* s = static_cast(e->GetPrimitiveArrayCritical(a, 0)); - throwIOException(e, reinterpret_cast(s)); - e->ReleasePrimitiveArrayCritical(a, s, 0); + size_t length = e->GetArrayLength(a); + uint8_t* buf = static_cast(allocate(e, length)); + if (buf) { + e->GetByteArrayRegion(a, 0, length, reinterpret_cast(buf)); + throwIOException(e, reinterpret_cast(buf)); + free(buf); + } else { + return; + } } void diff --git a/src/avian/machine.h b/src/avian/machine.h index 5197185b71..38d2d85b88 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1841,6 +1841,7 @@ allocate(Thread* t, unsigned sizeInBytes, bool objectMask) { return allocate2(t, sizeInBytes, objectMask); } else { + assert(t, t->criticalLevel == 0); return allocateSmall(t, sizeInBytes); } } diff --git a/test/Sockets.java b/test/Sockets.java new file mode 100644 index 0000000000..9bce0e036e --- /dev/null +++ b/test/Sockets.java @@ -0,0 +1,33 @@ +import java.net.SocketAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; +import java.io.IOException; + +public class Sockets { + private static void expect(boolean v) { + if (! v) throw new RuntimeException(); + } + + public static void testFailedBind() throws Exception { + final String Hostname = "localhost"; + final int Port = 22046; // hopefully this port is unused + final SocketAddress Address = new InetSocketAddress(Hostname, Port); + final byte[] Message = "hello, world!".getBytes(); + + SocketChannel out = SocketChannel.open(); + try { + try { + out.connect(Address); + expect(false); + } catch(IOException e) { + // We're good. This previously triggered a vm assert, rather than an exception + } + } finally { + out.close(); + } + } + + public static void main(String[] args) throws Exception { + testFailedBind(); + } +}