Add missing calls to ReleaseByteArrayElements.
Without this fix, the two new tests cause the VM to abort like this:
W/dalvikvm( 386): ReferenceTable overflow (max=1024)
W/dalvikvm( 386): Last 10 entries in JNI pinned array reference table:
W/dalvikvm( 386): 1014: 0x4038e018 cls=[B (1044 bytes)
W/dalvikvm( 386): 1015: 0x4038e430 cls=[B (1044 bytes)
W/dalvikvm( 386): 1016: 0x4038e848 cls=[B (1044 bytes)
W/dalvikvm( 386): 1017: 0x4038ec60 cls=[B (1044 bytes)
W/dalvikvm( 386): 1018: 0x4038f078 cls=[B (1044 bytes)
W/dalvikvm( 386): 1019: 0x4038f490 cls=[B (1044 bytes)
W/dalvikvm( 386): 1020: 0x4038f8a8 cls=[B (1044 bytes)
W/dalvikvm( 386): 1021: 0x4038fcc0 cls=[B (1044 bytes)
W/dalvikvm( 386): 1022: 0x403900d8 cls=[B (1044 bytes)
W/dalvikvm( 386): 1023: 0x403904f0 cls=[B (1044 bytes)
W/dalvikvm( 386): JNI pinned array reference table summary (1024 entries):
W/dalvikvm( 386): 1024 of [B 1044B (1024 unique)
W/dalvikvm( 386): Memory held directly by native code is 1069056 bytes
E/dalvikvm( 386): Failed adding to JNI pinned array ref table (1024 entries)
I/dalvikvm( 386): "main" prio=5 tid=3 RUNNABLE
I/dalvikvm( 386): | group="main" sCount=0 dsCount=0 s=N obj=0x4001e2b8 self=0xb488
I/dalvikvm( 386): | sysTid=386 nice=0 sched=0/0 cgrp=default handle=-1344005452
I/dalvikvm( 386): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeinit(Native Method)
I/dalvikvm( 386): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.init(OpenSSLSocketImpl.java:126)
I/dalvikvm( 386): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.<init>(OpenSSLSocketImpl.java:158)
I/dalvikvm( 386): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl.createSocket(OpenSSLSocketFactoryImpl.java:61)
I/dalvikvm( 386): at tests.api.javax.net.ssl.SSLSocketTest.test_creationStressTest(SSLSocketTest.java:359)
...
Tested on sapphire-eng.
No bug; found by inspection when investigating bug 1639287.
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
index 13a1e61..bb5e3b7 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
@@ -87,9 +87,9 @@
// 'seed == null' when no SecureRandom Object is set
// in the SSLContext.
if (seed != NULL) {
- jboolean iscopy = JNI_FALSE;
- jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+ jbyte* randseed = env->GetByteArrayElements(seed, NULL);
RAND_seed((unsigned char*) randseed, 1024);
+ env->ReleaseByteArrayElements(seed, randseed, 0);
} else {
RAND_load_file("/dev/urandom", 1024);
}
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 87f2af3..1b0feeb 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -989,9 +989,9 @@
// 'seed == null' when no SecureRandom Object is set
// in the SSLContext.
if (seed != NULL) {
- jboolean iscopy = JNI_FALSE;
- jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+ jbyte* randseed = env->GetByteArrayElements(seed, NULL);
RAND_seed((unsigned char*) randseed, 1024);
+ env->ReleaseByteArrayElements(seed, randseed, 0);
} else {
RAND_load_file("/dev/urandom", 1024);
}
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
index 3c1fb2e..c4bae0a 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
@@ -32,6 +32,7 @@
import java.io.InputStream;
import java.net.InetAddress;
import java.security.KeyStore;
+import java.security.SecureRandom;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -585,4 +586,26 @@
.createServerSocket();
return sss;
}
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Guard against native resource leakage.",
+ method = "SSLSocket",
+ args = {}
+ )
+ public void test_creationStressTest() throws Exception {
+ KeyManager[] keyManagers = getKeyManagers();
+ // Test the default codepath, which uses /dev/urandom.
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, null, null);
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getServerSocketFactory().createServerSocket();
+ }
+
+ // Test the other codepath, which copies a seed from a byte[].
+ sslContext.init(keyManagers, null, new SecureRandom());
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getServerSocketFactory().createServerSocket();
+ }
+ }
}
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
index 5e39cb1..13a0e59 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
@@ -26,6 +26,7 @@
import java.net.*;
import java.security.KeyStore;
+import java.security.SecureRandom;
import java.lang.String;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -336,6 +337,27 @@
}
}
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Guard against native resource leakage.",
+ method = "SSLSocket",
+ args = {}
+ )
+ public void test_creationStressTest() throws Exception {
+ // Test the default codepath, which uses /dev/urandom.
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, null, null);
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getSocketFactory().createSocket();
+ }
+
+ // Test the other codepath, which copies a seed from a byte[].
+ sslContext.init(null, null, new SecureRandom());
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getSocketFactory().createSocket();
+ }
+ }
+
/**
* @throws IOException
* @tests javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener listener)